nohup

问题引出:这几天遇到一个问题,调用别人写的nginx啊、logstash啊等等一些启动脚本(如:nginx_start.sh)的时候,ps查看了一下进程,发现应用起来后,启动脚本的进竟然也还在,看了一下脚本,里面用nohup方法,理论上进程起来后,启动脚本的进程不应该还在才对,针对这个现象,自己做了一些测试。


一、模仿写了一个nginx“启动”脚本,如下:

#!/bin/bash

## 状态信息
nginx_status()
{
    # 查看状态
    if [ "x${pid}" != "x" ]; then
        echo "nginx (PID:$(echo -n ${pid})) is running..."
    else
        echo "nginx was stopped"
    fi
}

nginx_start()
{
    # 判断是否已启动
    [ "x${pid}" = "x" ] && nohup sleep 300 &
    sleep 1

    nginx_status
}

if [ "$USER" = "root" ]; then
    case $1 in
        start)
            nginx_start
            ;;
        status)
            nginx_status
            ;;
        *)
            echo "nothing"
    esac
else
    echo "User is $USER. You must be apps to run this script!"
fi

2、执行这个进程,出现如下的结果:启动进程尽然还在。

pstree查看一下:


3、多次测试,排除了启动脚本中sleep 1、后面调用nginx_status和最后的case的可能性。(这里测试过程比较简单,略)

4、多次测试,排除一些可能性后,再研究启动脚本的写法,

理论上来说,使用nohup &会进入后台执行,并不会影响父进程的正常退出,为了验证这个,做了如下尝试:

执行后发现:并不会出现启动脚本的进程。


5、这样,就把问题集中到了nohup &前面的语句了,仔细的想了一下,[ "x${pid}" = "x" ] && nohup sleep 300 &  这条语句,会不会是最后的&将命令放入后台执行的时候失败了,也就是会所这条语句并没有像预想中的那样进入后台执行,即进入后台“失败”,没有真正意义上的进入后台,从而影响了父进程的正常退出,这里只需要把sleep 300放入后台进行就可以了,为了排除前面可能带来的干扰,做了如下测试:

结果发现:启动脚本的进程没有了,也就是说sleep 300放入后台执行并没有影响父进程的退出。


6、上面的测试中,进入后台运行的程序都是需要执行一定时间或者是一直在执行的(引出这些测试的例子就是这种类型),那么如果是进入后台执行的程序很快就能执行完,结果会怎样?

运行结果:并没有发现启动脚本的进程


二、总结:

个人总结:查看一下资料后,个人觉得原因可能如下:nohup  &的执行依赖于前面[ "x${pid}" = "x" ] 的执行结果为真,即进入后台的程序依赖了父进程的一些资源,例如文件资源等,所以在子进程(后台进程)没有运行结束之前(文中模仿的就是进入后台的子进程还在运行中),这些依赖的资源没有被释放,导致父进程无法正常退出,一旦子进程执行完后(文中sleep 300后)依赖的父进程的资源释放后,父进程正常退出。

求其他高见。谢谢




















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章