0

Problem

I am using PHP to interact with a multitude of Python services.

This is how PHP uses bash to start processes and get PID:

$created_pid= shell_exec("nohup python3.8 -u $python_filename >> $log_filename & echo $!");
echo json_encode([
    "resolved"=>true,
    "pid"=>trim($created_pid)
]);

This perfectly logs the started PID. However, I would like to also write a function that checks if the PID is still active and if it's associated with the correct script contained in $python_filename.

What I tried

So let's suppose $python_filename = "test.py" and $created_pid = 29780

I have tried using this command to retrieve process info based on PID:

$ ps -p 29780

Which outputs:

29780 pts/0    00:00:00 python3.8

Yeah, it's telling me it's a python3.8 process, and I'm happy but not satisfied. I need to know if, in particular, it's the test.py script.


On the other hand, if I execute:

$ ps -ef | grep "python"

Which outputs something that is too hard to parse:

root     29780 29615  0 17:26 pts/0    00:00:00 python3.8 -u test.py

So this is basically close to the solution that I'm expecting. What I'm looking for is just a cleaner output of the last bash command, which only contains test.py.

6
  • kill -0 <pid> checks if a process is alive. Commented May 14, 2020 at 15:55
  • @jordann but it does not tell me if it's test.py python filename running under that process or it's another script :) Commented May 14, 2020 at 16:48
  • You probably have a better chance of winning the lottery than hitting a race condition where the pid is currently being reused by another process. Around 65k other processes need to come and go before it will reuse that PID again. Commented May 14, 2020 at 16:52
  • @jordanm in my infrastructure I store py script filenames and relative PID in the database, for later checking on the service. The process is on nohup & so it will stay in the background without changing the PID, most likely. Commented May 14, 2020 at 17:12
  • the output is not that hard to parse, you want just the last field. try ps -p 5771 -f | awk 'NR == 2 { print $NF }' where 5771 is your pid Commented May 14, 2020 at 17:12

1 Answer 1

1

A "quick and dirty" solution is to just extract the last "field" in the command string since we know that the filename is in that position:

$ python test.py &
[1] 8040
$ ps -p 8040 --no-headers -o cmd | awk '{ print $NF }'
test.py
$

we tell ps to print just the command string of the process without the columns header (ps -p 8040 --no-headers -o cmd) and we tell awk to extract just the last space separate field of the input line (awk '{ print $NF }'). $NF is an automatic variable in awk which holds the "number of fields" in the current record.

This will fail if your filenames contain spaces since awk interprets spaces as field separator by default:

$ mv test.py test\ with\ spaces.py
$ python test\ with\ spaces.py &
[1] 9033
$ ps -p 9033 --no-headers -o cmd | awk '{ print $NF }'
spaces.py
$

As I said, this is a quick and dirty solution slightly improved from my first attempt in the comments.

EDIT

After some thinking, I may have found a better solution more specific to the "still running check" rather than to the "extract script filename from command".

Since you know and store the PID -> filename association you could grep for the file name in the command string and just check the exit code of grep: 0 match, running; 1 no match, not running.

ps -p 11873 -o cmd | grep -q 'test with spaces.py'

e.g.

$ python test\ with\ spaces.py &
[4] 11873
$ ps -p 11873 -o cmd | grep -q 'test with spaces.py' && echo running || echo not running
running
$ ps -p 999 -o cmd | grep -q 'test with spaces.py' && echo running || echo not running
not running
$
Sign up to request clarification or add additional context in comments.

1 Comment

Awesome solution! The last solution did it even better! You def know bash.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.