具有多个要求用户输入的程序的 linux 管道
Posted
技术标签:
【中文标题】具有多个要求用户输入的程序的 linux 管道【英文标题】:linux pipe with multiple programs asking for user input 【发布时间】:2012-08-02 22:08:05 【问题描述】:我想知道如何创建管道
program 1 | ... | program N
其中多个程序要求用户输入。问题是|
并行启动程序,因此它们开始从终端并行读取。
对于这种情况,有一个管道 |
仅在程序 i 产生一些输出后启动程序 (i+1) 会很有用。
编辑:
例子:
cat /dev/sda | bzip2 | gpg -c | ssh user@host 'cat > backup'
这里gpg -c
和ssh
都要求输入密码。
此特定示例的解决方法是创建 ssh 密钥对,但这并非在每个系统上都可行,我想知道是否有通用解决方案。 gpg 还允许将密码短语作为命令行参数传递,但出于安全原因不建议这样做。
【问题讨论】:
将程序连接到管道后,它会从另一个程序而不是用户获取输入。你确定你想要一根管子吗?我真的想不出一个程序可以同时接受用户输入和从标准输入读取。 不是一个答案,而是一个可以为您指明正确方向的想法:您能否在每个程序周围包含代码以检查特定字符串的输出,一旦找到就更新标志并进行其他调用循环直到前一个程序的标志被更新,然后允许它们运行? 显示发生这种情况的具体示例。程序可以从stdin
和/dev/tty
读取数据,但这很不寻常。
@chepner:不,并非总是如此,程序也可以从tty
读取。而问题中的情况正是这种情况。
【参考方案1】:
你可以使用这个结构:
(read a; echo "$a"; cat) > file
例如:
$ (read a; echo "$a"; echo cat is started > /dev/stderr; cat) > file
1
cat is started
2
3
这里1
、2
和3
是从键盘输入的; cat is started
是由 echo 写的。
命令执行后file
的内容:
$ cat file
1
2
3
【讨论】:
【参考方案2】:我现在正在使用:
#!/bin/bash
sudo echo "I am root!"
sudo cat /dev/disk0 | bzip2 | gpg -c | (read -n 1 a; (echo -n "$a"; cat) | ssh user@host 'cat > backup')
第一个sudo
将阻止第二个再次询问密码。如上所述,read
推迟了 ssh 的启动。我使用-n 1
代替read
,因为我不想等待换行符,而-n
代替echo
来抑制换行符。
【讨论】:
sudo -v
将延长超时时间,如果您还没有通过验证,则会提示您输入密码。这让您不必想出一个无关的命令 (echo "I am root!"
) 来运行。【参考方案3】:
您可以使用--passphrase
选项为 gpg 提供密码。
对于 ssh,最佳 解决方案是按键登录。但是,如果您需要通过密码进行操作,expect
命令会很好。这是一个很好的例子:Use expect in bash script to provide password to SSH command
Expect 还允许您进行一些输入 - 因此,如果您不想硬编码您的密码,这可能是可行的方法。
【讨论】:
【参考方案4】:我之前几次需要类似的东西,管道中的第一个命令需要输入密码,而下一个命令不会自动满足这一点(就像less
所做的那样)。
与 Igor 的回复类似,我发现在子shell 中使用 read 很有用:
cmd1 | ( read; cat - | cmd2 )
【讨论】:
以上是关于具有多个要求用户输入的程序的 linux 管道的主要内容,如果未能解决你的问题,请参考以下文章
具有多个 BOT 集成的 Microsoft Chat BOT
在多个管道上创建具有多个输入源的单个管道的意义,每个管道都定义了单独的输入源?