Reputation: 2311
I have a bash script which I think is making a false assumption.
The bash script is as shown:
running()
{
if
test -e .pid
then
pid=`cat .pid`
if
ps -p $pid | grep -q $pid
then
return 0
fi
fi
return 1
}
dd=`date +'%d'`
if
running
then
echo Still running PID:
cat .pid
else
echo $$ > .pid
echo Current PID: $$
java -cp ./runLoad2.jar:$CLASSPATH runLoad.mainClass
fi
In my opinion the above bash shell script is making a false assumption while checking if the process id is still active or not.
Here while starting for the first time there is no .pid file so it creates the file and stores the pid in the .pid file.
The second time on wards it checks if the process id stored in the .pid file is active or not and if it is inactive or if the ps commad does not return any input it starts the java program.
But here after the first load is complete the pid is released back to os and when the shell script runs for the second time it uses the old pid which can be used by some other process and this is where I think its making a false assumption thinking that the stored process id always refers to this shell script.
I'm not sure if I'm correct. Can someone clarify.
Upvotes: 0
Views: 95
Reputation: 113844
In the last else
clause, you need to clean up after the java program finishes by deleting the .pid file:
else
echo $$ > .pid
echo Current PID: $$
java -cp ./runLoad2.jar:$CLASSPATH runLoad.mainClass
rm -f .pid
fi
Otherwise, as you surmise, the pid may be reused.
The above assumes that the java process does not fork or otherwise spawn background processes. If it does, you have other issues.
If there is a chance that your process terminates by ctrl-C or some such signal, then you need to trap the signal and put the clean up code in the trap. To do that, put the following near the beginning of the script:
MyExit() {
rm -f .pid
exit
}
trap MyExit EXIT
This causes the bash function MyExit to run when the script receives an EXIT signal.
MORE: Your program, modified minimally to add the exit trap, would be:
MyExit() {
rm -f .pid
exit
}
running()
{
if
test -e .pid
then
pid=`cat .pid`
if
ps -p $pid | grep -q $pid
then
return 0
fi
fi
return 1
}
dd=`date +'%d'`
if
running
then
echo Still running PID:
cat .pid
else
trap MyExit EXIT
echo $$ > .pid
echo Current PID: $$
java -cp ./runLoad2.jar:$CLASSPATH runLoad.mainClass
fi
The definition of the MyExit function could go a variety of places as long as it is defined before the trap statement is executed. I put it at the top because it is commonly considered good style to have bash function definitions at the top.
The trap statement should to be placed strategically after the decision has been made to write the .pid
file and before it has been written.
Upvotes: 1
Reputation: 20980
Your java command may be internally fork
ing & the parent among the 2 processes may be exiting, keeping the child running in the background.
Hence the bash script exits, & PID becomes available to OS.
Also, on another note, I would recommend adding exec
before the java command, because (most likely,) you would want to monitor the java process rather than the parent (bash wrapper).
By adding exec
bash script PID will be inherited by the java process.
To verify speculation (1), try the exec method I described in (2). Check in ps -ef
output, it the java process has indeed spawn a child process. If the parent process has exited, the child process should have ppid=1 (init)
Upvotes: 0