使用pexpect时关闭ssh连接的正确方法是什么?

2024-10-01 09:16:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用pythonpexpect(和winpexpect)通过ssh执行命令

if platform.system() == 'Windows':
    pexpectmodname = "winpexpect"
    from winpexpect import winspawn as spawn
else:
    pexpectmodname = "pexpect"
    from pexpect import spawn

pexpectmod = __import__(pexpectmodname)

...

# connect
shellCmd = "ssh %s %d -l %s %s" % (portParam, port, username, server.host)
self.spawn = spawn(shellCmd, timeout=self.timeout, env=os.environ, ignore_sighup=False)

...
# DO WORK WITH SSH
...

# close ssh connection #1 (send exit)
self.spawn.sendline('exit')
index = self.spawn.expect([pexpectmod.EOF, "(?i)there are stopped jobs"])
if index == 1:
    self.spawn.sendline("exit")
    self.spawn.expect([pexpect.EOF])

# close ssh connection #2 (check isalive, send exit and close)
if self.spawn.isalive():
    self.spawn.sendline('exit')
    self.spawn.close()

# close ssh connection #3 (send sigkill)
import signal
self.spawn.kill(signal.SIGKILL)

如何关闭self.spawn生成以确保ssh会话已关闭? Windows和UNIX的crossplatform是什么?在


Tags: fromimportselfsendcloseifwindowsexit
2条回答

如果您的目标只是通过SSH执行命令,那么还可以考虑使用Paramiko

import paramiko

# Create a new client
client = paramiko.SSHClient()
# Connect to your remote
client.connect('127.0.0.1', username='john', password='doe')

# Execute a command
stdin, stdout, stderr = client.exec_command("pwd")

# Do anything you want with `stdout` and `stderr`
# Execute as many other commands as you want

# When you are done, close your connection
client.close()

它是一个纯Python包,每次使用它都能很好地工作。在

优雅的方法是发送exit\rCTRL-D,然后等待EOF。但是,在完成SSH会话之后直接退出脚本(Expect、pexpect或winexpect)也可以,而不关心SSH会话的退出状态。当脚本退出时(不管它是否干净),操作系统内核会为您关闭SSH会话(TCP连接)。SSH服务器不会对此抱怨。在

pexpect.spawn.close()将关闭pty,而pty又会将SIGHUP发送到shell,后者将终止(杀死)shell,除非shell忽略SIGHUP。这就像在shell仍在运行时关闭PuTTY(或gnome-terminal,…)窗口。在

更新:

上述语句假设所有应用程序(Expect、pexpect、winexpect和SSH-server)都得到了很好的实现。我有一个系统(ESXi),当SSH连接未完全关闭时,SSH服务器无法回收已分配的pty。因此,过了一段时间后,虽然SSH身份验证成功,但我无法再获得PTY。在

相关问题 更多 >