【问题标题】:How does one correctly kill processes in bash如何在 bash 中正确杀死进程
【发布时间】:2013-08-23 11:17:04
【问题描述】:

我使用以下脚本通过超时杀死进程:

# $1 - name of program and its command line

#launch program and remember PID
eval "$1" &
PID=$!

echo "Program '"$1"' started, PID="$PID

i=1
while [ $i -le 300 ]
do
 ps -p $PID >> /dev/null
 if [ $? -ne 0 ]
  then
   wait $PID
   exit $? #success, return rc of program
  fi

 i=$(($i+1))
 echo "waiting 1 second..."
 sleep 1
done

#program does not want to exit itself, kill it
echo "killing program..."
kill $PID
exit 1 #failed

到目前为止,它运行良好,但今天,我注意到 htop 中有一堆“挂起”进程,所以我检查了一下,结果发现,$PID 在这种情况下不是 ID程序进程,但脚本本身,我检查的所有时间,程序的 ID 是$PID+1。现在,问题是,我的假设是否正确,它将始终是 $PID+1,我不会通过将 kill $PID 替换为 kill $PID $($PID+1) 之类的东西来杀死重要的东西

编辑:$1 可能有几个要求,例如 ./bzip2 -ds sample3.bz2 -k

【问题讨论】:

标签: linux bash kill


【解决方案1】:

您可以通过以下更改简单地解决问题:

发件人:

eval "$1" &

收件人:

eval "$1 &"

原因在this answer中有解释。

【讨论】:

    【解决方案2】:

    我刚刚开始编写具有此功能的脚本。我打算称它为“超时”,但在我打开一个空白文件之前,我检查了是否已经有一个同名的命令。有...

    timeout

    编辑

    如果您需要“1”作为失败的返回值...

    timeout 1 nano -w; `if [[ $? == 124 ]] ; then exit 1 ; fi ; exit $?`
    

    【讨论】:

    • 我知道这个命令,但是 fom man If the command times out, then exit with status 124 不适合。有很多遗留脚本,其中“1”应该是挂起程序的返回码,所以我被绑在这里
    • @Shf 如果命令还没有完成,它不会有输出。你想要什么?
    • timeout 将在 timeout kill 后返回 124,但在大量脚本中,预计在这种情况下返回 1
    • 感谢您的精彩回复,但对我来说 eval "$1 &" 已解决问题
    【解决方案3】:

    普通的有什么问题

    ( eval "$1" ) &
    sleep 300
    kill %1
    

    【讨论】:

    • 我需要有进程的返回码,如果它提前完成,我需要等待 300 秒,因为这个脚本启动了很多次
    • (sleep 300; kill $PID ) & wait $PID
    • 感谢您的精彩回复,但对我来说 eval "$1 &" 已解决问题
    【解决方案4】:

    您正在后台处理eval,而不是它运行的命令,并且eval 是内置的shell,因此您正在分叉一个新的shell;这就是为什么(我认为)$! 是当前 shell 的 PID。

    一个简单的解决方案是避免使用eval(为此以及通常对安全性的担忧)。

    $1 "$@" &
    PID=$!
    

    确实,这不允许您将任意的bash 命令行(管道、&& 列表等)传递给您的脚本,但您的用例可能不需要支持这种泛化。你通常会传递什么命令?

    【讨论】:

    • 需要eval,因为<>被频繁使用,比如./cc_dry2 < dhryinput > results,没有eval bash很混乱
    【解决方案5】:

    另外,这里对你的代码进行了一些重构,也许你会从中学到一些东西:

    #launch program and remember PID
    eval "$1" &
    PID=$!
    
    echo "Program '$1' started, PID=$PID" # you can safely use single quotes inside double quotes, your variables are going to work in  " " as well!
    
    i=1
    while (( i <= 300 )) # use (( )) for math operations!
    do
        ps -p "$PID" >> /dev/null # it is a good rule to quote every variable, even if you're pretty sure that it doesn't contain spaces
        if [[ $? != 0 ]]; then # Try to use [[ ]] instead of [. It is modern bash syntax
            wait "$PID"
            exit "$?" #success, return rc of program
        fi
        ((i++))
        echo "waiting 1 second..."
        sleep 1
    done
    
    #program does not want to exit itself, kill it
    echo "killing program..."
    kill "$PID"
    exit 1 #failed
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-15
      相关资源
      最近更新 更多