Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. Execute .sh script in a way that it keeps running after Qt programm has quit

Execute .sh script in a way that it keeps running after Qt programm has quit

Scheduled Pinned Locked Moved Unsolved Mobile and Embedded
14 Posts 5 Posters 7.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • aha_1980A aha_1980

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

    M Offline
    M Offline
    Markus Ippy
    wrote on last edited by
    #5

    @aha_1980 I haven't tried via Qt.quit() yet . i will try that when i come home tonight and let you know

    1 Reply Last reply
    0
    • M Markus Ippy

      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 ?

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #6

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

      M 1 Reply Last reply
      0
      • JonBJ JonB

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

        M Offline
        M Offline
        Markus Ippy
        wrote on last edited by
        #7

        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

        ErikRE 1 Reply Last reply
        0
        • M Markus Ippy

          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

          ErikRE Offline
          ErikRE Offline
          ErikR
          wrote on last edited by
          #8

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

          aha_1980A 1 Reply Last reply
          0
          • ErikRE ErikR

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

            aha_1980A Offline
            aha_1980A Offline
            aha_1980
            Lifetime Qt Champion
            wrote on last edited by
            #9

            @ErikR that will not make a difference in reality. Hint: the script is still run by the interpreter mentioned in the shebang.

            Qt has to stay free or it will die.

            ErikRE 1 Reply Last reply
            1
            • aha_1980A aha_1980

              @ErikR that will not make a difference in reality. Hint: the script is still run by the interpreter mentioned in the shebang.

              ErikRE Offline
              ErikRE Offline
              ErikR
              wrote on last edited by
              #10

              @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

              1 Reply Last reply
              0
              • ? Offline
                ? Offline
                A Former User
                wrote on last edited by
                #11

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

                1 Reply Last reply
                1
                • M Markus Ippy

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

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #12

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

                  1 Reply Last reply
                  1
                  • ErikRE Offline
                    ErikRE Offline
                    ErikR
                    wrote on last edited by
                    #13

                    @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

                    JonBJ 1 Reply Last reply
                    1
                    • ErikRE ErikR

                      @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

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by JonB
                      #14

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

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved