2011-01-11 115 views
4

我正在Python中运行ssh,而不使用像Paramiko这样的外部库。我有这样做的理由,而不是通过外部图书馆。“伪终端将不会被分配,因为stdin不是终端”当通过python运行ssh而没有paramiko

基本上是做这个的时候我做subprocess.Popen("ssh -t bla -- command")

我得到以下信息:

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

我与-t运行它的原因是我想要的远程命令时,我杀了我的Python终止脚本。

当我试着使用-t -t(给力了),我得到以下信息:

tcgetattr: Inappropriate ioctl for device 

有没有一种方法,我可以通过用Python -t运行我的ssh命令?

+0

如果你可以与远程设置的sshd胡闹,这应有助于:http://superuser.com/questions/396994/setting-ssh-to-terminate-remote-process-upon-disconnection – 2012-05-22 02:48:08

回答

2

我可否建议你问错了问题,而正确的问题可能是这样的“我如何确保当我的Python程序终止子进程终止”

你可以做一些聪明unix的东西像分配一个pty,并确保你的子进程使用这个std in out等等,以便ssh命令认为​​它正在和终端而不是管道通话,但这可能不是你真正想要做的。

+0

的SSH当我杀死我的python脚本时,子进程会终止。但是,它在远程主机上启动的命令不会终止,除非我将-t标志传递给ssh命令。 但是,当我将-t标志传递给ssh时,它不尊重那个标志,并且给了我粘贴在问题主体中的错误消息。 – 2011-01-12 00:13:19

0

这听起来像你真的要求旧的nohup命令的反向;也就是说,可以确保远程命令响应由TTY(PTY或psuedo-tty)驱动程序在其底层连接关闭时生成的HUP(挂断)信号。

就我个人而言,我怀疑Paramiko会比试图用子进程模块管理这个好得多。你可以让Paramiko打开连接,分配pty并执行你的命令而不会有任何困难;并且使用现有的known_hosts和身份文件(私钥)的代码相对比较简单。

这在ActiveState的配方Copy files over SSH using paramiko显示加载SSH的known_hosts的基础知识,使用的身份文件,并与任何SSH代理交互您可能正在运行。从那里,你要问的应该是简单的事:

您还可以使用SSH协议的TwistedConch实现。但是,围绕Twisted编程框架包头可能会更困难。

下面是扭曲一个简单的SSH服务器的一个例子,与PTY支持:Twisted Conch in 60 Seconds: PTY Requests 下面是一个SO仅一个星期线程你被张贴Best way to run remote commands thru ssh in Twisted?但并没有在所有覆盖PTY相关问题之前。查看文档twisted.conch.ssh.session表明它有pty支持;但将其列为“未记录”。

当然,你甚至可以用Pexpect去壳,产生一个shell到你的本地ssh客户端并通过它发送远程命令。这将最接近地模拟你从你自己的shell运行命令的方式。

1

要终止远程命令时python脚本就会被杀死,你可以(作为替代-t选项ssh)实现使用命名管道转换“EOF为SIGHUP”时的sshd标准输入是一种解决方法正在关闭(见Bug 396 - sshd orphans processes when no pty allocated)。

# sample code in Bash 

# press ctrl-d for EOF 
ssh localhost ' 
TUBE=/tmp/myfifo.fifo 
rm -f "$TUBE" 
mkfifo "$TUBE" 
#exec 3<>"$TUBE" 

<"$TUBE" sleep 100 & appPID=$! 

# cf. "OpenSSH and non-blocking mode", 
# http://lists.mindrot.org/pipermail/openssh-unix-dev/2005-July/023090.html 
#cat >"$TUBE" 
#socat -u STDIN "PIPE:$TUBE" 
dd of="$TUBE" bs=1 2>/dev/null 
#while IFS="" read -r -n 1 char; do printf '%s' "$char"; done > "$TUBE" 

#kill -HUP -$appPID 
kill $appPID 

rm -f "$TUBE" 
'