我有一个bash脚本,我认为这是一个错误的假设。
bash脚本如下所示:
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
在我看来,上面的bash shell脚本在检查进程ID是否仍处于活动状态时做出了错误的假设。
这里第一次启动时没有.pid文件,所以它创建文件并将pid存储在.pid文件中。
第二次在wards上检查存储在.pid文件中的进程id是否处于活动状态,如果它处于非活动状态,或者如果ps commad没有返回任何输入,则启动java程序。
但是在第一次加载完成后,pid被释放回os,当shell脚本第二次运行时,它使用了旧的pid,可以被其他进程使用,这就是我认为假设存储过程id始终引用此shell脚本的错误假设。
我不确定我是否正确。有人可以澄清一下。
答案 0 :(得分:1)
在上一个else
子句中,您需要在java程序完成后通过删除.pid文件进行清理:
else
echo $$ > .pid
echo Current PID: $$
java -cp ./runLoad2.jar:$CLASSPATH runLoad.mainClass
rm -f .pid
fi
否则,正如你猜测的那样,可以重复使用pid。
以上假设java进程不会派生或以其他方式生成后台进程。如果是,则还有其他问题。
如果您的进程有可能通过ctrl-C或某些此类信号终止,那么您需要捕获信号并将清理代码放入陷阱中。为此,请将以下内容放在脚本的开头附近:
MyExit() {
rm -f .pid
exit
}
trap MyExit EXIT
这会导致bash函数MyExit在脚本收到EXIT信号时运行。
更多信息:您的程序,最低限度修改以添加退出陷阱,将是:
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
MyExit函数的定义可以在各种位置进行,只要在执行trap语句之前定义它。我把它放在顶部,因为在顶部有bash函数定义通常被认为是好的风格。
在决定编写.pid
文件之后以及编写之前,应该策略性地放置陷阱语句。
答案 1 :(得分:0)
您的java命令可能在内部fork
和&两个进程中的父进程可能正在退出,使子进程在后台运行
因此bash脚本退出,& PID可用于操作系统。
另外,在另一个注释中,我建议在java命令之前添加exec
,因为(很可能),您希望监视java进程而不是父进程(bash包装器)。登记/>
通过添加exec
bash脚本,PID将由java进程继承。
要验证推测(1),请尝试我在(2)中描述的exec方法。签入ps -ef
输出,java进程确实产生了一个子进程。如果父进程已退出,则子进程应具有ppid = 1(init)