0

We see the running PHP scripts with this command below on terminal:

echo 'User | ProcID | CPU | MEM | ----------------------- START | ELAPSED ---------- COMMAND'; 
ps aux --forest | grep php;

I would like to be email alerted when there is more than one copy of a file running at the same time. Even kill the earlier process maybe automatically!

This happens on cron jobs, when one script is stuck somehow and there comes the the next cycled run time for the cron and you have a stuck (or incomplete, slow script) continuing to run and a new instance of the same script running at the same time.

You may offer a better BASH solution (other than modifying the PHP script).

See image attached for example problem script:

\_ php -f /var/webserver/public_html/cron/scheduled_job_1.php
(process id: 3824)

BASH Alert Script for Ubuntu 16.04.

dessert
  • 39,982
Tarik
  • 215

1 Answers1

3

The easiest way to ensure you have no two instances of your PHP script running would be IMHO to write a tiny wrapper script in Bash that kills any currently running instances of your exact command before running it.

You can then execute this wrapper script in your cronjob instead of the actual PHP command.

Possible wrapper implementation:

#!/bin/bash

my_command='php -f /var/webserver/public_html/cron/scheduled_job_1.php'

# kill processes with the exact command line as above, if any are running
if pkill -fx "$my_command" ; then
    # You can do something here, which runs only if a process was killed.
    # The command below would just echo a warning to the terminal (not visible as a cronjob)
    echo "$(date) - WARNING: Previous instance of '$my_command' was killed."
fi

# (re)run the command
$my_command

Or a generic wrapper that expects the command to run as argument.

#!/bin/bash
# This script expects a command as argument(s), like e.g. "my_wrapper sleep 60"

# kill processes with the given command line, if any are running
if pkill -fx "$*" ; then
    # You can do something here, which runs only if a process was killed.
    # The command below would just echo a warning to the terminal (not visible as a cronjob)
    echo "$(date) - WARNING: Previous instance of '$*' was killed."
fi

# (re)run the command
"$@"

If you save it e.g. as /usr/local/bin/my_wrapper, you can call it like

my_wrapper php -f /var/webserver/public_html/cron/scheduled_job_1.php
Byte Commander
  • 107,489
  • Thanks it is a good idea but the main point is not only kill the process but be notified about it. Because the previous script is stuck means that it had jobs that were not complete yet. And next run could end up in the same point like 80% for example and the remaining 20% stay untouched and I am not aware of that at all... – Tarik Nov 09 '18 at 20:14
  • Well, that's easy. You can do whatever you want in the wrapper script. pkill will exit with status code 1 if there was no matching process found, 0 if it killed something. You can examine that to determine if any cleanup or notification needs to be done, and insert that before actually running your php command. If you'd need to do something before killing the process, you can check if any matching process is running without killing it using pgrep -fx "$my_command" and examining the exit code of that. Everything is possible. – Byte Commander Nov 09 '18 at 21:18
  • Can you edit the answer with IF statement that sends email alert if the pkill has really killed a process? – Tarik Nov 10 '18 at 08:49
  • I added a simple if-statement that lets you do something if a process was killed. What you do in there is up to you, I don't know if/how you have set up mailing and how you would use it. https://askubuntu.com/q/2261/367990 might be helpful for that. – Byte Commander Nov 10 '18 at 16:03
  • Thanks it is much better now. It is hard to implement a wrapper around all of the many cron jobs. Is there a way we can implement a single wrapper and pipe all the PHP scripts onto it? Or use arguments? – Tarik Nov 10 '18 at 20:57
  • @Tarik I added a version of the wrapper that would take the command to run as argument, similar to sudo. – Byte Commander Nov 10 '18 at 21:53