【问题标题】:Bash: How to send an openssl command and have the script output to stdin when it sees line XBash:当看到第 X 行时,如何发送 openssl 命令并将脚本输出到标准输入
【发布时间】:2017-05-08 15:21:20
【问题描述】:

是否可以在 bash 脚本中发送 openssl 命令,然后让脚本在将正确的文本输出到标准输入之前等待提示?

我希望能够:

  • 发送 openssl 命令
  • 等待 X 行出现
  • 如果 X 行未出现则报告故障
  • 等待 Y 行出现
  • 输出到标准输入
  • 更多处理...

我目前的方法是将 openssl 命令置于后台,将输出通过管道传输到一个文件(使用 tee,所以我也在终端中看到它)并使用 while 循环连续读取输出。

我的问题在于我输出到标准输入时。我的脚本检测到出现了 Y 行,但使用 cat <<< "my_input" 不起作用。我知道openssl命令正在等待输入,因为如果我此时手动输入命令,一切都OK。

任何想法我错过了什么?还是有更好的方法?

注意:我希望有一种不使用第三方应用程序的方法,例如下面提到的“期望”。

【问题讨论】:

  • Expect 是为解决此类问题而创建的。除了原来的 TCL 库之外,还有PythonPerlRuby 等多个版本。
  • 我希望不必使用任何外部库。我已更新我的问题以包含此信息。

标签: bash openssl


【解决方案1】:

如果您坚持使用 Bash:您需要调用 openssl,以便您拥有其标准输入的文件句柄,以便编写向其发送数据的脚本。例如,如果你有 Bash 4,

# Run openssl with stdin and stdout attached to pipes stored in ${OPENSSL[*]}
coproc OPENSSL {
    openssl ...
}

# Wait for a line to appear
while read -r -u ${OPENSSL[0]} line; do
    if [[ ${line} = X ]]; then
        break
    fi
done

# Send something to the input
echo 'hello, world!' >&${OPENSSL[1]}

# Close input
exec {OPENSSL[1]}>&-

# Forward everything from the output to our stdout
cat <&${OPENSSL[0]}

如果您有较早版本的 Bash,则需要使用命名管道命令来附加到进程的标准输入和标准输出。

如果你只需要附加到标准输入,有一些技巧:要么重定向一个子shell(这可能很难协调读取子shell之外的数据)

{
    echo 'hello, world! (from a subshell)'
} | openssl ... | tee ...

或使用进程替换。

exec {OPENSSL}> >(openssl ... | tee ...)
echo 'hello, world!' >&${OPENSSL}
exec {OPENSSL}>&-

【讨论】:

  • 谢谢,有道理!使用您的第一种方法,我收到以下错误:{OPENSSL[0]}: ambiguous redirect。这指向cat &lt;&amp;{OPENSSL[0]} 行。有什么想法吗?
  • @mfisher91 糟糕,应该是 cat &lt;&amp;${OPENSSL[0]},其他几个地方也有类似的修复。
  • 太好了。还有一个问题;所以,我想把它放在一个循环中,所以我的程序将建立 openssl 连接并每 X 分钟执行一次任务。如何终止当前的协同进程?我不想让很多协同流程处于打开状态!
  • @mfisher91 PID 将在$OPENSSL_PID 中,因为我们将数组命名为${OPENSSL[*]},所以你可以杀死它。但是在你关闭它的标准输入并完全读取它的标准输出之后,openssl 应该会自然终止。
猜你喜欢
  • 2011-02-02
  • 2022-08-14
  • 1970-01-01
  • 1970-01-01
  • 2014-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多