-
-
Save manovotny/5352248d3553da4d77dc to your computer and use it in GitHub Desktop.
#!/bin/bash | |
dupe_script=$(ps -ef | grep "SCRIPT_NAME.sh" | grep -v grep | wc -l | xargs) | |
if [ ${dupe_script} -gt 2 ]; then | |
echo -e "The SCRIPT_NAME.sh script was already running!" | |
exit 0 | |
fi |
Why do we check dupe_script
value with 3 ??
For two sleep command
ps -ef | grep "SCRIPT_NAME.sh" | grep -v grep
it fails to detect ??
It require atleast three instances of the script to detect.
Should it be checked with 1 ??
Should it be checked with 1 ??
i am also interested...and thanks that you shared your idea.
Well, y'all we're right. 3
doesn't work in usual circumstances. I was using 3
for a specific reason, which I'll explain later...
You would think it should be -gt 1
, and I agree with you, logically, it should! But it's not. It's because of bash's subshells and pipes. This StackOverflow answer explains why, but I'll admit it's a bit over my head.
So because of that, we need to use 2
when we're in the script, though it will only show as 1
outside of the script. Yes, weird, I know. It bakes my noodle too. But it is what it is and it works and I won't try and fight it.
You can see what's going on in the screenshot below with some extra echos.
I've updated the gist above and changed it to 2
.
Now... Why was I originally using 3
? It's because I was using this in a scheduled cron job, so when it went to do the grep
for the running processes, it saw an extra entry for the script as a scheduled cron job. If that's you and your use case, you'll want to continue to use 3
instead of 2
.
Hope that helps explain things a bit! 😅
How about determining the script name like this?
#!/bin/bash
SCRIPT_NAME=$(basename "$0")
dupe_script=$(ps -ef | grep "$SCRIPT_NAME" | grep -v grep | wc -l | xargs)
if [ ${dupe_script} -gt 2 ]; then
echo -e "The $SCRIPT_NAME script was already running!"
exit 0
fi
consider looking at "pgrep", one for "-c" to count the pids and two for -f "for full path", three -u for uid running, and execute with fqfn so that the script is "/path/to/script/runtime.sh" not "runtime.sh". Now you can run multiple scripts of the same name and not get conflicts between them (eg, ~/bin/cron.sh and ~/test/cron.sh) and other user's cron.sh won't clash, or when you are editing cron.sh (eg, "emacs cron.sh")
@eiswezinoo if you want to test if it's working or not, try:
sleep
command in your script to make it process longer than it normally would.I don't believe the code above is checking for arguments, just the name of the script. I am sure it could be enhanced to also check for arguments.