我有一个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 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]
第二个输出略有修改,但显示缺少“\ r”,以及运行脚本后我的提示如何“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
我想知道如何阻止沟通()改变我的终端设置?是可能的,还是这个错误?
答案 0 :(得分: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 \``;
希望它可以帮到你!
其他非常有用的链接:
- ssh和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
的“-t”答案 1 :(得分:4)
我找到了
<?php
if(isset($_POST['exportBtn']) && isset($_POST['sflt'])){
set_time_limit(0);
$arr = array();
$i=0;
foreach($_POST['sflt'] as $key => $value) {
$eflt = mysql_prep($_POST['sflt'][$key]);
$emodel = mysql_prep($_POST['smodel'][$key]);
$eengine = mysql_prep($_POST['sengine'][$key]);
$eloc = mysql_prep($_POST['sloc'][$key]);
$estye = mysql_prep($_POST['sstye'][$key]);
$ensvr = mysql_prep($_POST['snsvr'][$key]);
$eehd = mysql_prep($_POST['sehd'][$key]);
$epname = mysql_prep($_POST['spname'][$key]);
$epn = mysql_prep($_POST['spn'][$key]);
$ecu = mysql_prep($_POST['scu'][$key]);
$eqty = mysql_prep($_POST['sqty'][$key]);
$ett = mysql_prep($_POST['stt'][$key]);
$mtyp = mysql_prep($_POST['sstye'][$key]);
$mtyp2 = $mtyp=='T'?'T':'S';
$cby = $_SESSION['username'];
$ct = date('Y-m-d H:i:s');
array_push($arr,"('$eflt','$emodel','$eengine','$eloc','$estye','$ensvr','$eehd','$epname','$epn','$ecu','$eqty','$ett','$cby','$ct','$mtyp2')");
$i++;
if($i == 100){
$inExp = mysqli_query($link,"INSERT INTO tab_mydbtrans(fltno,model,engine,loc,serviceType,nextSvr,usageHr,partName,partNo,costUnit,qty,total,createdBy,created_at,mtype)VALUES".implode(',', $arr));
$arr = array();
$i=0;
}
}
//If any rows left at the end this code will insert them
if(count($arr) > 0){
$inExp = mysqli_query($link,"INSERT INTO tab_mydbtrans(fltno,model,engine,loc,serviceType,nextSvr,usageHr,partName,partNo,costUnit,qty,total,createdBy,created_at,mtype)VALUES".implode(',', $arr));
}
}
将控制台恢复到之前的状态。 我真的不明白其他答案,所以我帮助了一个人。
找到答案javax.jms.Message。