首先,关于术语的注释...
“背景”和“前景”是控制终端的概念,也就是说,它们与您键入ctrl+C,ctrl+Z等时发生的情况有关(哪个进程获取信号),进程是否可以从终端设备读取(“背景” " 进程得到一个SIGTTIN
默认情况下会导致它停止的),依此类推。
很明显,这与您想要实现的目标无关。相反,你有一个行为不端的程序(或程序套件)需要一些特殊的溺爱:当服务器第一次启动时,它需要一些手牵手到某个点,之后就可以了。一旦输出一些文本字符串,手持就可以停止(请参阅您的相关问题或下面的技术)。
这里有一个很大的潜在问题:很多程序,当它们的输出被重定向到管道或文件时,直到它们打印出一个“块”的输出值,或者正在退出时才产生输出。如果是这种情况,一个简单的:
start-server-command | cat
不会打印您要查找的行(因此这是判断您是否也必须解决此问题的一种快速方法)。如果是这样,您将需要类似expect的东西,这是实现您想要的完全不同的方式。
不过,假设这不是问题,让我们尝试一种完全在 shell 中的方法。
您需要运行start-server-command
并保存进程 ID,以便您可以(最终)向其发送SIGINT
信号(就像ctrl+C进程“在前台”一样,但您是从脚本执行此操作,而不是从控制终端,因此脚本无法按下任何键)。幸运的是sh
,有一个专门用于此的语法。
首先让我们创建一个临时文件:
#! /bin/sh
# myscript - script to run server, check for startup, then run tests
TMPFILE=$(mktemp -t myscript) || exit 1 # create /tmp/myscript.<unique>
trap "rm -f $TMPFILE" 0 1 2 3 15 # arrange to clean up when done
现在启动服务器并保存它的 PID:
start-server-command > $TMPFILE & # start server, save output in file
SERVER_PID=$! # and save its PID so we can end it
trap "kill -INT $SERVER_PID; rm -f $TMPFILE" 0 1 2 3 15 # adjust cleanup
现在您需要扫描$TMPFILE
直到出现所需的输出,就像在另一个问题中一样。因为这需要一定数量的轮询,所以您应该插入延迟。检查服务器是否失败并终止而没有到达“开始”点也可能是明智的。
while ! grep '^Server started, Press Control+C to exit$' >/dev/null; do
# message has not yet appeared, is server still starting?
if kill -0 $SERVER_PID 2>/dev/null; then
# server is running; let's wait a bit and try grepping again
sleep 1 # or other delay interval
else
echo "ERROR: server terminated without starting properly" 1>&2
exit 1
fi
done
(这里kill -0
用来测试进程是否还存在;如果不存在,则退出。“清理”kill -INT
会产生错误消息,但可能没问题。如果不存在,要么重定向该kill
命令的错误输出,要么调整清理或手动执行,如下所示。)
此时,服务器正在运行,您可以进行测试。当您希望它像用户点击一样退出时ctrl+C,请发送一个SIGINT
with kill -INT
。
因为kill -INT
在trap
脚本退出 (0) 以及脚本被SIGHUP
(1)、SIGINT
(2)、SIGQUIT
(3) 和SIGTERM
(15) 终止时的集合中有一个 - 这就是:
trap "do some stuff" 0 1 2 3 15
部分——此时你可以简单地让你的脚本退出,除非你也想专门等待服务器退出。如果你想要,也许:
kill -INT $SERVER_PID; rm -f $TMPFILE # do the pre-arranged cleanup now
trap - 0 1 2 3 15 # don't need it arranged anymore
wait $SERVER_PID # wait for server to finish exit
将是适当的。
(显然以上都没有经过测试,但这是一般框架。)