Execute .sh script in a way that it keeps running after Qt programm has quit
-
I have a raspberry pi programm written wit QT5.8 opensource.
I wanted to give the user a possibility to update the program from source directly from the program itself.
The program is installed in "$/opt/PowerTune" the source code resides in "/home/pi/PowerTune"
i have written a sh script to update the program ://Contents of the script update.sh
cd /home/pi/PowerTune
git pull
pkill -f PowerTuneQMLGui //Close my program before removing the install directory
sudo rm -r /opt/PowerTune //remove the old install directory
sudo mkdir /opt/PowerTune
sudo chown /opt/PowerTune
cd /opt/PowerTune
qmake /home/pi/PowerTune/PowerTuneQMLGui.pro
make
sudo reboot now
//End ScriptI execute my script from within c++
void Serial::update()
{
QProcess process;
process.startDetached("/bin/sh", QStringList()<< "/home/pi/update.sh");
qDebug() << "Update PowerTune.";
}My Problem now is that i oviously kill my program before deleting the install directory .
Is there any way i can start the execute the script that it keeps running after i kill my qt programm ? -
I have a raspberry pi programm written wit QT5.8 opensource.
I wanted to give the user a possibility to update the program from source directly from the program itself.
The program is installed in "$/opt/PowerTune" the source code resides in "/home/pi/PowerTune"
i have written a sh script to update the program ://Contents of the script update.sh
cd /home/pi/PowerTune
git pull
pkill -f PowerTuneQMLGui //Close my program before removing the install directory
sudo rm -r /opt/PowerTune //remove the old install directory
sudo mkdir /opt/PowerTune
sudo chown /opt/PowerTune
cd /opt/PowerTune
qmake /home/pi/PowerTune/PowerTuneQMLGui.pro
make
sudo reboot now
//End ScriptI execute my script from within c++
void Serial::update()
{
QProcess process;
process.startDetached("/bin/sh", QStringList()<< "/home/pi/update.sh");
qDebug() << "Update PowerTune.";
}My Problem now is that i oviously kill my program before deleting the install directory .
Is there any way i can start the execute the script that it keeps running after i kill my qt programm ?@Markus-Ippy Maybe not the answer you expected, but have you thougt about running the script on boot before your program runs?
you would put the update files at a defined dir and pick them up from your script if they exist. otherwise just start your program normally.
-
@aha_1980 said in execute .sh script in a way that it keeps running after qt programm has quit:
would put the update files at a defined dir and pick them up from your script if they exist. otherwise just start your program normally.
I haven't thought about that. that is actually not a bad idea. Nevertheless it would be interesting to know if i can start a script from QT that stays alive even after the QT programm gets closed .
-
@aha_1980 said in execute .sh script in a way that it keeps running after qt programm has quit:
would put the update files at a defined dir and pick them up from your script if they exist. otherwise just start your program normally.
I haven't thought about that. that is actually not a bad idea. Nevertheless it would be interesting to know if i can start a script from QT that stays alive even after the QT programm gets closed .
@Markus-Ippy reading the docs of
startDetached
it should already work. have you tried exiting your Qt program the 'normal' way i.e. not by killing it? -
@Markus-Ippy reading the docs of
startDetached
it should already work. have you tried exiting your Qt program the 'normal' way i.e. not by killing it?@aha_1980 I haven't tried via Qt.quit() yet . i will try that when i come home tonight and let you know
-
I have a raspberry pi programm written wit QT5.8 opensource.
I wanted to give the user a possibility to update the program from source directly from the program itself.
The program is installed in "$/opt/PowerTune" the source code resides in "/home/pi/PowerTune"
i have written a sh script to update the program ://Contents of the script update.sh
cd /home/pi/PowerTune
git pull
pkill -f PowerTuneQMLGui //Close my program before removing the install directory
sudo rm -r /opt/PowerTune //remove the old install directory
sudo mkdir /opt/PowerTune
sudo chown /opt/PowerTune
cd /opt/PowerTune
qmake /home/pi/PowerTune/PowerTuneQMLGui.pro
make
sudo reboot now
//End ScriptI execute my script from within c++
void Serial::update()
{
QProcess process;
process.startDetached("/bin/sh", QStringList()<< "/home/pi/update.sh");
qDebug() << "Update PowerTune.";
}My Problem now is that i oviously kill my program before deleting the install directory .
Is there any way i can start the execute the script that it keeps running after i kill my qt programm ?@Markus-Ippy
Firstly, in your script, which I assume you have copied & pasted here:sudo chown /opt/PowerTune
should give:
jon@ubuntu:~$ sudo chown file chown: missing operand after ‘file’ Try 'chown --help' for more information.
?
Now to summarise your situation:
- You run Qt app
PowerTuneQMLGui
which launches script viaQProcess::startDetached()
. - Script executes
pkill -f PowerTuneQMLGui
, killing your app. - You're finding that killing the app immediately also kills your script.
Right?
http://doc.qt.io/qt-5/qprocess.html#startDetached claims:
Unix: The started process will run in its own session and act like a daemon.
We don't know what code
startDetached()
uses under Linux, but I agree that explanation implies to me that the script should not itself get terminated....Let's be clear about the behaviour you are actually seeing. You say:
My Problem now is that i oviously kill my program before deleting the install directory .
Deleting the install directory is the least of your problems. If you are right your script gets killed at the
pkill -f PowerTuneQMLGui //Close my program before removing the install directory
line. In that case it does not proceed to any further line at all, so it never does theqmake
orreboot
at all. Is that what you experience? - You run Qt app
-
@Markus-Ippy
Firstly, in your script, which I assume you have copied & pasted here:sudo chown /opt/PowerTune
should give:
jon@ubuntu:~$ sudo chown file chown: missing operand after ‘file’ Try 'chown --help' for more information.
?
Now to summarise your situation:
- You run Qt app
PowerTuneQMLGui
which launches script viaQProcess::startDetached()
. - Script executes
pkill -f PowerTuneQMLGui
, killing your app. - You're finding that killing the app immediately also kills your script.
Right?
http://doc.qt.io/qt-5/qprocess.html#startDetached claims:
Unix: The started process will run in its own session and act like a daemon.
We don't know what code
startDetached()
uses under Linux, but I agree that explanation implies to me that the script should not itself get terminated....Let's be clear about the behaviour you are actually seeing. You say:
My Problem now is that i oviously kill my program before deleting the install directory .
Deleting the install directory is the least of your problems. If you are right your script gets killed at the
pkill -f PowerTuneQMLGui //Close my program before removing the install directory
line. In that case it does not proceed to any further line at all, so it never does theqmake
orreboot
at all. Is that what you experience?Sorry i just typed what i have in the script not copied and pasted it
in the script i use :
$ sudo chown pi:pi /opt/PowerTuneThe script itself works properly when executed from commandline . my program is running in a car so its inconvenient to have a mouse and keyboard , hence my try to execute the script from my program.
As for what i am experiencing you are spot on
pkill -f PowerTuneQMLGui also stops the script and i just end up on the command line without the delete / qmake / reboot - You run Qt app
-
Sorry i just typed what i have in the script not copied and pasted it
in the script i use :
$ sudo chown pi:pi /opt/PowerTuneThe script itself works properly when executed from commandline . my program is running in a car so its inconvenient to have a mouse and keyboard , hence my try to execute the script from my program.
As for what i am experiencing you are spot on
pkill -f PowerTuneQMLGui also stops the script and i just end up on the command line without the delete / qmake / rebootHi,
What if you add a "shebang" in the script-file and makes it executable;First row of script:
#!/bin/sh
Then start the script as any other program and not as an argument to /bin/sh.
process.startDetached(""/home/pi/update.sh");
(I have not verified that startDetached can operate without the second argument)
-
Hi,
What if you add a "shebang" in the script-file and makes it executable;First row of script:
#!/bin/sh
Then start the script as any other program and not as an argument to /bin/sh.
process.startDetached(""/home/pi/update.sh");
(I have not verified that startDetached can operate without the second argument)
-
@ErikR that will not make a difference in reality. Hint: the script is still run by the interpreter mentioned in the shebang.
Well, we can conclude that startDetached does not really start as detached we might expect in this particular case.
I would assume that in the first case /bin/sh is started by the Qt application with an argument that happens to be a script-file (there is a lot of options to sh and bash, you might want to look into them).
In the second case a recognized executable program is started by the Qt application and the OS will figure out that it shall be interpreted using /bin/sh.
It will work the same on high level but might differ on the lower levels and as we are hunting some obscure reason to why startDetached does not actually start detached it might work different.
Another thing I have stumbled on is that the file of a started process can be overwritten while the already started process remains intact (well, loading dynamic libraries will not work well). I am not sure how this works on lower levels but when I stumbled on this it looked like the started version of the file was accessible from within the running program while any new process will use the new one. This was on the Solaris 2.6 age and might need to be verified for Linux ;)
The implication in this case is the started process will survive the script removing its files and one might consider not to kill the process at all as reboot will do that eventually which will solve the actual problem; successful rebuild and reboot
-
@Markus-Ippy said in execute .sh script in a way that it keeps running after qt programm has quit:
I wanted to give the user a possibility to update the program from source directly from the program itself.
But why? That's the one great thing about Linux distributions, that they all come with a unified install / update mechanism for all parts of the system. Why torture your users with a wacky home-grown updater?
-
@aha_1980 said in execute .sh script in a way that it keeps running after qt programm has quit:
would put the update files at a defined dir and pick them up from your script if they exist. otherwise just start your program normally.
I haven't thought about that. that is actually not a bad idea. Nevertheless it would be interesting to know if i can start a script from QT that stays alive even after the QT programm gets closed .
@Markus-Ippy
Assuming you're still interested in pursuing the reason for this behaviour...As I said, from the Qt docs on
startDetached()
I would have expected you sub-process not to get killed when the parent Qt app gets killed. I'm certainly interested if you are!To find out what is going on, I would replace the content of your script with something like
sleep 60
or similar. Set it off from within your app.Now use
ps
with options to get all details about both your running app and the sub-process. I thinkps -ejH
will do it. (You will want to specify other options to reduce the number of processes shown or show more of the command-line to identify what is what, since you're writing scripts I imagine you can figure that.)The column headers are at the top of the output: the first 3 are
PID
,PGID
&SID
. That's the ids for the process itself, the Group id & the Session id. What we need to know is whether your parent application and your sub-process child do or do not have same Group and/or Session ids, as this affects who signals delivered to the parent (your app) do or do not also get sent to.If you fancy coming back with that information we would be in a starting position to understand what's going on to produce the behaviour you see!
-
@Markus-Ippy said in Execute .sh script in a way that it keeps running after Qt programm has quit:
I managed to get it work by adding a ampersand to the arg-list. Strange that it is needed but well, it made the trick. For non-unix/linux users this is the signal to start a process in the background.
The script:
#!/bin/bash echo "Test-script started with PID = ${$}" >> log.txt sleep 5 echo "Kill and remove the program" >> log.txt pkill -f script-restart-test >> log.txt rm script-restart-test >> log.txt echo "Done killing, sleep" >> log.txt sleep 5 echo "Terminating" >> log.txt
The reason I use a logfile (wich I tail -f in another window) is that output is lost when the parent is killed and there are no indication beside ps to verify that the script-process is still alive. In general printouts from background processes may cause problems from time to time, better to log to a file.
The Qt C++ code cut from a public slot triggered by a button in a newly generated application:
void MainWindow::runScript() { bool bStatus = false; QStringList args; qint64 pid = 0; args << "&"; bStatus = QProcess::startDetached("./testscript.sh", args, ".", &pid); qDebug() << "Started process detached"; qDebug() << "got PID = " << pid; qDebug() << "and status = " << bStatus; }
I observed that the child process (script) started got PID 1 as parent process (unsing ps -def).
$ ps -def | grep script .... 24268 5572 1 13:40 ? 00:00:00 /home/..../script-restart-test .... 24273 1 0 13:40 ? 00:00:00 /bin/bash ./testscript.sh & .... 24276 22779 0 13:40 pts/6 00:00:00 grep --colour=auto script $ ps -def | grep script .... 24273 1 0 13:40 ? 00:00:00 /bin/bash ./testscript.sh & .... 24282 22779 0 13:41 pts/6 00:00:00 grep --colour=auto script
Regards,
Erik -
@Markus-Ippy said in Execute .sh script in a way that it keeps running after Qt programm has quit:
I managed to get it work by adding a ampersand to the arg-list. Strange that it is needed but well, it made the trick. For non-unix/linux users this is the signal to start a process in the background.
The script:
#!/bin/bash echo "Test-script started with PID = ${$}" >> log.txt sleep 5 echo "Kill and remove the program" >> log.txt pkill -f script-restart-test >> log.txt rm script-restart-test >> log.txt echo "Done killing, sleep" >> log.txt sleep 5 echo "Terminating" >> log.txt
The reason I use a logfile (wich I tail -f in another window) is that output is lost when the parent is killed and there are no indication beside ps to verify that the script-process is still alive. In general printouts from background processes may cause problems from time to time, better to log to a file.
The Qt C++ code cut from a public slot triggered by a button in a newly generated application:
void MainWindow::runScript() { bool bStatus = false; QStringList args; qint64 pid = 0; args << "&"; bStatus = QProcess::startDetached("./testscript.sh", args, ".", &pid); qDebug() << "Started process detached"; qDebug() << "got PID = " << pid; qDebug() << "and status = " << bStatus; }
I observed that the child process (script) started got PID 1 as parent process (unsing ps -def).
$ ps -def | grep script .... 24268 5572 1 13:40 ? 00:00:00 /home/..../script-restart-test .... 24273 1 0 13:40 ? 00:00:00 /bin/bash ./testscript.sh & .... 24276 22779 0 13:40 pts/6 00:00:00 grep --colour=auto script $ ps -def | grep script .... 24273 1 0 13:40 ? 00:00:00 /bin/bash ./testscript.sh & .... 24282 22779 0 13:41 pts/6 00:00:00 grep --colour=auto script
Regards,
Erik@ErikR
When a process has PPID of 1, it has been removed from the parent's process group, and is immune from signals delivered to parent, i.e. just what you wanted.When a shell runs a command with an
&
, it sets so that the child process has PPID of 1.I still would have expected
startDetached()
to have done this itself from the docs ("runs it as a daemon process"), but we don't know for sure what the code is. So thanks for your tip.If you want an explanation of "sessions" & "process groups": http://www.informit.com/articles/article.aspx?p=397655&seqNum=6
P.S.
Since telling you to useps
to find out about running processes, I have now learned that Linux has the/proc
pseudo-filing system for processes (didn't used to exist in my old UNIX days!).cat
tting "files" there reveals all sorts of interesting information about the process!