【问题标题】:Safely kill background process started in bash script安全地杀死在 bash 脚本中启动的后台进程
【发布时间】:2021-08-12 22:30:55
【问题描述】:

假设我在 bash 脚本中启动了一个后台进程,在本例中为 http-server,我想在脚本退出时终止它。我可能会这样做:

# launch http-server in the background
http-server -p8080 &

# capture PID of background process
HTTP_PID=$!

trap "kill $HTTP_PID" EXIT 

# ... more stuff 

这似乎是捕获后台进程的PID的推荐方式,但是有一个问题:如果进程无法启动或稍后在任何时候失败,PID可能会被另一个进程回收并使用,其中如果我的kill 会杀死系统上的一些随机进程。

我怎样才能安全地仅杀死在此脚本中启动的进程,如果该进程已经死亡则什么都不做?

【问题讨论】:

    标签: linux bash


    【解决方案1】:

    这应该达到你的预期:

    trap "pkill --parent $$ http-server" EXIT
    

    杀死一个特定的pid:

    function killpid {
        local ppid=$1 pid=$2 cmd=$3
        local v_pid="$(ps -h --ppid $ppid -o pid,cmd | awk -v pid=$pid -v cmd="$cmd" '$1 == pid && $2 == cmd {print pid}')"
        if  test -n "$v_pid"; then
            echo "Killing $v_pid..."
            kill $v_pid
        fi
    }
    
    sleep 2 &
    echo "Spawning $!"
    sleep 2 &
    echo "Spawning $!"
    trap "killpid $$ $! sleep" EXIT
    

    测试后用http-server 替换sleep。

    【讨论】:

    • 嗯,不错的方法。使用--exact 可能会更安全一些。很遗憾,pkill 没有 --pid 选项,因为这不允许我针对我启动的http-server 的 特定 实例,尽管在这种情况下我只启动一个.
    • ‘ps’同时具有-pid和-ppid,当你真正杀死一个特定的进程id时,你应该能够验证它们
    猜你喜欢
    • 1970-01-01
    • 2012-09-30
    • 2015-09-10
    • 2016-01-24
    • 1970-01-01
    • 1970-01-01
    • 2012-09-01
    • 2013-07-24
    • 2011-08-08
    相关资源
    最近更新 更多