2

I'm trying to set up a system init script on my Raspbian, just to send an HTTP POST request to a public web server (99,9% uptime), reporting that the Raspbian has just been started up (or rebooted). So far, I've done the following:

A. Approach A: System-V style startup script

A.1. Edited /etc/init.d/notify-startup (initial test T0) (showing only relevant lines):

...
# Required-Start:       $remote_fs $syslog $time
# Required-Stop:        $remote_fs $syslog
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
...
case "$1" in
  start)
    logger -i "Starting Notify-Startup" || true
    /opt/notify-startup/bin/notify-startup.sh &
...

A.2. And /opt/notify-startup/bin/notify-startup.sh:

#!/bin/sh

# First.
curl --insecure --include --request POST \
    --url https://example.com/notify-startup.php \
    --header "Content-Type: application/x-www-form-urlencoded" \
    --data-urlencode "id=0" \
    --data-urlencode "count=1" \
    --data-urlencode "message=Starting up (1)" > /dev/null 2>&1
sleep 180
# Second.
curl --insecure --include --request POST \
    --url https://example.com/notify-startup.php \
    --header "Content-Type: application/x-www-form-urlencoded" \
    --data-urlencode "id=0" \
    --data-urlencode "count=2" \
    --data-urlencode "message=Starting up (2)" > /dev/null 2>&1

exit 0

A.3. Run update-rc.d to create System-V style links under /etc/rc?.d:

$ sudo update-rc.d notify-startup defaults # Command [C1]

After this execution, my symlinks under /etc/rc?.d are the following:

/etc/rc0.d/K01notify-startup
/etc/rc1.d/K01notify-startup
/etc/rc2.d/S02notify-startup
/etc/rc3.d/S02notify-startup
/etc/rc4.d/S02notify-startup
/etc/rc5.d/S02notify-startup
/etc/rc6.d/K01notify-startup

A.4. Then I reboot my Raspbian.

Result is that the first HTTP POST request does not reach the public web server but the second one actually does, and I'd like both of them would do.

It's important to say that Ethernet interface and DNS resolver must be operative so that my HTTP POST request could reach the public web server. So I've tried the following combinations of LSB facility names [1] on my script with no success until now:

A.5. Test [T1]:

# Required-Start:       $network $remote_fs $syslog $time

A.6. Test [T2]:

# Required-Start:       $named $remote_fs $syslog $time

I also have noticed that, after re-running update-rc.d [C1], the symlinks under /etc/rc?.d are not re-numbered in order to satisfy the dependencies on facility names configured on tests [T1] and [T2].

My question is: Is there any way to ensure that my startup script gets run just after DNS resolution is available to my Raspbian system, by using facility name dependencies or by any other programmatic way (I would prefer the former)? Am I doing something wrong with command [C1] so that my startup script execution order does not get updated and does not ensure DNS resolution and network availability?

PS: I already know that this simple task could be achieved well by using just a @reboot crontab job, but I need it to be a System-V startup script as I would be upgrading it to add more and more functionality over time.

[1] https://refspecs.linuxfoundation.org/LSB_1.2.0/gLSB/facilname.html

B. Approach B: Systemd unit

As suggested in comments, I also tried systemd.unit but had problems too. Steps follow:

B.1. Edit /opt/notify-startup/bin/notify-startup-02.sh:

$ sudo pico /opt/notify-startup/bin/notify-startup-02.sh

B.2. Same contents as in A.2.

B.3. Give execute permission:

$ sudo chmod ugo+x /opt/notify-startup/bin/notify-startup-02.sh

B.4. Edit service unit:

$ sudo pico /opt/notify-startup/etc/notify-startup-02.service

Contents:

[Unit]
Description=Test Service Unit
Before=runlevel2.target runlevel3.target runlevel4.target runlevel5.target shutdown.target
After=network-online.target nss-lookup.target remote-fs.target systemd-journald-dev-log.socket time-sync.target
Conflicts=shutdown.target

[Service]
Type=forking
Restart=no
TimeoutSec=5min
IgnoreSIGPIPE=no
KillMode=process
GuessMainPID=no
RemainAfterExit=yes
ExecStart=/opt/notify-startup/bin/notify-startup-02.sh
ExecStop=/usr/bin/logger -i "Stopping"

[Install]
WantedBy=default.target

B.5. Create symlinks:

$ cd /etc/systemd/system
$ sudo ln -s /opt/notify-startup/etc/notify-startup-02.service
$ cd /lib/systemd/system
$ sudo ln -s /opt/notify-startup/etc/notify-startup-02.service

B.6. Run a systemd reload and enable my unit (got stuck here):

$ sudo systemctl daemon-reload
$ sudo systemctl enable notify-startup-02.service

Got the following output:

Failed to execute operation: No such file or directory

C. Help/Solution

No matter which approach is choosen, I'd like to have a solution. Approach B, as suggested in comments, should be the best, but I got stuck in step B.6.

  • 1
    Why don't you use systemd? It's easy to achieve what you want with it. – jake Jan 26 at 1:58
  • Please read systemd - Compatibility with SysV before doing further debugging and have a look at man systemd-sysv-generator. You shouldn't ride a dead horse. – Ingo Jan 26 at 12:35
  • Thanks, @jake and @Ingo, for your suggestion. I've found this file: /run/systemd/generator.late/notify-startup.service, whose first line says: # Automatically generated by systemd-sysv-generator. Do you think the contents of this file would be a good starting point to solve my problem using the systemd approach? – Pestro Jan 27 at 20:23
  • Yes! Take it. Delete everything not needed. Add an [Install] section (for example WantedBy=default.target) and something like After=network-online.target to the [Unit] section. Then you can enable it by running systemctl daemon-reload and systemctl enable <your>.service. Put your service unit file in /etc/systemd/system/. – jake Jan 27 at 20:45
  • @jake, should my service unit file be put better in /etc/systemd/user/ directory? man systemd.unit describes it but I have seen it's empty, so I don't know if it is adequate. – Pestro Feb 24 at 23:29
2

As far as I see you want to execute a bash script at startup that only runs about 3 minutes and that accesses a remote web site. So main condition is that the network must be online. We check this with the network-online.target. To have a clean starting point I suggest to start over again with a fresh flashed Raspbian Stretch Lite.

Then create a new service with:

rpi ~$ sudo systemctl --force --full edit notify-startup-02.service

In the empty editor insert these statements, save them and quit the editor:

[Unit]
Description=Test Service Unit
Wants=network-online.target
After=network-online.target

[Service]
ExecStart=/opt/notify-startup/bin/notify-startup-02.sh

[Install]
WantedBy=multi-user.target

You can edit it again with:

rpi ~$ sudo systemctl --full edit notify-startup-02.service

Test with:

rpi ~$ sudo systemctl start notify-startup-02.service

Within 3 minutes you can stop the service with:

rpi ~$ sudo systemctl stop notify-startup-02.service

After three minutes the service has finished by itself. Then you can just start it again. Check its status at every time with:

rpi ~$ systemctl status notify-startup-02.service

To start the script on boot up, just enable it:

rpi ~$ sudo systemctl enable notify-startup-02.service

In notify-startup-02.sh you suppress curls output with > /dev/null 2>&1. This will also send the error messages into the black hole. I would not do that. You cannot see if something goes wrong. I would just only send the standard output to > /dev/null, not the error output (2>&1). The error messages are then send to the systemd journal. You can find them with:

rpi ~$ journalctl -b -e

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.