就我而言,我必须跑 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

解释

让我们把它分成几部分:

  1. echo <(sudo openvpn --config FILE) 会打印出类似的东西 /dev/fd63
    • <(..) 运行 开放VPN 在背景中,并且...
    • 将其标准输出附加到文件描述符,该文件描述符由以下命令打印出来 echo
  2. exec 3< /dev/fd63
    • (在哪里 /dev/fd63 是从步骤 1 打印的文件描述符)
    • 这告诉 shell 打开文件描述符(/dev/fd63)用于阅读,并且...
    • 使其在文件描述符中可用 3
  3. sed '/Initialization Sequence Completed$/q' <&3
    • 现在我们跑 sed 在前台,但让它从文件描述符中读取 3 我们刚刚开业
    • 立刻 sed 看到当前行以“初始化序列完成”结束,它退出( /q 部分)
  4. cat <&3 &
    • 开放VPN 将继续写入文件描述符 3 如果没有从中读取任何内容,最终会阻塞
    • 为了防止这种情况,我们运行 在后台读取输出的其余部分

基本思想是运行 openvpn 在后台,但在某处捕获其输出,以便我们可以在前台运行一个命令,该命令将阻塞,直到它读取魔术词“初始化序列完成”。上面的代码尝试在不创建混乱的临时文件的情况下完成此操作,但更简单的方法可能只是使用临时文件。

其他提示

使用 -m 1 和...一起 --line-buffered 在 grep 中,在连续流中的第一个匹配后终止 grep。这应该有效:

sudo openvpn --config FILE | grep -m "Initialization Sequence Completed" --line-buffered && ssh SERVER
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top