这是Willie Wheeler答案的修改版本,该答案通过tar传输文件,但还支持将密码传递给远程主机上的sudo。
(stty -echo; read passwd; stty echo; echo $passwd; tar -cz foo.*) \
| ssh remote_host "sudo -S bash -c \"tar -C /var/www/ -xz; echo\""
一点点额外的魔力是sudo的-S选项。在sudo手册页中:
-S,--stdin将提示写入标准错误,并从标准输入中读取密码,而不使用终端设备。密码后必须带有换行符。
现在,我们实际上希望将tar的输出通过管道传递到ssh,并将ssh的stdin重定向到tar的stdout,从而消除了将密码从交互式终端传递到sudo的任何方法。(我们可以在远端使用sudo的ASKPASS功能,但这是另一回事。)我们可以通过预先捕获密码并将其放在tar输出中(通过在子shell中执行这些操作并将其输出管道化)来将密码输入sudo中。将subshell放入ssh。这还具有一个额外的优点,即不会在交互外壳中保留包含悬空密码的环境变量。
您会注意到我没有使用-p选项执行“读取”来显示提示。这是因为来自sudo的密码提示已通过ssh方便地传递回了交互式shell的stderr。您可能会想:“鉴于sudo在管道右侧的ssh中运行,sudo如何执行?” 当我们执行多个命令并将一个命令的输出传递到另一个命令时,父外壳程序(在本例中为交互式外壳程序)将在执行前一个命令后立即按顺序执行每个命令。在执行管道后面的每个命令时,父外壳程序会将左侧的stdout附加(重定向)到右侧的stdin。然后,在通过过程时,输出变为输入。
$ (stty -echo; read passwd; stty echo; echo $passwd; tar -cz foo.*) | ssh
remote_host "sudo -S bash -c \"tar -C /var/www/ -xz; echo\""
[sudo] password for bruce:
[1]+ Stopped ( stty -echo; read passwd; stty echo; echo
$passwd; tar -cz foo.* ) | ssh remote_host "sudo -S bash -c \"tar -C
/var/www/ -xz; echo\""
$ pstree -lap $$
bash,7168
├─bash,7969
├─pstree,7972 -lap 7168
└─ssh,7970 remote_host sudo -S bash -c "tar -C /var/www/ -xz; echo"`
我们的交互式外壳是PID 7168,子外壳是PID 7969,而ssh进程是PID 7970。
唯一的缺点是read会在sudo有时间将其提示发送回之前接受输入。在快速连接和快速远程主机上,您不会注意到这一点,但如果两者都很慢,则可能会发现这一点。任何延迟都不会影响输入提示的能力;它可能会在您开始键入后出现。
注意,我只是将“ remote_Host”的主机文件条目添加到了用于演示的本地计算机上。