All of the problems witnessed above are the result of the shell forking to create new processes to run a pipeline: ps, grep, wc, another shell for the command substition (in the case of the original post). All of these processes initially begin as a new shell with the same name, $0, as the parent shell.
If ps scans the process list before any of these shells have had a chance to exec and become the utility it will become, the result is multiple instances of $0.
The solution is trivial and widely available: pgrep
Your analysis is incorrect. You're just getting lucky with timing. In your original wc version, you were unlucky with timing. Nothing has been fixed.
The reason pgrep works reliably is because it's only one command and it doesn't run until after the shell that was forked to create it has exec'd.
Unless the system lacks pgrep and pkill , there's no need to resort to the ps ... | grep/awk ... silliness.
Yes I WAS lucky to get that desired ouput. After a while, I found out am unlucky.. It again started creating that mess. Also the problem is my system doesn't contain pgrep I found out another way to accomplish my result.
If there is any other way that we can acquire the result with grep, wc or other silly commands, please post here..
@Alister: I have a cron which runs my script every 1 minute. If any error identified by my script, it runs another program which takes a while say 4 mins. Until it gets completed, my Cron should not allow the Script to run on the next minute.. So i thought of counting the number of PS of that script name will fix that problem. Thanks to Lem for that Solution.
What I have built is as below:
pd=$(head -1 pid.check)
ps -ef | grep $pd | grep -v grep
if [ $? -eq 0 ]; then
exit 0
fi
pid1=$$
echo "$pid1" > pid.check
Shout me if the above fails at any condition, I will correct my code. Thanks
Needs a "first time" condition. Also, if you know the pid just look for the one pid. You can dump the output from ps as you only need to know if the process is still running.
# Has previous script finished?
if [ -f pid.check ]
then
pd=$(head -1 pid.check)
ps -fp $pd 1>/dev/null
if [ $? -eq 0 ]
then
exit 0
fi
fi
# Record pid of current script
pid1=$$
echo "$pid1" > pid.check
### PROCESSING GOES HERE
It would be better to specify a directory (e.g. /var/tmp) for pid.check file or it will be created in the home directory of the owner of the crontab.