bash序列:等待输出,然后开始下一个程序
题
就我而言,我必须跑 openvpn
在 ssh'ing 进入服务器之前,以及 openvpn
命令回显“初始化序列已完成”。
所以,我希望我的脚本能够设置 openvpn
然后ssh进去。
我的问题是:如何在后台执行 bash 中的命令并在运行另一个程序之前等待它回显“完成”?
我目前的做法是打开 2 个终端窗格,其中一个正在运行:
sudo openvpn --config FILE
在另一个我运行:
ssh SERVER
一旦第一个终端窗格向我显示“初始化序列已完成”文本。
解决方案
看来你想要 在后台运行 openvpn 作为进程,同时在前台处理其标准输出.
exec 3< <(sudo openvpn --config FILE)
sed '/Initialization Sequence Completed$/q' <&3 ; cat <&3 &
# VPN initialization is now complete and running in the background
ssh SERVER
解释
让我们把它分成几部分:
echo <(sudo openvpn --config FILE)
会打印出类似的东西/dev/fd63
- 这
<(..)
运行 开放VPN 在背景中,并且... - 将其标准输出附加到文件描述符,该文件描述符由以下命令打印出来
echo
- 这
exec 3< /dev/fd63
- (在哪里 /dev/fd63 是从步骤 1 打印的文件描述符)
- 这告诉 shell 打开文件描述符(/dev/fd63)用于阅读,并且...
- 使其在文件描述符中可用
3
sed '/Initialization Sequence Completed$/q' <&3
- 现在我们跑 sed 在前台,但让它从文件描述符中读取
3
我们刚刚开业 - 立刻 sed 看到当前行以“初始化序列完成”结束,它退出( /q 部分)
- 现在我们跑 sed 在前台,但让它从文件描述符中读取
cat <&3 &
- 开放VPN 将继续写入文件描述符
3
如果没有从中读取任何内容,最终会阻塞 - 为了防止这种情况,我们运行 猫 在后台读取输出的其余部分
- 开放VPN 将继续写入文件描述符
基本思想是运行 openvpn
在后台,但在某处捕获其输出,以便我们可以在前台运行一个命令,该命令将阻塞,直到它读取魔术词“初始化序列完成”。上面的代码尝试在不创建混乱的临时文件的情况下完成此操作,但更简单的方法可能只是使用临时文件。
其他提示
使用 -m 1
和...一起 --line-buffered
在 grep 中,在连续流中的第一个匹配后终止 grep。这应该有效:
sudo openvpn --config FILE | grep -m "Initialization Sequence Completed" --line-buffered && ssh SERVER
不隶属于 StackOverflow