运行Python脚本后终端搞砸了(不显示新行)

bli*_*ile 7 python terminal subprocess tty stty

我有一个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()
Run Code Online (Sandbox Code Playgroud)

有效命令执行如下:

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

它工作正常,除了我得到一个间歇性错误,我的终端在运行脚本后搞砸了(丢失换行符).从命令行"重置"修复它,但我不确定这是怎么回事.我注意到有时在元组输出的第一项结尾处有一个"\ r \n",有时它不在那里.请参阅以下内容,特别是" Permission denied\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 denied\r\n', 'Connection to server1.example.com closed.\r\n')
('grep: /etc/shadow: Permission denied\r\n', 'Connection to server2.example.com closed.\r\n')
[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 denied\r\n', 'Connection to server1.example.com closed.\r\n')
('grep: /etc/shadow: Permission denied\n', 'Connection to server2.example.com closed.\r\n')
                                 [user@/home/user]# [user@/home/user]# [user@/home/user]
Run Code Online (Sandbox Code Playgroud)

第二个输出略有修改,但显示缺少"\ r \n",以及运行脚本后我的提示如何"wacked".

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

只是想知道是否有人知道解决这个问题的方法,而不删除"-t"选项?

更新: 看起来我的tty设置在我的脚本中运行subprocess.Popen(...).communic()命令后被改变,无论我是否实际将输出打印到屏幕.我觉得这很奇怪.以下是我的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
Run Code Online (Sandbox Code Playgroud)

我想知道如何阻止沟通()改变我的终端设置?有可能,还是这个bug?

jhy*_*nds 8

我找到

stty sane
Run Code Online (Sandbox Code Playgroud)

将控制台恢复到以前的状态。我并没有真正理解这里的另一个答案,所以我这可以帮助某人。

这里找到了答案。


小智 5

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

在Perl中:

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

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

#Execute remote command prepending"stty -raw"

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

#Restore终端设置

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

希望它能帮到你!

其他非常有用的链接:

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

-Some 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-没有-A-密码