通过shell杀死进程而不杀死自己

时间:2013-08-27 14:19:33

标签: python linux shell

在linux shell中,我可以运行此命令来杀死我的python脚本创建的每个进程(由sudo python3 server.py启动):

sudo kill -9 `ps -ef | grep server.py |grep -v "grep"|awk '{{print $2}}'

我想将此添加到我的脚本并在开始时结束任何先前的脚本过程,以避免获得套接字"地址已在使用"错误。

这是我的代码:

    try:
        application.listen(port=63)
    except OSError as e:
        if e.errno == errno.EADDRINUSE:
            cmd = 'sudo kill -9 `ps -ef | grep server.py |grep -v "grep"|awk \'{{print $2}}\'`'
            print('try to kill previous',cmd)
            import os
            os.system(cmd)

问题是这也会扼杀新流程,因为它也是由相同的关键字启动的。

我该如何避免这种情况?

2 个答案:

答案 0 :(得分:2)

而不是按名称杀死程序,你可以简单地 杀死正在侦听端口63的程序。

以下命令为您提供侦听端口63的程序的PID

netstat --numeric-ports --listening --program | awk '{if (match($4, ":63$")) { split($NF, a, "/"); print a[1];}}' 

或者是一种较短的形式:

netstat -nlp | awk '{if (match($4, ":63$")) {split($NF, a, "/"); print a[1];}}' 

将所有内容粘合在一起以杀死侦听端口63的程序的命令如下:

sudo kill -9 `netstat -nlp | awk '{if (match($4, ":63$")) {split($NF, a, "/"); print a[1];}}'`

这里的解释是:

netstat -nlp输出在某些端口上侦听的所有程序,而不解析端口名称。

因此可以得到这样的结果:

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:9000          0.0.0.0:*               LISTEN      2096/php-fpm.conf)
tcp        0      0 127.0.0.1:63            0.0.0.0:*               LISTEN      2263/memcached  
tcp        0      0 0.0.0.0:36815           0.0.0.0:*               LISTEN      1748/rpc.statd 
....

awk命令具有以下含义:

  awk '{
       # check if field "Local Address" ends with ":63"
       if (match($4, ":63$")) {

           # split the field "PID/Program name" 
           # into the array a based on delimiter "/"
           split($NF, a, "/");

           # print the PID  
           print a[1];

       }
  }'

答案 1 :(得分:1)

您可以使用psutil模块获取流程和网络信息

import psutil
import pprint

for process in psutil.process_iter():
    ### find which ports is the listening (if any)
    listening_ports = [conn for conn in process.get_connections() if conn.status == psutil.CONN_LISTEN]
    if len(listening_ports) > 0:
        print("PID: {}, Process Name: {}".format(process.pid, process.name))
        print("Connections:")
        pprint.pprint(listening_ports)
    ### You could check the desired process and terminate/kill it
    # process.terminate()

示例在Windows上输出,该模块也支持Linux(列出所有监听进程):

PID: 664, Process Name: lsass.exe
Connections:
[connection(fd=-1, family=2, type=1, laddr=('0.0.0.0', 49155), raddr=(), status='LISTEN'),
 connection(fd=-1, family=23, type=1, laddr=('::', 49155), raddr=(), status='LISTEN')]
PID: 904, Process Name: svchost.exe
Connections:
[connection(fd=-1, family=2, type=1, laddr=('0.0.0.0', 135), raddr=(), status='LISTEN'),
 connection(fd=-1, family=23, type=1, laddr=('::', 135), raddr=(), status='LISTEN')]
PID: 1712, Process Name: SpiderOak.exe
Connections:
[connection(fd=-1, family=2, type=1, laddr=('127.0.0.1', 49201), raddr=(), status='LISTEN'),
 connection(fd=-1, family=2, type=1, laddr=('0.0.0.0', 49258), raddr=(), status='LISTEN')]

通过所有这些信息,您可以找到自己的流程,甚至可以使用psutil.Process方法terminate()(发送SIGTERM信号)或kill()(发送SIGKILL将其删除}信号,就像kill -9