user2003548
user2003548

Reputation: 4545

kill process through shell without kill itself

In a linux shell, I can run this command to kill every process created by my python script (started by sudo python3 server.py):

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

I wanted to add this to my script and end any previous script process at start, to a avoid getting a socket "Address already in use" error.

Here's my code:

    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)

The problem is that this also kill the new process, because it's also started by the same keyword.

How can I avoid this?

Upvotes: 2

Views: 866

Answers (2)

KurzedMetal
KurzedMetal

Reputation: 12946

You can use the psutil module to get process and networking information

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

Example Output on Windows, the module supports Linux too (list all listening processes):

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

With all this information you can find your process and even kill it with the psutil.Process methods terminate() (sends SIGTERM signal) or kill() (sends SIGKILL signal, just like kill -9)

Upvotes: 1

wooghie
wooghie

Reputation: 437

Instead of killing the program by name you could simply kill the program that is listening on port 63.

The following command gives you the PID of the program listening on port 63

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

Or in a shorter form:

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

Gluing everything together the command to kill the program listening on port 63 is the following:

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

Here the explanation:

netstat -nlp outputs all the programs listening on some ports without resolving the port names.

Thus one gets something like this:

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

The awk command has the following meaning:

  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];

       }
  }'

Upvotes: 2

Related Questions