ssh执行远程命令的坑

2018-02-01  本文已影响281人  yiduyangyi

要做的事情

远程主机(your.host.com)上部署有docker,期望从本地开发机ssh到远程主机,在指定的容器中执行命令,基本命令如下:

/usr/bin/ssh -i /home/users/yangjinfeng02/.ssh/.id_rsa  -oUserKnownHostsFile=/dev/null -oStrictHostKeyChecking=no -t rd@your.host.com "sudo docker exec -u rd -it 0284c4594aecc7689de407e8d2aa9106edaf646b000e3c362ad95f6dde5c9f0b bash -c 'pwd'"

出现的问题

登入shell终端,手动执行上面的命令,一切ok。但是放到crontab中无法执行,重定向输出到文件,得到如下信息

Pseudo-terminal will not be allocated because stdin is not a terminal. 

问题排查与解决

注意到ssh命令中的-t参数,是用来控制给ssh分配伪终端。查看ssh帮助

-T      Disable pseudo-tty allocation.

-t      Force pseudo-tty allocation.  This can be used to execute arbitrary screen-based programs on a remote machine, which can be very useful, e.g., when implementing
             menu services.  Multiple -t options force tty allocation, even if ssh has no local tty.

注意到上述问题出错信息,结合ssh -t参数的含义,
Multiple -t options force tty allocation, even if ssh has no local tty.
可看出问题是在于分配终端引起的。

使用 ssh -t -t 执行,发现crontab下运行正常,问题得以解决。

延伸1——不分配伪终端

既然是终端分配导致的,那么根据ssh -T参数的含义,是否可以disable伪终端的分配呢?可以进行试验,执行如下命令

/usr/bin/ssh -i /home/users/yangjinfeng02/.ssh/.id_rsa  -oUserKnownHostsFile=/dev/null -oStrictHostKeyChecking=no -T rd@your.host.com "sudo docker exec -u rd -it 0284c4594aecc7689de407e8d2aa9106edaf646b000e3c362ad95f6dde5c9f0b bash -c 'pwd'"

此时不管是命令行,还是crontab里,均无法运行。提示如下错误信息

sudo: sorry, you must have a tty to run sudo

出现该问题,是因为sudo命令必须在终端中执行。如果要突破该限制,需要修改/etc/sudoers,有两种选择

  1. Replace Defaults requiretty by Defaults !requiretty in your /etc/sudoers. This will impact your global sudo configuration.

  2. Alternatively, you can change this configuration at a per user, per group or per command basis

Defaults!/path/to/my/bin !requiretty
Defaults:myuser !requiretty

延伸2——登录shell和非登录shell的区别

直接在终端里执行shell命令,与crontab里执行,本质区别是二者环境变量的差异。

登录shell将查找4个不同的启动文件来处理其中的命令。 bash shell处理文件的顺序如下:
1:/etc/profile
2:/etc/profile.d等待配置文件
3:$HOME/.bash_profile 会加载$HOME/.bashrc和/etc/bashrc
4:$HOME/.bash_login
5:$HOME/.profile

非登入shell则按如下顺序加载配置文件
1:/etc/bashrc
2:~/.bashrc

上一篇下一篇

猜你喜欢

热点阅读