运行Python脚本后,终端出现问题(不显示新行)



我有一个Python脚本,用于使用Python子流程模块在多个主机上并行执行命令。它封装SSH,并基本上进行如下调用:

output = subprocess.Popen(["/bin/env", env, "/usr/bin/ssh", "-t", "%s@%s" % (user, host), "--", command], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()

有效的命令执行如下:

/bin/env TERM=$TERM:password /usr/bin/ssh -t "%s@%s" % (user, host), "--", command

它工作得很好,只是我遇到了一个间歇性错误,在运行脚本后,我的终端会出错(丢失换行符)。命令行中的"重置"可以修复它,但我不确定这到底是怎么发生的。我注意到,有时在元组输出的第一个项的末尾有一个"\r\n",有时它不在那里。请参阅以下内容,特别是"权限被拒绝\r\n"

**** Okay output ****
[user@/home/user]# ./command.py hosts.lists "grep root /etc/shadow"
Running command "grep root /etc/shadow" on hosts in file "hosts.test"
('grep: /etc/shadow: Permission deniedrn', 'Connection to server1.example.com closed.rn')
('grep: /etc/shadow: Permission deniedrn', 'Connection to server2.example.com closed.rn')
[user@/home/user]#

**** Output causes terminal to not display newlines ****
[user@/home/user]# ./command.py hosts.list "grep root /etc/shadow"
('grep: /etc/shadow: Permission deniedrn', 'Connection to server1.example.com closed.rn')
('grep: /etc/shadow: Permission deniedn', 'Connection to server2.example.com closed.rn')
                                 [user@/home/user]# [user@/home/user]# [user@/home/user]

第二个输出略有修改,但显示了缺少的"\r",以及运行脚本后我的提示如何变得"古怪"。

我认为这与在我的子流程命令中使用"-t"选项有关。不知怎么的,我失去了。如果我去掉"-t"选项,这个问题就会消失,但长话短说,我需要它来传递在远程机器上使用的环境变量(出于sudo的目的,我使用TERM变量来传递用户的密码是很不明智的,因为我不能假设AcceptEnv允许在远程sshd服务器上传递任意变量;我这样做是为了避免在命令行上传递密码,这将显示在远程机器的进程列表中)。

只是想知道是否有人知道在不删除"-t"选项的情况下绕过这一问题的方法?

更新:在脚本中运行子进程.Popen(…).communicate()命令后,我的tty设置似乎发生了更改,无论我是否真的将输出打印到屏幕上。我觉得这真的很奇怪。以下是我的tty配置中的前后差异(来自stty-a):

-ignbrk brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
-ignbrk brkint ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff

opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
-opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon -iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt

我想知道如何阻止communication()更改我的终端设置?有可能吗,还是这是一个bug?

我发现

stty sane

将控制台恢复到以前的状态。我真的不明白这里的另一个答案,所以我这有助于别人。

在这里找到答案。

我在Perl脚本中遇到了同样的问题。为了解决这个问题,我必须保存本地终端的当前设置(以便在脚本结束时恢复它),并在执行远程命令之前准备"stty-raw"。

所以在Perl中:

#保存当前终端设置(您可以在文件名中添加PID)

`stty-g>~/tmp/.currentTtySettings`;

#执行远程命令准备"stty-raw"

my@out=`ssh-t-quser@server1.example.com"stty-raw;grep root/etc/shadow"`;

#恢复终端设置

`stty\`cat ~/tmp/.currentTtySettings\``;

希望它能帮助你!

其他非常有用的链接:

-ssh和tty(-t选项)的详细说明https://unix.stackexchange.com/questions/151916/why-is-this-binary-file-being-changed

-Perl和ssh的一些灵感http://search.cpan.org/~bnegrao/Net-SSH-Expect-1.09/lib/Net/SSH/Expect.pod

-如何避免sudo的"-t"https://unix.stackexchange.com/questions/122616/why-do-i-need-a-tty-to-run-sudo-if-i-can-sudo-without-a-password

最新更新