Paramiko和exec_command - 杀死远程进程?

vic*_*ooi 13 python ssh signals solaris paramiko

我正在将Paramiko用于tail -f远程服务器上的文件.

以前,我们正在运行此通道ssh -t,但事实证明这种情况很脆弱,并且-t导致我们的远程调度系统出现问题.

我的问题是当脚本捕获SIGINT时如何杀死尾巴?

我的脚本(基于python paramiko模块中长期运行的ssh命令(以及如何结束它们))

#!/usr/bin/env python2
import paramiko
import select

client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect('someserver', username='victorhooi', password='blahblah')
transport = client.get_transport()
channel = transport.open_session()

channel.exec_command("tail -f /home/victorhooi/macbeth.txt")
while True:
    try:
        rl, wl, xl = select.select([channel],[],[],0.0)
        if len(rl) > 0:
            # Must be stdout
            print channel.recv(1024)
    except KeyboardInterrupt:
        print("Caught control-C")
        client.close()
        channel.close()
        exit(0)
Run Code Online (Sandbox Code Playgroud)

该脚本Ctrl-C成功捕获了我的结尾.但是,它使tail -f进程在远程系统上运行.

client.close()和channel.close()似乎都没有终止它.

我可以在except块中发出什么命令来杀死它?

远程服务器正在运行Solaris 10.

Mik*_*ton 6

你应该使用ssh keepalive ...你遇到的问题是远程shell无法知道(默认情况下)你的ssh会话被杀死了.Keepalive将使远程shell能够检测到您已杀死会话

client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect('someserver', username='victorhooi', password='blahblah')
transport = client.get_transport()
transport.set_keepalive(1)   # <------------------------------
# ... carry on as usual...
Run Code Online (Sandbox Code Playgroud)

将keepalive值设置为您想要的最低值(甚至1秒)......几秒钟后,远程shell将看到ssh登录名死亡,它将终止由它生成的任何进程.


Sve*_*ven 6

有一种方法可以做到这一点.它就像在shell上一样

ssh -t commandname
Run Code Online (Sandbox Code Playgroud)

选项-t是打开一个伪pty来帮助ssh跟踪这个过程应该持续多长时间.同样可以通过pormiko via完成

channel.get_pty()
Run Code Online (Sandbox Code Playgroud)

在execute_command(...)之前.这不会像使用channel.invoke_shell()一样打开shell,它只是请求这样的伪接口将所有进程绑定到.如果在远程计算机上发出ps aux,也可以看到效果,此过程现在通过ptxXY接口附加到sshd.


cho*_*own 1

虽然不是最有效的方法,但这应该可行。您先请CTRL+C; 在 KeyboardInterrupt 处理程序中,您可能会exec_command("killall -u %s tail" % uname)喜欢这样:

\n\n
#!/usr/bin/env python2\n\nimport paramiko\nimport select\n\nimport time\nltime = time.time()\n\n# Or use random:\n# import random\n# ltime = random.randint(0, 500)\n\nuname = "victorhooi"\nclient = paramiko.SSHClient()\nclient.load_system_host_keys()\nclient.connect(\'someserver\', username=uname, password=\'blahblah\')\ntransport = client.get_transport()\nchannel = transport.open_session()\n\nchannel.exec_command("tail -%df /home/victorhooi/macbeth.txt" % ltime)\nwhile True:\n\xc2\xa0 \xc2\xa0 try:\n\xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 rl, wl, xl = select.select([channel],[],[],0.0)\n\xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 if len(rl) > 0:\n\xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 # Must be stdout\n\xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 print channel.recv(1024)\n\xc2\xa0 \xc2\xa0 except KeyboardInterrupt:\n        print("Caught control-C")\n        channel.close()\n        try:\n            # open new socket and kill the proc..\n            client.get_transport().open_session().exec_command("kill -9 `ps -fu %s | grep \'tail -%df /home/victorhooi/macbeth.txt\' | grep -v grep | awk \'{print $2}\'`" % (uname, ltime))\n        except:\n            pass\n\xc2\xa0 \xc2\xa0 \n\xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 client.close()\n\xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 exit(0)\n
Run Code Online (Sandbox Code Playgroud)\n\n

这将杀死所有名为 的打开进程tail。如果你tail打开了不想关闭的s,这可能会导致问题,如果是这种情况,你可以grep获取pspid和kill -9它。

\n\n

首先,将 tail 设置为n在跟随之前从文件末尾读取行。设置n为像 这样的唯一数字time.time(),因为 tail 不关心该数字是否大于文件中的行数,因此大数字不time.time()应该引起问题并且将是唯一的。然后 grep 中查找该唯一编号ps

\n\n
   client.get_transport().open_session().exec_command("kill -9 `ps -fu %s | grep \'tail -%df /home/victorhooi/macbeth.txt\' | grep -v grep | awk \'{print $2}\'`" % (uname, ltime))\n
Run Code Online (Sandbox Code Playgroud)\n