Paramiko和exec_命令-终止远程进程?

2024-04-28 06:13:11 发布

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

我正在使用Paramiko在远程服务器上tail -f一个文件。

以前,我们是通过ssh -t运行这个程序的,但事实证明这是不稳定的,-t导致了远程调度系统的问题。

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

我的脚本(基于Long-running ssh commands in python paramiko module (and how to end them)

#!/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)

脚本成功捕获myCtrl-C,并结束。但是,它让tail -f进程在远程系统上运行,。

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

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

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


Tags: import服务器脚本clientparamikoclose远程系统
3条回答

你应该使用ssh keepalives。。。您遇到的问题是远程shell无法知道(默认情况下)您的ssh会话已被终止。Keepalives将使远程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...

将keepalive值设置为尽可能低的值(甚至1秒)。。。几秒钟后,远程shell将看到ssh登录失败,它将终止由此派生的任何进程。

有一种方法可以做到这一点。它的作用就像在贝壳上

ssh -t commandname

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

channel.get_pty()

在执行_命令之前(…)。这不会像对channel.invoke_shell()那样打开shell,它只是请求这样一个伪接口来绑定所有进程。如果在远程机器上发出ps aux,也可以看到效果,该进程现在通过ptxXY接口连接到sshd。

虽然不是最有效的方法,但这应该是可行的。在键盘中断处理程序中,您可以exec_command("killall -u %s tail" % uname)这样:

#!/usr/bin/env python2

import paramiko
import select

import time
ltime = time.time()

# Or use random:
# import random
# ltime = random.randint(0, 500)

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

channel.exec_command("tail -%df /home/victorhooi/macbeth.txt" % ltime)
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")
        channel.close()
        try:
            # open new socket and kill the proc..
            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))
        except:
            pass
    
        client.close()
        exit(0)

这将杀死任何名为tail的打开进程。但如果您打开了不想关闭的tail,那么这可能会导致问题,如果是这样,您可以grepaps,获取pid和kill -9

首先,将tail设置为在执行以下操作之前从文件末尾读取n行。将n设置为像time.time()这样的唯一数字,因为tail不关心该数字是否大于文件中的行数,所以time.time()中的大数字不应该引起问题,并且将是唯一的。然后grep为ps中的唯一数字:

   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))

相关问题 更多 >