How to Check If a Process Is Still Running Using Python on Linux

How to check if a process is still running using Python on Linux?

Mark's answer is the way to go, after all, that's why the /proc file system is there. For something a little more copy/pasteable:

 >>> import os.path
>>> os.path.exists("/proc/0")
False
>>> os.path.exists("/proc/12")
True

Python script checking if a particular Linux command is still running

Have to change the logic a bit, but basically you want an infinite loop alternating a check on all processes - not checking the same one over and over:

import subprocess
import shlex
import time
from datetime import datetime

proc_def = "top"
grep_cmd = "pgrep -a " + proc_def
try:
proc_run = subprocess.check_output(shlex.split(grep_cmd)).decode('utf-8')
proc_run = proc_run.strip().split('\n')
'''
Creating a dictionary with key the PID of the process and value
the command line
'''
proc_dict = dict(zip([i.split(' ', 1)[0] for i in proc_run],
[i.split(' ', 1)[1] for i in proc_run]))

check_run = "ps -o pid= -p "
while proc_dict:
for key, value in proc_dict.items():
check_run_cmd = check_run + key
try:
# While the output of check_run_cmd isn't empty line do
subprocess.check_output(shlex.split(check_run_cmd)).decode('utf-8').strip()
# This print statement is for debugging purposes only
print("Running")
time.sleep(3)
except subprocess.CalledProcessError as e:
print(f"PID: {key} of command: \"{value}\" stopped at {datetime.now().strftime('%d-%m-%Y %T')}")
del proc_dict[key]
break
# Check if the proc_def is actually running on the machine
except subprocess.CalledProcessError as e:
print(f"The \"{proc_def}\" command isn't running on this machine")

This suffers from the same problems in the original code, namely the time resolution is 3 seconds, and if a new process is run during this script, you won't ping it (though this may be desired).

The first problem would be fixed by sleeping for less time, depending on what you need, the second by running the initial lines creating proc_dict in the while True.

Checking if script is already running (python / linux)

As @JohnGordon noticed in the comments, there is a logic problem in your code.

if __file__ in c:
print('already running')
sys.exit()
else:
print('not yet running')
return

Here, if it checks a process and it doesn't match the file, the function returns. That means it won't check any remaining processes.

You can only deduce that the program is not yet running after the loop has been allowed to complete.

def check_if_running():
# print('process_nb: ', len(list(psutil.process_iter())))
for i, q in enumerate(psutil.process_iter()):
n = q.name()
# print(i, n)
if 'python' in n.lower():
print(i, n)
c = q.cmdline()
print(c)
if __file__ in c:
print('already running')
sys.exit()
# every process has been checked
print('not yet running')

I also changed 'python' in n to 'python' in n.lower(), because on my system the process is called 'Python', not 'python', and this change should cover both cases.

However, when I tried this I found another problem, which is that the program finds its own process and always shuts down, even if it's the only version of itself running.

To avoid that, maybe you want to count the number of matching processes instead, and only exit if it finds more than one match.

def count_processes(name, file):
return sum(name in q.name().lower() and file in q.cmdline() for q in psutil.process_iter())

def check_if_running():
if count_processes('python', __file__) > 1:
print('already running')
sys.exit()
else:
print('not yet running')

Checking if process is completed (python)

pidof -- find the process ID of a running program.

pidof will have his exit code to zero if at least one process by that name is running, else it will be one.

You can do a little bash script like this:

if pidof python > /dev/null;
then
echo 'At least one is running'
else
echo 'No process is running'
fi

I am pipe-ing the output to /dev/null just to avoid having the PID of the found process being printed, but this is optional.

EDIT: If you want to be able to do it from python, just do the same thing:

import os

if os.system("pidof man > /dev/null") == 0:
print('At least one is running')
else:
print('No process is running')

Check if a process is still running

Since you are already using psutil I suggest you replace the calls to the subprocess module with calls to psutil.Popen. This class has the same interface of subprocess.Popen but provides all the functionality of psutil.Process.

Also note that the psutil library pre-emptively checks for PID reuse already, at least for a number of methods including terminate and kill (just read the documentation for Process).

This means that the following code:

cmd = ["bash", "script.sh", self.get_script_path()]
process = psutil.Popen(cmd)

time.sleep(10) # process running here...

children = process.children(recursive=True)
for child in children:
child.terminate() # try to close the process "gently" first
child.kill()

Note that the documentation for children says:

children(recursive=False)

Return the children of this process as a list of Process objects, preemptively checking whether PID has been reused.

In summary this means that:

  1. When you call children the psutil library checks that you want the children of the correct process and not one that happen to have the same pid
  2. When you call terminate or kill the library makes sure that you are killing your child process and not a random process with the same pid.

How to display list of running processes Python?

Try this command:

ps -ef | grep python

ps stands for process status

How to check if a process is running in Python?

If you insist on no 3rd party modules (and I'd argue that win32api when running on Windows should be shipped with Python anyway), you can at least offset most of the work to systems that do utilize Win32 API instead of trying to do everything through Python. Here's how I'd do it:

import subprocess
import time

# list of processes to auto-kill
kill_list = ["chrome.exe", "opera.exe", "iexplore.exe", "firefox.exe"]

# WMI command to search & destroy the processes
wmi_command = "wmic process where \"{}\" delete\r\n".format(
" OR ".join("Name='{}'".format(e) for e in kill_list))

# run a single subprocess with Windows Command Prompt
proc = subprocess.Popen(["cmd.exe"], stdout=subprocess.PIPE, stdin=subprocess.PIPE)
while True:
proc.stdin.write(wmi_command.encode("ascii")) # issue the WMI command to it
proc.stdin.flush() # flush the STDIN buffer
time.sleep(1) # let it breathe a little

In most cases you won't even notice the performance impact of this one.

Now, why would you need such a thing in the first place is a completely different topic - I'd argue that there is no real-world use for a script like this.



Related Topics



Leave a reply



Submit