4

Edit -- So it turns out that this line is the culprit . /lib/lsb/init-functions

If I comment out that line then the commands are actually able to run. Why would this be? I'm able to source this file in my other init scripts with no issues.

So I have a script that I've place in /etc/init.d and run update-rc.d on. I can run this using sudo /etc/init.d/usbstorage start, and I get a message saying that is has started, but none of the commands have any effect. I can check this by putting simple commands like

echo "here here maytee" > /home/pi/some_file.txt"

in the script, and after running it that file does not exist. Part of the script is posted below for reference.

#! /bin/sh
### BEGIN INIT INFO
# Provides:          usbstorage
# Required-Start:    $local_fs
# Required-Stop:
# Default-Start:     S
# Default-Stop:      0 6
# Short-Description: Automounts external storage if found.
### END INIT INFO

PATH=/sbin:/bin

. /lib/lsb/init-functions

do_start () {
    umount /dev/sda1 2> /dev/null || echo "sda1 not already mounted"
    mkdir /mnt/usbstorage 2> /dev/null || echo "/mnt/usbstorage already exists"
    mount /dev/sda1 /mnt/usbstorage
    chown -R pi:pi /mnt/usbstorage
    echo "Started usbstorage"
}
do_stop () {
    umount /dev/sda1 || echo "sda1 not already mounted"
}

case "$1" in
  start)
        do_start
        ;;
  restart|reload|force-reload)
    do_stop || echo 1
    do_start
        ;;
  stop|status)
        # No-op
        ;;
  *)
        echo "Usage: $0 start|stop" >&2
        exit 3
        ;;
esac

why do the commands refuse to run? It's almost like something is failing silently in the beginning .

--- Edit

So I ran the following:

sudo -i 
bash -x /etc/init.d/usbstorage start

and got this output

[ ok ] Starting usbstorage (via systemctl): usbstorage.service.
root@johns-box:~# bash -x /etc/init.d/usbstorage start
+ PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
+ . /lib/lsb/init-functions
+++ run-parts --lsbsysinit --list /lib/lsb/init-functions.d
++ for hook in '$(run-parts --lsbsysinit --list /lib/lsb/init-functions.d 2>/dev/null)'
++ '[' -r /lib/lsb/init-functions.d/20-left-info-blocks ']'
++ . /lib/lsb/init-functions.d/20-left-info-blocks
++ for hook in '$(run-parts --lsbsysinit --list /lib/lsb/init-functions.d 2>/dev/null)'
++ '[' -r /lib/lsb/init-functions.d/40-systemd ']'
++ . /lib/lsb/init-functions.d/40-systemd
+++ _use_systemctl=0
+++ '[' -d /run/systemd/system ']'
+++ '[' -n '' ']'
+++ '[' 15898 -ne 1 ']'
+++ '[' -z '' ']'
+++ '[' -z '' ']'
+++ case $(readlink -f "$0") in
++++ readlink -f /etc/init.d/usbstorage
+++ _use_systemctl=1
+++ prog=usbstorage
+++ service=usbstorage.service
++++ systemctl -p CanReload show usbstorage.service
+++ '[' CanReload=no = CanReload=no ']'
+++ '[' start = reload ']'
+++ '[' 1 = 1 ']'
+++ set +e
+++ set +u
+++ '[' xstart = xstart -o xstart = xstop -o xstart = xrestart -o xstart = xreload -o xstart = xforce-reload -o xstart = xstatus ']'
+++ systemctl_redirect /etc/init.d/usbstorage start
+++ local s
+++ local rc
+++ local prog=usbstorage
+++ local command=start
+++ case "$command" in
+++ s='Starting usbstorage (via systemctl)'
+++ service=usbstorage.service
++++ systemctl -p LoadState show usbstorage.service
+++ state=LoadState=loaded
+++ '[' LoadState=loaded = LoadState=masked ']'
+++ '[' start = status ']'
+++ log_daemon_msg 'Starting usbstorage (via systemctl)' usbstorage.service
+++ '[' -z 'Starting usbstorage (via systemctl)' ']'
+++ log_daemon_msg_pre 'Starting usbstorage (via systemctl)' usbstorage.service
+++ log_use_fancy_output
+++ TPUT=/usr/bin/tput
+++ EXPR=/usr/bin/expr
+++ '[' -t 1 ']'
+++ '[' xxterm-256color '!=' x ']'
+++ '[' xxterm-256color '!=' xdumb ']'
+++ '[' -x /usr/bin/tput ']'
+++ '[' -x /usr/bin/expr ']'
+++ /usr/bin/tput hpa 60
+++ /usr/bin/tput setaf 1
+++ '[' -z ']'
+++ FANCYTTY=1
+++ case "$FANCYTTY" in
+++ true
+++ echo -n '[....] '
[....] +++ '[' -z usbstorage.service ']'
+++ echo -n 'Starting usbstorage (via systemctl): usbstorage.service'
Starting usbstorage (via systemctl): usbstorage.service+++ log_daemon_msg_post 'Starting usbstorage (via systemctl)' usbstorage.service
+++ :
+++ /bin/systemctl start usbstorage.service
+++ rc=0
+++ '[' start = status ']'
+++ log_end_msg 0
+++ '[' -z 0 ']'
+++ local retval
+++ retval=0
+++ log_end_msg_pre 0
+++ log_use_fancy_output
+++ TPUT=/usr/bin/tput
+++ EXPR=/usr/bin/expr
+++ '[' -t 1 ']'
+++ '[' xxterm-256color '!=' x ']'
+++ '[' xxterm-256color '!=' xdumb ']'
+++ '[' -x /usr/bin/tput ']'
+++ '[' -x /usr/bin/expr ']'
+++ /usr/bin/tput hpa 60
+++ /usr/bin/tput setaf 1
+++ '[' -z 1 ']'
+++ true
+++ case "$FANCYTTY" in
+++ true
++++ /usr/bin/tput setaf 1
+++ RED=''
++++ /usr/bin/tput setaf 2
+++ GREEN=''
++++ /usr/bin/tput setaf 3
+++ YELLOW=''
++++ /usr/bin/tput op
+++ NORMAL=''
+++ /usr/bin/tput civis
+++ /usr/bin/tput sc
+++ /usr/bin/tput hpa 0
+++ '[' 0 -eq 0 ']'
+++ /bin/echo -ne '[ ok '
[ ok +++ /usr/bin/tput rc
+++ /usr/bin/tput cnorm
+++ log_use_fancy_output
+++ TPUT=/usr/bin/tput
+++ EXPR=/usr/bin/expr
+++ '[' -t 1 ']'
+++ '[' xxterm-256color '!=' x ']'
+++ '[' xxterm-256color '!=' xdumb ']'
+++ '[' -x /usr/bin/tput ']'
+++ '[' -x /usr/bin/expr ']'
+++ /usr/bin/tput hpa 60
+++ /usr/bin/tput setaf 1
+++ '[' -z 1 ']'
+++ true
+++ case "$FANCYTTY" in
+++ true
++++ /usr/bin/tput setaf 1
+++ RED=''
++++ /usr/bin/tput setaf 3
+++ YELLOW=''
++++ /usr/bin/tput op
+++ NORMAL=''
+++ '[' 0 -eq 0 ']'
+++ echo .
.
+++ log_end_msg_post 0
+++ :
+++ return 0
+++ return 0
+++ exit 0
John Allard
  • 1,368
  • Do you have other (simpler) scripts that run from init.d? If your system uses systemd and is only backward compatible with sysv see this question. Systemd is often quirky with backward compatibility. – grochmal Jul 27 '16 at 21:44
  • yeah we have other scripts that run with init.d and run perfectly. There isn't any real difference between those scripts and this one except for the commands being run inside of the do_start function – John Allard Jul 27 '16 at 21:45
  • Strange. It is like the execution stops after . /lib/lsb/init-functions. Do you get the help msg if you run the script without parameters? – hschou Jul 27 '16 at 21:58
  • I get the "Usage: /etc/init.d/usbstorage start|stop" message if I run the /etc/init.d/cam usbstorage with no other arugments. But I did confirm that by removing the sourcing of lsb/init-functions the commands in the script run but it looks ugly. I no longer get the nice logging of the service status – John Allard Jul 27 '16 at 22:01
  • When you type this #! /bin/sh i think you want to do this #!/bin/sh this space does not exists, and more i think you want to use bash, because you're testing your scripts using bash. So the right way is #!/bin/bash , there are big differences between the shell interpreters! – Luciano Andress Martini Jul 27 '16 at 23:58
  • All of our other shell scripts use #! /bin/sh and they work, but I tried your suggestion anyways and it had no effect. – John Allard Jul 28 '16 at 00:18

1 Answers1

3

TL;DR. Your start script does nothing because it is already "started", says systemd. You need to stop it then you can start it.

As you can see in your shell trace output, when you run

sudo /etc/init.d/usbstorage start

on an OS using systemd as the preferred manager, which is your case, then the line

. /lib/lsb/init-functions

in your SysV-style script causes the shell code in

/lib/lsb/init-functions.d/40-systemd

to be run. It basically sees you need the systemd equivalent to your file, so prints

Starting usbstorage (via systemctl)

then runs

/bin/systemctl start usbstorage.service

and exits there. The rest of your script is never executed in this particular process.

However, each time someone calls systemctl daemon-reload, all the /etc/init.d/* scripts are parsed and a small systemd unit file is created for each of them in /run/systemd/generator/ (at boot) or /run/systemd/generator.late/.

The ### BEGIN INIT INFO comment block of each script is converted into the equivalent systemd dependencies. The unit file for your script, usbstorage.service, will include these lines

RemainAfterExit=yes
ExecStart=/etc/init.d/usbstorage start
ExecStop=/etc/init.d/usbstorage stop

Hence that final /bin/systemctl start usbstorage.service issued just before the end of the execution of your script will simply run your script again with arg start, like you just did. This time the environment holds _SYSTEMCTL_SKIP_REDIRECT=true, so the inclusion of 40-systemd will not cause more recursion, and instead your script will execute as normal.

So why does it not do anything when you run it?

It all lies in the RemainAfterExit=yes line. This causes systemd to keep note of the fact that a start has been done, and so when you issue another start it will do nothing, because it is already started and "running".

You need to issue a stop first, then your start will actually fully run your script. You can check for the current state of your service eg:

$ sudo systemctl status usbstorage.service
* usbstorage.service - LSB: Automounts external storage if found.
   Loaded: loaded (/etc/init.d/usbstorage)
   Active: active (exited) since Thu 2016-07-28 15:37:24 CEST; 26min ago
  Process: 7977 ExecStart=/etc/init.d/usbstorage start (code=exited, status=0/SUCCESS)

Jul 28 15:37:23 three usbstorage[7977]: <stdout/stderr of your script>

Notice how it says active (exited). You can look in the log for messages with

sudo journalctl -u usbstorage
meuh
  • 51,383
  • 1
    This answer provides a very good overview of the SysV compatibility layer of systemd. The part about RemainAfterExit is inaccurate, though: systemd keeps note of the service status anyway. RemainAfterExit=yes only means that if the all processes of a service exit, its status remains active (instead of changing into inactive or failed). Which means a crashed daemon does not show up as failed, thus you can't start (only restart) it, for example. But RemainAfterExit=no (the default) could not work in general, because many LSB init scripts don't leave behind running daemons. – Ferenc Wágner Sep 05 '16 at 19:14