sbs20 / scanservjs

SANE scanner nodejs web ui
https://sbs20.github.io/scanservjs/
GNU General Public License v2.0
757 stars 145 forks source link

AIRSCAN_DEVICES - sed: couldn't open temporary file Permission denied #352

Closed rourke closed 2 years ago

rourke commented 3 years ago

I'm trying to add my Canon Pixma TS5150 scanner. It is not connected by USB to my server running Ubuntu Server 20.04, so I'm connecting to sane-airscan. I know the string for my device should be:

"Canon TS5150" = http://192.168.1.24:80/eSCL/

So I've added this environmental variable to my docker run command:

AIRSCAN_DEVICES='"Canon TS5150" = http://192.168.1.24:80/eSCL/'

But the logs keep returning:

sed -i "/^\[devices\]/a $device" /etc/sane.d/airscan.conf
sed: couldn't open temporary file /etc/sane.d/sed1IIthM: Permission denied

When I run the container without this env variable, and bash into the container I could do some more investigation.

scanservjs@e37e13c9492e:/app$ sed -i "/^\[devices\]/a test" /etc/sane.d/airscan.conf
sed: couldn't open temporary file /etc/sane.d/sed1IIthM: Permission denied

scanservjs@e37e13c9492e:/app$ ls -lsa /etc/sane.d                                              
total 352
8 drwxr-xr-x 1 root       root       4096 Aug 28 15:23 .
8 drwxr-xr-x 1 root       root       4096 Sep  3 21:00 ..
4 -rw-r--r-- 1 root       root         25 Mar 23  2019 abaton.conf
4 -rw-r--r-- 1 root       root         14 Mar 23  2019 agfafocus.conf
4 -rw-r--r-- 1 scanservjs scanservjs 3197 Jun 19 11:03 airscan.conf
4 -rw-r--r-- 1 root       root         24 Mar 23  2019 apple.conf
4 -rw-r--r-- 1 root       root         26 Mar 23  2019 artec.conf
8 -rw-r--r-- 1 root       root       4140 Mar 23  2019 artec_eplus48u.conf
4 -rw-r--r-- 1 root       root        548 Mar 23  2019 avision.conf
4 -rw-r--r-- 1 root       root         29 Mar 23  2019 bh.conf
4 -rw-r--r-- 1 root       root         26 Mar 23  2019 canon.conf
4 -rw-r--r-- 1 root       root        193 Mar 23  2019 canon630u.conf
4 -rw-r--r-- 1 root       root       3961 Mar 23  2019 canon_dr.conf
4 -rw-r--r-- 1 root       root       1160 Mar 23  2019 canon_pp.conf
4 -rw-r--r-- 1 root       root        552 Mar 23  2019 cardscan.conf
4 -rw-r--r-- 1 root       root         34 Mar 23  2019 coolscan.conf
4 -rw-r--r-- 1 root       root        754 Mar 23  2019 coolscan2.conf
4 -rw-r--r-- 1 root       root        754 Mar 23  2019 coolscan3.conf
4 -rw-r--r-- 1 root       root        984 Mar 23  2019 dc210.conf
4 -rw-r--r-- 1 root       root        984 Mar 23  2019 dc240.conf
4 -rw-r--r-- 1 root       root        704 Mar 23  2019 dc25.conf
4 -rw-r--r-- 1 root       root        492 Mar 23  2019 dell1600n_net.conf
4 -rw-r--r-- 1 root       root       1088 Mar 23  2019 dll.conf
4 drwxr-xr-x 2 root       root       4096 Aug 28 15:22 dll.d
4 -rw-r--r-- 1 root       root         12 Mar 23  2019 dmc.conf
4 -rw-r--r-- 1 root       root       2736 Mar 23  2019 epjitsu.conf
4 -rw-r--r-- 1 root       root        793 Mar 23  2019 epson.conf
4 -rw-r--r-- 1 root       root        376 Mar 23  2019 epson2.conf
4 -rw-r--r-- 1 root       root        271 Mar 23  2019 epsonds.conf
4 -rw-r--r-- 1 root       root       3404 Mar 23  2019 fujitsu.conf
4 -rw-r--r-- 1 root       root       2008 Mar 23  2019 genesys.conf
4 -rw-r--r-- 1 root       root       1149 Mar 23  2019 gphoto2.conf
8 -rw-r--r-- 1 root       root       7792 Mar 23  2019 gt68xx.conf
4 -rw-r--r-- 1 root       root        497 Mar 23  2019 hp.conf
4 -rw-r--r-- 1 root       root        396 Mar 23  2019 hp3900.conf
4 -rw-r--r-- 1 root       root         76 Mar 23  2019 hp4200.conf
4 -rw-r--r-- 1 root       root        238 Mar 23  2019 hp5400.conf
4 -rw-r--r-- 1 root       root         22 Mar 23  2019 hpsj5s.conf
4 -rw-r--r-- 1 root       root         24 Mar 23  2019 hs2p.conf
4 -rw-r--r-- 1 root       root         38 Mar 23  2019 ibm.conf
4 -rw-r--r-- 1 root       root        367 Mar 23  2019 kodak.conf
4 -rw-r--r-- 1 root       root       2599 Mar 23  2019 kodakaio.conf
4 -rw-r--r-- 1 root       root         39 Mar 23  2019 kvs1025.conf
4 -rw-r--r-- 1 root       root        113 Mar 23  2019 leo.conf
4 -rw-r--r-- 1 root       root        119 Mar 23  2019 lexmark.conf
4 -rw-r--r-- 1 root       root        187 Mar 23  2019 ma1509.conf
4 -rw-r--r-- 1 root       root       1254 Mar 23  2019 magicolor.conf
4 -rw-r--r-- 1 root       root        666 Mar 23  2019 matsushita.conf
4 -rw-r--r-- 1 root       root        268 Mar 23  2019 microtek.conf
4 -rw-r--r-- 1 root       root        279 Mar 23  2019 microtek2.conf
4 -rw-r--r-- 1 root       root       2125 Mar 23  2019 mustek.conf
4 -rw-r--r-- 1 root       root       3824 Mar 23  2019 mustek_pp.conf
4 -rw-r--r-- 1 root       root        809 Mar 23  2019 mustek_usb.conf
4 -rw-r--r-- 1 root       root         13 Mar 23  2019 nec.conf
4 -rw-r--r-- 1 scanservjs scanservjs  586 Sep  3 21:00 net.conf
4 -rw-r--r-- 1 root       root        365 Mar 23  2019 p5.conf
4 -rw-r--r-- 1 root       root         75 Mar 23  2019 pie.conf
4 -rw-r--r-- 1 root       root        554 Mar 23  2019 pieusb.conf
4 -rw-r--r-- 1 root       root        985 Mar 23  2019 pixma.conf
8 -rw-r--r-- 1 root       root       4142 Mar 23  2019 plustek.conf
4 -rw-r--r-- 1 root       root        943 Mar 23  2019 plustek_pp.conf
4 -rw-r--r-- 1 root       root        391 Mar 23  2019 qcam.conf
4 -rw-r--r-- 1 root       root         29 Mar 23  2019 ricoh.conf
4 -rw-r--r-- 1 root       root        183 Mar 23  2019 rts8891.conf
4 -rw-r--r-- 1 root       root         13 Mar 23  2019 s9036.conf
4 -rw-r--r-- 1 root       root       1052 Mar 23  2019 saned.conf
4 -rw-r--r-- 1 root       root         48 Mar 23  2019 sceptre.conf
4 -rw-r--r-- 1 root       root       1464 Mar 23  2019 sharp.conf
4 -rw-r--r-- 1 root       root        115 Mar 23  2019 sm3840.conf
4 -rw-r--r-- 1 root       root       2239 Mar 23  2019 snapscan.conf
4 -rw-r--r-- 1 root       root         10 Mar 23  2019 sp15c.conf
4 -rw-r--r-- 1 root       root       2224 Mar 23  2019 st400.conf
4 -rw-r--r-- 1 root       root        178 Mar 23  2019 stv680.conf
4 -rw-r--r-- 1 root       root         28 Mar 23  2019 tamarack.conf
4 -rw-r--r-- 1 root       root        355 Mar 23  2019 teco1.conf
4 -rw-r--r-- 1 root       root        636 Mar 23  2019 teco2.conf
4 -rw-r--r-- 1 root       root        217 Mar 23  2019 teco3.conf
4 -rw-r--r-- 1 root       root       1807 Mar 23  2019 test.conf
4 -rw-r--r-- 1 root       root       1495 Mar 23  2019 u12.conf
4 -rw-r--r-- 1 root       root       3094 Mar 23  2019 umax.conf
4 -rw-r--r-- 1 root       root        386 Mar 23  2019 umax1220u.conf
4 -rw-r--r-- 1 root       root       1684 Mar 23  2019 umax_pp.conf
4 -rw-r--r-- 1 root       root       3917 Mar 23  2019 xerox_mfp.conf

scanservjs@e37e13c9492e:/app$ id
uid=2001(scanservjs) gid=2001(scanservjs) groups=2001(scanservjs)

So the sed command cannot be executed as user 2001(scanservjs) because it's trying to create a temporary file inside the /etc/sane.d folder, which is owned by root:root.

I've tried running the container as root:root, and this does write the correct string to airscan.conf. But when I try to do a airscan-discover -d (with debugging) I get another error: MDNS: avahi_client_new failed: Access denied.

I've read the documentation over and over, but it's late, so I might've missed it. Hope someone has a solution.

rourke commented 3 years ago

I don't have an automated solution for the editing of the airscan.conf file, but I did find this:

root@e37e13c9492e:/app# scanimage -L

No scanners were identified. If you were expecting something different,
check that the scanner is plugged in, turned on and detected by the
sane-find-scanner tool (if appropriate). Please read the documentation
which came with this software (README, FAQ, manpages).

root@e37e13c9492e:/app# service --status-all
 [ - ]  dbus
 [ ? ]  hwclock.sh
 [ - ]  saned
 [ + ]  udev
 [ - ]  x11-common

root@e37e13c9492e:/app# service dbus start
[ ok ] Removing stale PID file /var/run/dbus/pid..
[ ok ] Starting system message bus: dbus.

root@e37e13c9492e:/app# scanimage -L
device `airscan:e0:Canon TS5150' is a eSCL Canon TS5150 ip=192.168.1.24

So with just starting the dbus service it finds my Canon scanner. So current questions:

  1. Is it possible to change the airscan devices with the current version of scanservjs?
  2. Isn't the dbus service supposed to start somewhere? Is it something in my configuration?
sbs20 commented 3 years ago

Hi. I'm sorry for the very slow reply. And thank you for sharing the problem and your investigations.

Is it possible to change the airscan devices with the current version of scanservjs?

I was sure that I had tested the airscan change (hence the change of owner here) - however, it doesn't seem to work for you and I haven't tested recently enough to know if that's something specific to your setup or a wider issue. I will look into it.

Isn't the dbus service supposed to start somewhere? Is it something in my configuration?

Hmm - quite possibly. I only have the rather lame excuse that it works for me. Would you be prepared to try and build your own Docker container from the Dockerfile, check it fails, and then add a line to start the dbus service and check it works?

rourke commented 3 years ago

Hi! No worries. I'm quite happy you taking the time to help me out. It's no problem to build a container from the Dockerfile. I won't have time for that for the next few hours, but I will get back to you on that.

sbs20 commented 3 years ago

No hurry for me - real life keeps getting in the way of me doing this!

rourke commented 3 years ago

I thought I could do this, but it seems I don't have enough experience with building from scratch. Could you tell me the best/easiest way to do this?

I've done this in a separate (empty) directory:

git clone https://github.com/sbs20/scanservjs.git
docker build -t scanservjs_custom .

All steps succeed, so I follow up by:

docker run -d \
  -p 8080:8080 \
  -e AIRSCAN_DEVICES='"Canon TS5150"=http://192.168.1.24:80/eSCL/' \
  -v /var/run/dbus:/var/run/dbus \
  --restart unless-stopped \
  --name scanservjs-container \
  9e593d503a22

9e593d503a22 is the image ID I just built. docker logs -ft scanservjs-container is empty. docker exec -it scanservjs-container /bin/bash returns Error response from daemon: Container d0d75b6bfaad4cd054fbd806e5af50960f3f6882f392658cf6329b422cb966ca is restarting, wait until the container is running. What am I doing wrong?

sbs20 commented 3 years ago

Not sure. Rather than use a hash, I usually just use the image name but I doubt that's it.

My guess is that the container is throwing an error and docker is attempting to restart it. You could try removing --restart unless-stopped and see if that helps with the logs.

Alternatively, instead of running the container, you can shell into the image and attempt to manually run stuff there to see where it goes wrong:

# Shell inside image
docker run -it --entrypoint=/bin/bash scanservjs_custom
rourke commented 3 years ago

When I run that and so a export AIRSCAN_DEVICES='"Canon TS5150"=http://192.168.1.24:80/eSCL/' (and confirm it with an echo $AIRSCAN_DEVICES), and execute run.sh it gives the same Permission denied error.

So I mounted the config file which already has my scanner configured:

docker run -it --publish 8080:8080 --entrypoint=/bin/bash --volume /home/user/apps/scanservjs/airscan.conf:/etc/sane.d/airscan.conf scanservjs_custom

And then if I execute run.sh again I get:

scanservjs@40a83a397e58:/app$ /run.sh

# Test using the following form:
# export SANED_NET_HOSTS="a|b" AIRSCAN_DEVICES="c|d" DELIMITER="|"; ./run.sh

# turn off globbing
set -f
+ set -f

# split at newlines only (airscan devices can have spaces in)
IFS='
'
+ IFS=

# Get a custom delimiter but default to ;
DELIMITER=${DELIMITER:-;}
+ DELIMITER=;

# Insert a list of net hosts
if [ ! -z "$SANED_NET_HOSTS" ]; then
  hosts=$(echo $SANED_NET_HOSTS | sed "s/$DELIMITER/\n/")
  for host in $hosts; do
    echo $host >> /etc/sane.d/net.conf
  done
fi
+ [ ! -z  ]

# Insert airscan devices
if [ ! -z "$AIRSCAN_DEVICES" ]; then
  devices=$(echo $AIRSCAN_DEVICES | sed "s/$DELIMITER/\n/")
  for device in $devices; do
    sed -i "/^\[devices\]/a $device" /etc/sane.d/airscan.conf
  done
fi
+ [ ! -z  ]

unset IFS
+ unset IFS
set +f
+ set +f

node ./server/server.js
+ node ./server/server.js
[2021-09-07T10:26:45.133Z] INFO (server): Started
[2021-09-07T10:26:51.778Z] DEBUG (Http): request:  { method: 'GET', path: '/context' }
[2021-09-07T10:26:51.787Z] DEBUG (Devices): devices.json does not exist. Reloading
[2021-09-07T10:26:51.787Z] DEBUG (Devices): Config.devices:  []
[2021-09-07T10:26:56.169Z] DEBUG (Devices): Device list:
No scanners were identified. If you were expecting something different,
check that the scanner is plugged in, turned on and detected by the
sane-find-scanner tool (if appropriate). Please read the documentation
which came with this software (README, FAQ, manpages).

[2021-09-07T10:26:56.205Z] DEBUG (Http): request:  { method: 'POST', path: '/preview' }
[2021-09-07T10:26:56.206Z] DEBUG (Devices): devices.json contains no devices. Reloading
[2021-09-07T10:26:56.206Z] DEBUG (Devices): Config.devices:  []
[2021-09-07T10:27:00.584Z] DEBUG (Devices): Device list:
No scanners were identified. If you were expecting something different,
check that the scanner is plugged in, turned on and detected by the
sane-find-scanner tool (if appropriate). Please read the documentation
which came with this software (README, FAQ, manpages).

So now I want to adjust the Dockerfile (I assume) to start the dbus service. But this needs to be done by root user. I don't believe a RUN command will do, and CMD command just gets attached to the entrypoint as an argument right? So how would I be able to run the service dbus start command as root at the start of the container?

sbs20 commented 3 years ago

So how would I be able to run the service dbus start command as root at the start of the container?

That is a good question. I think you're right. The more I deal with Docker for this project, the more I come to the conclusion that the hardware integration part of it (i.e. interfacing with the scanner) should be on the host, not in the container. The container should not run as root, but it needs to to make this work.

Are you able to make this work if you setup the airscan on the host and then connect to to it over the network from the container?

rourke commented 3 years ago

I prefer to keep as much containerized as possible which allows me to quickly change setups and software, or recover from a backup, but I guess there are some limitations here.

Are you able to make this work if you setup the airscan on the host and then connect to to it over the network from the container?

When I first was aware of scanservjs I didn't quite get all the tools (saned, sane-airscan, ipp-usb, etc.), how they were supposed to work together, and what the minimum tools were to make it work for me. I still don't to be honest. So what I did at first was install all kinds of tools on my host which I thought were necessary according to different documentations. I figured some devices needed to be available or installed on the host, and passed through to the container.

But at one point it dawned to me your docker image might already have all the tools needed. So I thought I'd get your container to work first and then uninstall all the tools I've unnecessarily installed on my host later.

So before working with your container I was at one point trying to make my host see my scanner over the network. If I look at the current state of my host now with regards to my scanner:

$ scanimage -L

No scanners were identified. If you were expecting something different,
check that the scanner is plugged in, turned on and detected by the
sane-find-scanner tool (if appropriate). Please read the documentation
which came with this software (README, FAQ, manpages).
$ airscan-discover -d
MDNS: avahi_client_new failed: Daemon not running
[devices]
$ sudo systemctl status avahi-daemon.service
● avahi-daemon.service - Avahi mDNS/DNS-SD Stack
     Loaded: loaded (/lib/systemd/system/avahi-daemon.service; enabled; vendor preset: enabled)
     Active: failed (Result: exit-code) since Tue 2021-09-07 12:11:38 UTC; 6min ago
TriggeredBy: ● avahi-daemon.socket
    Process: 1141827 ExecStart=/usr/sbin/avahi-daemon -s (code=exited, status=255/EXCEPTION)
   Main PID: 1141827 (code=exited, status=255/EXCEPTION)
     Status: "avahi-daemon 0.7 exiting."

Sep 07 12:11:38 ownserver systemd[1]: Starting Avahi mDNS/DNS-SD Stack...
Sep 07 12:11:38 ownserver avahi-daemon[1141827]: Found user 'avahi' (UID 114) and group 'avahi' (GID 119).
Sep 07 12:11:38 ownserver avahi-daemon[1141827]: Successfully dropped root privileges.
Sep 07 12:11:38 ownserver avahi-daemon[1141827]: avahi-daemon 0.7 starting up.
Sep 07 12:11:38 ownserver avahi-daemon[1141827]: dbus_bus_get_private(): Failed to connect to socket /var/run/dbus/system_bus_socket: Connection refused
Sep 07 12:11:38 ownserver avahi-daemon[1141827]: WARNING: Failed to contact D-Bus daemon.
Sep 07 12:11:38 ownserver avahi-daemon[1141827]: avahi-daemon 0.7 exiting.
Sep 07 12:11:38 ownserver systemd[1]: avahi-daemon.service: Main process exited, code=exited, status=255/EXCEPTION
Sep 07 12:11:38 ownserver systemd[1]: avahi-daemon.service: Failed with result 'exit-code'.
Sep 07 12:11:38 ownserver systemd[1]: Failed to start Avahi mDNS/DNS-SD Stack.

Not sure how to continue from here. I'm way out of my league with this, but I'm always willing to challenge myself.

By the way, if this becomes an issue out of scope for scanservjs, just let me know.

shawly commented 3 years ago

I also got this error

sed -i "/^\[devices\]/a $device" /etc/sane.d/airscan.conf
sed: couldn't open temporary file /etc/sane.d/sed1IIthM: Permission denied

Since the script probably runs in userland the issue is that /etc/sane.d/ is not writable for the script since it is owned by root, hence it can not add a line to the airscan.conf

As a temporary fix I started the container with the root user (--user="root" parameter for CLI or just user: root for compose) and now it can find my scanner and I can use it.

rourke commented 3 years ago

That turns out to be my working trick as well. I'm running the container as root, which allows the airscan.conf file to be adjusted. But I also mount an adjusted run.sh which contains service dbus start. Even though this is a workaround, I'm perfectly fine with it. Thanks for all the help.

sbs20 commented 3 years ago

Re opening because I want to keep track of a better long term solution.

sbs20 commented 2 years ago

I'm hoping that the new staging image (yet to be promoted) requires no manual intervention for you.

docker pull sbs20/scanservjs:staging
michaeldeng1993 commented 2 years ago

I was running into the same permission issues on sed as well, and I can confirm that I'm no longer seeing the same issue after pulling the staging image sbs20/scanservjs:staging.