在 Bash 脚本中启动和停止进程

Start and Stop Process in Bash Script

我正在寻找一种基于 stdout 启动和停止 java 进程的简洁方法。基本上,我想在 Bash 中执行一个 for 循环,它启动一个带有输入变量的 java 命令,监视特定字符串 "Results:" 的标准输出,然后终止相同的进程,然后转到下一个,开始一个新的 java 进程并继续。

我已尝试使用 coproc,但无法获得接近预期的效果。

我会使用 screen。它适用于我的大部分脚本:

启动名为 myjava 命令的会话

screen -dmS myjava sh -c "/path/to/script.name parameters > /tmp/outfile"

这里您想用 bash 监视 /tmp/outfile ...(tail -f 或其他)

并用

终止你的会话myjava
screen -X -S myjava kill

假设您的 Java 代码在收到 SIGPIPE 时自行退出,您可以将输出通过管道传输到 grep 并让 grep exit as soon as it sees a match. Assuming you are using a version ofgrepthat supports the-moption (GNU and BSDgrepboth do), you can havegrep` 在第一次匹配后退出:

java ... | grep -m 1 'Results:'

一个小问题:由于缓冲,您的 java 程序可能会在 grep 实际看到 "Results" 行之前继续 运行 任意长的时间。


仅使用标准 grep,您可以使用 tee 来显示输出并在找到任何匹配项后退出。

java ... | grep 'Results:' | tee | grep -q '.*'

这遇到了同样的缓冲问题,但被放大了:不仅第一个 grep 在实际接收到 "Results" 行之前必须等待,而且 tee 可能同样需要在它最终得到相同的线路之前等待。此外,如果行太小,第一个 grep 可能永远不会产生更多输出,需要您等待 javatee 看到任何输入之前自然退出。

您可以像这样使用 coproc

coproc java …
grep -q -m1 'Results:' <&$COPROC && kill $COPROC_PID 

这将使 grep 从 java 输出中读取并在看到匹配行后立即将其终止。


如果您想查看 java 命令的输出而不是默默执行此操作,请使用 tee 打印输出并将其发送到 grep … && kill … 组。

coproc java …
tee <&$COPROC >(grep -q -m1 'Results:' && kill $COPROC_PID)