Selfupdating Python service kills itself

Viewed 44

TLDR: I want to selfupdate service from git. Bash script needs to stop this service. But it kills selfupdate. How to start bash script from Python that it will finish even if Python script is killed?

I want to run selfupdate bash script (update.sh) from Python script running as service to selfupdate service. Problem is I need to stop service, because I need to pull new data from git. Without stopping service I endup with corrupted data.

This is part Python script, which is run as service. This part should handle selfupdate of service:

import subprocess

subprocess.call('sudo /home/pi/myproject/update.sh', shell=True)

This is the update.sh script (100% working if I run it in terminal):

#!/bin/bash

systemctl stop myproject.service

su - pi -c "cd /home/pi/myproject; git reset --hard; git pull;"
su - pi -c "cd /home/pi/myproject; chmod +x update.sh"

systemctl start myproject.service

When systemctl stop myproject.service command is executed, service is killed and next lines aren't executed.

Is it possible to start update.sh in some environment which will be finished even if myproject.service is killed?

2 Answers

You can achieve this by calling

subprocess.call('sudo at now -f /home/pi/myproject/update.sh', shell=True)

at will spawn a new shell process so that the launching process can be stopped and then restarted from the spawned process.

The easiest option is to launch the script which restarts the service as a background process. This will 'detach' it so that killing/restarting the service doesn't affect the script.

This is done by using the close_fds parameter to subprocess.call:

subprocess.call('sudo /home/pi/myproject/update.sh', shell=True, close_fds=True)

Be aware however that since this process is now detached, nothing will tidy it up if it hangs or blocks. You may want to put extra code in to ensure it cleans up after itself properly, such as a timeout.

Alternatively, you might want to look at making the 'update' script run when the service starts, before the 'main' command. Then if you just call systemctl start/restart it will run the git commands before the main service starts.

You can do this by adding ExecStartPre in the systemctl service:

[Service]
ExecStartPre=sudo /home/pi/myproject/update.sh
Related