Bash cron flock screen

I am using cron to run a bash script periodically and am trying to use flock to prevent this script and the processes it creates from being run multiple times.

Crontab entry to run every minute:

*/1 * * * * flock -n /tmp/mylockfile /home/user/myscript.sh arg1 arg2

      

The problem is that myscript.sh starts multiple screen sessions in a separate mode, contains

for i in {1..3}; 
do 
    screen -d -m ./mysubscript.sh arg3
done

      

Starting a screen with "-d -m" as above starts the screen in detached mode as a forked process, but these processes do not inherit the flock lock, so every minute there are 3 new screen processes running mysubscript.sh ,

If I use "-D -m" instead, then only one screen process is executed all the time until mysubscript.sh ends, not three.

I only need a flock to run myscript.sh if none of the on-screen processes running mysubscript.sh are running.

How can this be achieved? Are there flags in the screen or herd that can help achieve this?

EDIT: If I change the line inside the for loop to run mysubscript.sh as a background process with:

./mysubscript.sh arg3 &

      

The lock behavior is exactly what I want, except that I no longer have separate screens.

+1


source to share


1 answer


Depending on your specific needs, you can either run a substring loop sequentially or create separate screen sessions for each.

Multiple Screen Method

screens.sh

#!/bin/bash

if ! screen -ls | grep -q "screenSession"
    then
        for i in {1..3};
            do
                screen -S screenSession_${i} -d -m sh mysubscript.sh arg3 &
            done
            { echo "waking up after 3 seconds"; sleep 3; } &
            wait # wait for process to finish
            exit # exit screen
    else echo "Screen Currently Running"
fi

      

Session

62646.screenSession_1   (Detached)
62647.screenSession_2   (Detached)
62648.screenSession_3   (Detached)

      

This method will set up screens for each iteration of your loop and do the index. If cron tries to run and run the script while there are still active sockets, then it will exit before the next cron.

Single screen method

screencaller.sh

#!/bin/bash

if ! screen -ls | grep -q "screenSession"
    then screen -S screenSession -d -m sh screen.sh
    else echo "Screen Currently Running"
fi

      



screen.sh

#!/bin/bash

for i in {1..3}; 
do 
    sh mysubscript.sh arg3
done

{ echo "waking up after 3 seconds"; sleep 3; } &

wait # wait for process to finish
exit # exit screen

      

Session

59916.screenSession (Detached)

      

This method uses a separate calling script and then just loops your index one by one in the same screen session.

Then any method will be executed like this (for example, screens.sh or screencaller.sh):

*/1 * * * * flock -n /tmp/mylockfile screens.sh arg1 arg2

      

Or if you want to start it manually from the CLI, just do:

$ sh screens.sh

      

If you want to inject a session, you just call screen -r screenSession

. Several other useful commands: screen -ls

and ps aux | grep screen

, which show the screens and processes you are currently running.

+2


source







All Articles