Bash - 启动和终止进程

Posted

技术标签:

【中文标题】Bash - 启动和终止进程【英文标题】:Bash - starting and killing processes 【发布时间】:2011-02-21 13:39:31 【问题描述】:

我需要一些关于“简单”bash 脚本的建议。

我想启动一个程序“myprog”的大约 500 个实例,并在 x 秒后杀死所有实例

简而言之,我有一个在后台启动程序的循环,并在sleep x(秒数)之后使用程序名称调用pkill

我的问题是:

    如何验证 10 秒后所有 500 个实例都在运行? ps 和 grep 结合计数还是有其他方法?

    如何计算 pkill(或类似的 kill 函数)实际杀死了多少进程(这样就没有任何进程在实际时间限制之前终止)?

    如何重定向pkill(或类似的kill函数)的输出,使其不输出被杀死的进程信息,从而避免./initializeTest: line 250: 7566 Terminated ./$myprog的500行。重定向到 /dev/null 没有成功。

【问题讨论】:

请看Process Management。 【参考方案1】:

在 bash 中有 ulimit 命令控制(子)shell 的资源。

例如,保证最多使用 10 秒的 cpu 时间然后死:

(ulimit -t 10; ./do_something)

这并不能回答您的问题,但希望对您有所帮助。

【讨论】:

保证?我可以退款吗? time (ulimit -t 3; sleep 7) 输出:7. @Dennis:但这并没有占用太多 CPU 时间吗? :) 但是 OP 询问的是实时性。 @Dennis:(a) 我知道,这就是为什么我说“这不能回答你的问题”,(b) OP 的流程可能比 sleep 和 (c) ulimit 的许多其他选项在这里可能有用。【参考方案2】:

1,2。使用pgrep。我不记得pgrep 是否有-c 参数,所以你可能需要将它传递给wc -l

3:该输出是由你的 shell 的作业控制产生的。我认为如果您将其作为脚本运行(而不是在交互式外壳中),则不应该有这样的输出。对于交互式 shell,有多种方法可以关闭它,但它们取决于 shell,因此请参阅 shell 手册。

【讨论】:

感谢您的有用提示。 pgrep 确实有 -c 标志,并给出与 ps | 相同的结果。 grep 组合。从现在开始将使用它来使内容更具可读性。 @Milan:这不仅更具可读性,而且实际上更可靠。 (例如,ps | grep combo 可能与 grep 本身匹配,因为 combo 在其命令行中。) 确实如此。当我计算实例时,我总是使用 grep [x]xxx ,但是当我累了时可能会错过它。输出确实是由我的 shell 的作业控制产生的。这就解释了为什么我的“重定向”失败了。感谢您提供非常有用的信息。【参考方案3】:

好吧,我的 2 美分:

    ps 和 grep 可以完成这项工作。顺便说一句,我发现 kill -0 $pid 更好:)(它会告诉您进程是否正在运行) 您可以使用 ps/grep 或 kill -0。对于您的问题,我将在后台启动所有进程并使用$! 获取它们的pid,将它们存储在数组或列表中,然后使用kill -0 获取所有进程的状态。 使用&>2>&1,因为它可能写在stderr 上

my2c

【讨论】:

感谢您的快速回复。当我尝试重定向时,我使用 &> 来重定向所有不起作用的输出。重定向到标准输出,然后重定向到 /dev/null 也不起作用。【参考方案4】:

为了确保每个进程在被杀死之前获得公平的 10 秒份额,我会将每个命令用它自己的 sleep && kill 包装在一个子 shell 中。

function run_with_tmout 
    CMD=$1; TMOUT=$2
    $CMD & 
    PID=$!
    sleep $TMOUT
    kill $PID 


for ((i=0; i < 500; i++)); do 
    run_with_tmout ./myprog 10 &
done

# wait for all child processes to end
wait  && echo "all done"

有关更完整的示例,请参阅this example from bashcookbook.com,它首先检查进程是否仍在运行,然后在诉诸SIGKILL 之前尝试kill -s SIGTERM

【讨论】:

如果kill -0 失败,这意味着该PID 上没有进程。它不会试图杀死进程;它只是检查是否存在。你应该做 SIGTERM、SIGQUIT、SIGINT、SIGHUP before you do SIGKILL。 谢谢丹尼斯,我错误地引用了这个例子。固定答案。【参考方案5】:

我一直在使用类似以下的方法来获取 pid 列表。

PS=$(ps ax | sed s/^' '*// | grep java | grep program_name | cut -d' ' -f1)

然后我使用kill $PS 阻止他们。

!/bin/bash
PS=$(ps ax | sed s/^' '*// | grep java | grep program_name | cut -d' ' -f1)
kill $PS

【讨论】:

以上是关于Bash - 启动和终止进程的主要内容,如果未能解决你的问题,请参考以下文章

markdown 使用bash和regex在一行中查找并终止进程

结束 mpirun 进程会终止 bash 循环

如何用CMD命令终止和启动进程?

简述linux进程的启动、终止的方式以及如何进行进程的查看

第5章 进程环境_进程的启动和终止

在while循环中自毁子进程(Bash)