I have a systemd service which runs and does its thing. Periodically I need it to upgrade itself, which requires a shutdown and a restart of the service. For question purposes the upgrade script can be as simple as:
echo "Stopping service..."
systemctl stop myservice
echo "Doing some stuff..."
sleep 10s
echo "Starting service..."
systemctl start myservice
I want to call this within the service itself, preferably using boost::process
:
boost::process::child instexe{
boost::process::search_path("bash"),
std::vector<std::string>{"installerscript.sh"},
boost::process::start_dir("/installer/folder"),
boost::process::std_out > "/some/log/file.txt"
};
instexe.detach();
The problem is that as soon as the script calls systemctl stop myservice
, the installer script is killed.
Is there a way I can do what I want to do with boost::process
? Or how can I do it?
CodePudding user response:
If the upgrades are at predefined period you can think of using crontab. https://opensource.com/article/17/11/how-use-cron-linux
00 09-17 * * 1-5 /usr/local/bin/installerScript.sh
The above entry in crontab will make the program upgrade every hour between 9 am to 5pm from Monday to Friday. There are many combinations that you can think and configure.
CodePudding user response:
Is there a way I can do what I want to do with boost::process? Or how can I do it?
If you have the child process killing the parent, there's always going to be a race condition by definition.
The quick hack is to put a sleep statement at the start of the installer script, but the correct solution is to explicitly synchronize with the child:
- have the installer script detect whether it's running interactively (ie, being run manually from a terminal instead of by your service)
- if it is non-interactive (your use case), have it wait for some input in stdin
- connect the stdin pipe when you create the child
- detach the child and then write something to tell the child it's safe
Other synchronization mechanisms are available, you could use a lockfile or a signal - you just need to make sure the child doesn't do anything until after the parent has detached it.
It may be sufficient to just use bp::spawn
, but it's not obvious from the documentation that is race-free in this situation.
You should probably create a process group for the child as well, in case systemd
kills the whole group when it stops a service.