可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
GNU bash, version 1.14.7(1)
I have a script is called "abc.sh
" I have to check this from abc.sh
script only... inside it I have written following statement
status=`ps -efww | grep -w "abc.sh" | grep -v grep | grep -v $$ | awk '{ print $2 }'` if [ ! -z "$status" ]; then echo "[`date`] : abc.sh : Process is already running" exit 1; fi
I know it's wrong because every time it exits as it found its own process in 'ps' how to solve it? how can I check that script is already running or not from that script
only ?
回答1:
An easier way to check for a process already executing is the pidof
command.
if pidof -x "abc.sh" >/dev/null; then echo "Process already running" fi
Alternatively, have your script create a PID file when it executes. It's then a simple exercise of checking for the presence of the PID file to determine if the process is already running.
#!/bin/bash # abc.sh mypidfile=/var/run/abc.sh.pid # Could add check for existence of mypidfile here if interlock is # needed in the shell script itself. # Ensure PID file is removed on program exit. trap "rm -f -- '$mypidfile'" EXIT # Create a file with current PID to indicate that process is running. echo $$ > "$mypidfile" ...
Update: The question has now changed to check from the script itself. In this case, we would expect to always see at least one abc.sh
running. If there is more than one abc.sh
, then we know that process is still running. I'd still suggest use of the pidof
command which would return 2 PIDs if the process was already running. You could use grep
to filter out the current PID, loop in the shell or even revert to just counting PIDs with wc
to detect multiple processes.
Here's an example:
#!/bin/bash for pid in $(pidof -x abc.sh); do if [ $pid != $$ ]; then echo "[$(date)] : abc.sh : Process is already running with PID $pid" exit 1 fi done
回答2:
I you want the "pidof" method, here is the trick:
if pidof -o %PPID -x "abc.sh">/dev/null; then echo "Process already running" fi
Where the -o %PPID
parameter tells to omit the pid of the calling shell or shell script. More info in the pidof
man page.
回答3:
Here's one trick you'll see in various places:
status=`ps -efww | grep -w "[a]bc.sh" | awk -vpid=$$ '$2 != pid { print $2 }'` if [ ! -z "$status" ]; then echo "[`date`] : abc.sh : Process is already running" exit 1; fi
The brackets around the [a]
(or pick a different letter) prevent grep
from finding itself. This makes the grep -v grep
bit unnecessary. I also removed the grep -v $$
and fixed the awk
part to accomplish the same thing.
回答4:
Someone please shoot me down if I'm wrong here
I understand that the mkdir
operation is atomic, so you could create a lock directory
#!/bin/sh lockdir=/tmp/AXgqg0lsoeykp9L9NZjIuaqvu7ANILL4foeqzpJcTs3YkwtiJ0 mkdir $lockdir || { echo "lock directory exists. exiting" exit 1 } # take pains to remove lock directory when script terminates trap "rmdir $lockdir" EXIT INT KILL TERM # rest of script here
回答5:
Use the PS command in a little different way to ignore child process as well:
ps -eaf | grep -v grep | grep $PROCESS | grep -v $$
回答6:
I create a temporary file during execution.
This is how I do it:
#!/bin/sh # check if lock file exists if [ -e /tmp/script.lock ]; then echo "script is already running" else # create a lock file touch /tmp/script.lock echo "run script..." #remove lock file rm /tmp/script.lock fi
回答7:
Here's how I do it in a bash script:
if ps ax | grep $0 | grep -v $$ | grep bash | grep -v grep then echo "The script is already running." exit 1 fi
This allows me to use this snippet for any bash script. I needed to grep bash because when using with cron, it creates another process that executes it using /bin/sh.
回答8:
I have found that using backticks to capture command output into a variable, adversly, yeilds one too many ps aux results, e.g. for a single running instance of abc.sh:
ps aux | grep -w "abc.sh" | grep -v grep | wc -l
returns "1". However,
count=`ps aux | grep -w "abc.sh" | grep -v grep | wc -l` echo $count
returns "2"
Seems like using the backtick construction somehow temporarily creates another process. Could be the reason why the topicstarter could not make this work. Just need to decrement the $count var.