Score:2

Running a script at shutdown before networking goes down

lk flag

I would like to run a script when my computer (Ubuntu 22.04) shuts down, but while networking is still available.

The advice in this thread helpfully explained how to create a systemd service file that would run at shutdown, and the script did indeed run, but the script was not able to complete a task that required access to the network, so I assume networking had already shut down.

If found various threads (eg this one) about how to make sure a script ran before networking shut down, but they all seemed to have slightly different advice. I tried various permutations of Before=network-online.target, After=network-online.target, and Requires=network-online.target, but none of them seemed to work.

Does anyone know how to make sure the script can run while networking is still available?

BTW, I'm not wedded to doing this as a systemd job. I assumed that would be the best way to do it, but if there is another way of achieving the same thing then that would be fine.

A1 Computers avatar
cn flag
Really depends on what your trying to accomplish, for instance crontab is another way of getting things automated and you could create a specific cron rule for the task. But again, not sure what the task is. Hope this points you to an alternative solution.
Adam Jacobs avatar
lk flag
Specificlly, I'm trying to write to a database on a remote machine using a psql command. I want to do it shortly before shutdown, but it can't find the remote machine once the networking service starts to shut down.
Adam Jacobs avatar
lk flag
Also, I should clarify that shutdown is something that I will do manually. I don't want to schedule a shutdown at a specific time.
A1 Computers avatar
cn flag
Adam I found this useful - https://www.golinuxcloud.com/run-script-with-systemd-before-shutdown-linux/
Adam Jacobs avatar
lk flag
Yes, that's a nice clear explanation of how to get a script to run at shutdown, but it doesn't solve my problem. I notice that someone in the comments on that article seemed to have exactly the same problem as me, and the suggested solution was to have the line "Before= shutdown.target network.target". Well, I tried that, but it didn't work. My script runs at shutdown OK, but the part that relies on the network being available still fails.
Score:0
lk flag

OK, I've done a bit more playing around, and have made progress, but haven't actually solved the problem yet.

It turns out that the network does work, sort of, if I have After=network.target in the service file. It seems to be the name resolution that's not working. So if I run the interaction with the remote computer specifying the host name of the remote computer, then it doesn't work, but if I specify it using its IP address, then it does work.

I had hoped that I could fix this by having After=network.target nss-lookup.target, but that didn't fix it.

Any ideas what else I could try?

Score:0
ru flag

Off the top of my ancient and bald head, why not make a bash script:

#!/bin/bash
Your Commands;
shutdown -h now

Shutdown shouldn't execute until 'Your Commands' have completed execution.

The script could be called 'myshutdown' and even aliased to the system command.

(It seems too simplistic to me, and I'm sure someone will point out my errors!) (Thanks for the edit to tidy up the code 'Marco')

Score:0
tr flag

Don't know if this will help, but consider looking at the systemd .target files. This is what systemd actually runs when shutting down. Here's a link.

https://documentation.suse.com/smart/linux/html/reference-managing-systemd-targets-systemctl/index.html

shutdown.target
       A special target unit that terminates the services on system
       shutdown.

       Services that shall be terminated on system shutdown shall add
       Conflicts= and Before= dependencies to this unit for their service
       unit, which is implicitly done when DefaultDependencies=yes is set
       (the default).

The .target files lives in /usr/lib/systemd/system with the .service files. If it were me, I'd be doing this on a VM where I can easily roll back a snapshot ;)

Score:0
do flag

The key to understanding how to get a service to stop at shutdown prior to losing the network is knowing that the shutdown order is the reverse startup order. Therefore, your service should start after network-online.target while also having a dependency on network-online.target, because it requires the network to be up. Furthermore, there are ExecStart= and ExecStop= actions that you can define. Since you want the script to run at shutdown, which is when the service stops, you want to define ExecStop= pointing to your script.

To set this up, do the following:

  • In the [Unit] section, create a Requires=network-online.target dependency
  • Set the order to After=network-online.target.
  • In the [Service] section, don't define an ExecStart= action.
  • Set RemainAfterExit=true, because we didn't create an ExecStart= action.
  • Finally, create an ExecStop= action pointing to your script, such as ExecStop=/home/username/bin/testscript.sh.

Remember, the shutdown order is the reverse startup order. Therefore, when your service is stopped, your script, which is placed in ExecStop=, will be run. And because we started this service after network-online.target, it will be shutdown before any services in network-online.target are shutdown.

As an example...

Here is a simple test script that uses curl to get your public IP address. As such, DNS is required for this to run properly.

#!/bin/bash

# NAME: testscript.sh
# PATH: /home/username/bin

NOW=`date`
IP=`curl -s https://ipinfoio/ip`

echo $NOW $IP >> /home/username/ipaddresses

Next, create a systemd service/unit file in /etc/systemd/system. I named this testservice.service.

[Unit]
Description:Test service to execute at shutdown prior to losing network
Requires=network-online.target
After=network-online.target

[Service]
Type=oneshot
RemainAfterExit=true
ExecStop=/home/username/bin/testscript.sh

[Install]
WantedBy=multi-user.target

Tell systemd to read our file:

sudo systemctl daemon-reload

Enable the service:

sudo systemctl enable testservice.service

Then reboot the system and you will see that the file /home/username/ipaddress will be updated with a timestamp at shutdown and your public IP address.

I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.