我使用以下脚本通过超时终止进程:
# $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,以及我检查的所有时间,程序的ID是$PID+1
。现在,问题是,我是否正确地假设它始终是$PID+1
并且我不会通过用kill $PID
kill $PID $($PID+1)
来杀死一些重要内容
编辑:$1
可能有多个参数,例如./bzip2 -ds sample3.bz2 -k
答案 0 :(得分:3)
答案 1 :(得分:2)
我刚开始用这个功能编写脚本。我打算称之为“超时”,但在我打开一个空白文件之前,我检查是否已经有一个同名的命令。有... ...
修改强>
如果您特别需要“1”作为失败的返回值......
timeout 1 nano -w; `if [[ $? == 124 ]] ; then exit 1 ; fi ; exit $?`
答案 2 :(得分:1)
普通
有什么问题( eval "$1" ) &
sleep 300
kill %1
答案 3 :(得分:1)
你是后台eval
,而不是它运行的命令,而eval
是一个内置的shell,所以你要求一个新的shell;这就是为什么(我认为)$!
是当前shell的PID。
一个简单的解决方案是避免使用eval
(为此以及通常对安全性的担忧)。
$1 "$@" &
PID=$!
是的,这不允许您将任意bash
命令行(管道,&& list等)传递给您的脚本,但您的用例可能不需要支持此类泛化。你通常会传递什么命令?
答案 4 :(得分:0)
此外,这里有一些重构你的代码,也许你会从中学到一些东西:
#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