Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
管道化ssh sudo的输出_Ssh_Sudo_Tty - Fatal编程技术网

管道化ssh sudo的输出

管道化ssh sudo的输出,ssh,sudo,tty,Ssh,Sudo,Tty,我有时需要在远程服务器上以root用户身份运行命令,并在本地服务器上解析命令的输出。远程服务器不允许通过ssh进行root登录,但以需要密码的方式配置了sudo。我需要做的一个简单例子是 ssh remote sudo echo bar | tr bar foo (显然,在这个简化的示例中,没有充分的理由需要在另一台机器上运行echo,而不是tr:这只是一个玩具示例来解释我要做的事情。) 如果我运行上面的命令,我会得到一个错误,sudo无法提示输入密码: richard@local:~$ ss

我有时需要在远程服务器上以root用户身份运行命令,并在本地服务器上解析命令的输出。远程服务器不允许通过
ssh
进行root登录,但以需要密码的方式配置了
sudo
。我需要做的一个简单例子是

ssh remote sudo echo bar | tr bar foo
(显然,在这个简化的示例中,没有充分的理由需要在另一台机器上运行
echo
,而不是
tr
:这只是一个玩具示例来解释我要做的事情。)

如果我运行上面的命令,我会得到一个错误,sudo无法提示输入密码:

richard@local:~$ ssh remote sudo echo bar | tr bar foo
sudo: no tty present and no askpass program specified
我可以尝试解决这个问题的一种方法是将
-t
选项添加到
ssh
。如果我这样做,
sudo
会等待并接受密码,但是
ssh
的伪终端的输出会转到stdout,这意味着sudo提示消息通过管道传输到
tr
,而不会显示给用户。如果用户不知道sudo正在等待密码,他们会认为脚本已挂起,将提示消息传递到管道可能会中断进一步的处理:

richard@local:~$ ssh -t remote sudo echo bar | tr bar foo
[sudo] posswood foo oichood: 
foo
(这个公认愚蠢的示例显示,提示符已由输出管道所指向的
tr
命令处理。)

我可以看到的另一种解决方法是将
-S
选项添加到
sudo
。如果我这样做,
sudo
会在stderr上提示输入密码,因此提示不会在管道中传递。这很好,但是
sudo
也接受标准输入上的密码,这意味着它会回显到终端,任何人都可以从用户的肩膀上看到它:

richard@local:~$ ssh remote sudo -S echo bar | tr bar foo
[sudo] password for richard: p8ssw0rd
foo
我已经找到了解决这两个选项问题的不雅观的方法,但是如果用户第一次密码错误,我的解决方法就会遇到问题。这本身就是一个问题。例如:

richard@local:~$ echo "[sudo] password for $USER:"; \
  ssh -t remote sudo echo bar | tail +2 | tr bar foo

richard@local:~$ (read -s password; echo $password; echo >&2) \
  | ssh remote sudo -S echo bar | tr bar foo

我相信一定有一个很好的解决办法,因为这似乎不是一件不寻常的事情。有什么想法吗?

我想到的最佳解决方案是使用
sudo-S
并禁用本地echo,这样在键入密码时不会显示密码:

$ { stty -echo; ssh remote sudo -S echo hello; stty echo; echo 1>&2; }
[sudo] password for user:
hello
这使得sudo负责密码提示,因此,如果用户输入的密码错误,它可以正常工作


我认为任何使用
ssh-t
的解决方案都无法正常工作,因为它将stderr和stdout结合在一起。

首先为什么要使用
sudo
进行
ssh
呢?您建议我如何在不允许root登录的远程服务器上以root身份执行代码(即,
/etc/ssh/sshd_config
中有
permitrotlogin no
),@jww?也许有更好的解决方案,但我不能马上想到。在
1>&2
之后缺少一个分号。如果你想在正确的位置回显新行,你想在回显远程内容之前回显:即
{stty-echo;ssh remote sudo-S“echo 1>&2;echo bar”;stty echo;}| tr bar foo
修复了缺少分号的问题。谢谢!这是一个非常有用的示例,用于在终端上输出。如果您将输出重定向到一个文件或一个不提供任何输出的命令,那么无论换行符出现在何处,您都可以使用我的稍微简单的版本(无需引用)。