我想知道如何创建管道
program 1 | ... | program N
其中多个程序要求用户输入。问题是|
并行启动程序,因此它们开始并行地从终端读取。
对于这种情况,只有在程序i产生一些输出之后才有一个管道|
启动程序(i + 1)会很有用。
修改
示例:
cat /dev/sda | bzip2 | gpg -c | ssh user@host 'cat > backup'
此处gpg -c
以及ssh
都要求输入密码。
此特定示例的解决方法是创建ssh密钥对,但这在每个系统上都不可能,我想知道是否存在一般解决方案。 此外,gpg允许将密码短语作为命令行参数传递,但出于安全原因,不建议这样做。
答案 0 :(得分: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
答案 1 :(得分:1)
我现在正在使用:
#!/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
来压制换行符。
答案 2 :(得分:0)
您可以使用--passphrase
选项为gpg提供密码。
对于ssh,最佳解决方案是按键登录。但是如果您需要通过密码进行操作,expect
命令就会很好。这是一个很好的例子:Use expect in bash script to provide password to SSH command
Expect还允许您输入一些内容 - 因此,如果您不想对密码进行硬编码,则可能需要这样做。
答案 3 :(得分:0)
之前我需要类似的东西,管道中的第一个命令需要输入密码,而下一个命令不会自动满足此要求(就像less
所做的那样)。
与Igor的回复类似,我发现在子shell中使用read非常有用:
cmd1 | ( read; cat - | cmd2 )