简体   繁体   English

如何正确杀死bash中的进程

[英]How does one correctly kill processes in bash

I use the following script to kill process by timeout: 我使用以下脚本按超时终止进程:

# $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

So far, it have worked excellent, but today, i've noticed a bunch of 'hanging' processes in htop, so i've checked out and it turns out, that $PID in this case is not ID of the program process but of the script itself, and all the times i checked, ID of the program is $PID+1 . 到目前为止,它的运行效果非常好,但是今天,我注意到htop中有一堆“挂起”的进程,所以我已经检查了一下,结果发现,在这种情况下, $PID不是程序进程的ID,而是脚本本身,并且我每次检查时,程序的ID都是$PID+1 Now, the question is, am i correct to assume, that it will always be $PID+1 and i won't kill something important by replacing kill $PID with something like kill $PID $($PID+1) 现在,问题是,我是否正确假设,它将始终是$PID+1并且我不会通过将kill $PID替换kill $PID kill $PID $($PID+1)类的东西来kill $PID重要的东西

EDIT: $1 may have several urguments, like ./bzip2 -ds sample3.bz2 -k 编辑: $1可能有一些麻烦,例如./bzip2 -ds sample3.bz2 -k

You can solve the problem simply with the following change: 您可以通过以下更改简单地解决问题:

From: 从:

eval "$1" &

To: 至:

eval "$1 &"

The reason is explained in this answer . 原因在此答案中说明。

I just started writing a script with this functionality. 我刚刚开始使用此功能编写脚本。 I was going to call it "timeout" but before I opened a blank file, I checked to see if there was already a command with the same name. 我打算将其称为“超时”,但是在打开空白文件之前,我检查了是否已经有一个同名命令。 There was... 有...

timeout 暂停

edit 编辑

If you need "1" specifically as a return value on failure... 如果您特别需要“ 1”作为失败时的返回值...

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

What's wrong with plain 平原怎么了

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

You are backgrounding eval , not the command it runs, and eval is a shell built-in, so you are forking a new shell; 您将eval作为后台程序,而不是它运行的命令,并且eval是内置的shell,因此您要派生一个新的shell。 that's why (I think) $! 这就是为什么(我认为) $! is the PID of the current shell. 是当前外壳的PID。

One simple solution is to avoid using eval (for this and the usual concerns over security). 一种简单的解决方案是避免使用eval (为此以及通常的安全性问题)。

$1 "$@" &
PID=$!

True, this doesn't allow you to pass an arbitrary bash command line (pipeline, && list, etc) to your script, but your use case may not need to support such generalization. 的确,这不允许您将任意bash命令行(管道,&&列表等)传递给脚本,但是您的用例可能不需要支持这种概括。 What commands do you typically pass? 您通常会传递什么命令?

Also, here is some refactoring to your code, maybe you will learn something from it: 另外,这是对代码的一些重构,也许您会从中学习到一些东西:

#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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM