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 Script

    I 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 .



  • @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



  • @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:

    1. You run Qt app PowerTuneQMLGui which launches script via QProcess::startDetached().
    2. Script executes pkill -f PowerTuneQMLGui, killing your app.
    3. 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 the qmake or reboot 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/PowerTune

    The 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



  • @Markus-Ippy

    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.



  • @aha_1980

    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?



  • @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 think ps -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



  • @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 use ps 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!). cattting "files" there reveals all sorts of interesting information about the process!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.