bash脚本中的澄清

时间:2014-01-15 05:44:23

标签: bash unix

我有一个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脚本的错误假设。

我不确定我是否正确。有人可以澄清一下。

2 个答案:

答案 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)

  1. 您的java命令可能在内部fork和&两个进程中的父进程可能正在退出,使子进程在后台运行 因此bash脚本退出,& PID可用于操作系统。

  2. 另外,在另一个注释中,我建议在java命令之前添加exec,因为(很可能),您希望监视java进程而不是父进程(bash包装器)。登记/> 通过添加exec bash脚本,PID将由java进程继承。

  3. 要验证推测(1),请尝试我在(2)中描述的exec方法。签入ps -ef输出,java进程确实产生了一个子进程。如果父进程已退出,则子进程应具有ppid = 1(init)