Can PHP Detect If Its Run from a Cron Job or from the Command Line

Can PHP detect if its run from a cron job or from the command line?

Instead of detecting when the script is run from the crontab, it's probably easier to detect when you're running it manually.

There are a lot of environment variables (in the $_ENV array) that are set when you run a script from the command line. What these are will vary depending on your sever setup and how you log in. In my environment, the following environment variables are set when running a script manually that aren't present when running from cron:

  • TERM
  • SSH_CLIENT
  • SSH_TTY
  • SSH_CONNECTION

There are others too. So for example if you always use SSH to access the box, then the following line would detect if the script is running from cron:

$cron = !isset($_ENV['SSH_CLIENT']);

PHP - How to know if PHP script is being run via a Cron

There is a php_sapi_name() function for that

Check if a php file command is already running on cron

If you want the php solution, the simple way is to create a lock file, each time script is executed , check if file exist then exit script, if not let script go to end. But i think it's better to use flock in cron instruction ;)

<?php
$filename = "myscript.lock";
$lifelimit = 120; // in Second lifetime to prevent errors
/* check lifetime of file if exist */
if(file_exists($filename)){
$lifetime = time() - filemtime($filename);
}else{
$lifetime = 0;
}
/* check if file exist or if file is too old */
if(!file_exists($filename) || $lifetime > $lifelimit){
if($lifetime > $lifelimit){
unlink($filename); //Suppress if exist and too old
}
$file=fopen($filename, "w+"); // Create lockfile
if($file == false){
die("file didn't create, check permissions");
}
/* Your process */
unlink($filename); //Suppress lock file after your process
}else{
exit(); // Process already in progress
}

PHP and Cron job

You can use php_sapi_name(). It should return a different value from the command line (including, but not limited to, cron) than from say CGI or mod_php.

In PHP, how to detect the execution is from CLI mode or through browser ?

Use the php_sapi_name() function.

if (php_sapi_name() == "cli") {
// In cli-mode
} else {
// Not in cli-mode
}

Here are some relevant notes from the docs:

php_sapi_name — Returns the type of interface between web server and PHP

Although not exhaustive, the possible return values include aolserver, apache, apache2filter, apache2handler, caudium, cgi (until PHP 5.3), cgi-fcgi, cli, cli-server, continuity, embed, isapi, litespeed, milter, nsapi, phttpd, pi3web, roxen, thttpd, tux, and webjames.

Detect if a PHP script is being run interactively or not

I also needed a slightly more flexible solution than posix_isatty that could detect:

  • Is the script being run from the terminal
  • Is the script receiving data via a pipe or from a file
  • Is the output being redirected to a file

After a bit of experimenting and digging around through libc headers, I came up with a very simple class that can do all of the above and more.

class IOMode
{
public $stdin;
public $stdout;
public $stderr;

private function getMode(&$dev, $fp)
{
$stat = fstat($fp);
$mode = $stat['mode'] & 0170000; // S_IFMT

$dev = new StdClass;

$dev->isFifo = $mode == 0010000; // S_IFIFO
$dev->isChr = $mode == 0020000; // S_IFCHR
$dev->isDir = $mode == 0040000; // S_IFDIR
$dev->isBlk = $mode == 0060000; // S_IFBLK
$dev->isReg = $mode == 0100000; // S_IFREG
$dev->isLnk = $mode == 0120000; // S_IFLNK
$dev->isSock = $mode == 0140000; // S_IFSOCK
}

public function __construct()
{
$this->getMode($this->stdin, STDIN);
$this->getMode($this->stdout, STDOUT);
$this->getMode($this->stderr, STDERR);
}
}

$io = new IOMode;

Some example usage, to show what it can detect.

Input:

$ php io.php
// Character device as input
// $io->stdin->isChr == true

$ echo | php io.php
// Input piped from another command
// $io->stdin->isFifo == true

$ php io.php < infile
// Input from a regular file (name taken verbatim from C headers)
// $io->stdin->isReg == true

$ mkdir test
$ php io.php < test
// Directory used as input
// $io->stdin->isDir == true

Output:

$ php io.php
// $io->stdout->isChr == true

$ php io.php | cat
// $io->stdout->isFifo == true

$ php io.php > outfile
// $io->stdout->isReg == true

Error:

$ php io.php
// $io->stderr->isChr == true

$ php io.php 2>&1 | cat
// stderr redirected to stdout AND piped to another command
// $io->stderr->isFifo == true

$ php io.php 2>error
// $io->stderr->isReg == true

I've not included examples for links, sockets, or block devices, but there's no reason they shouldn't work, as the device mode masks for them are in the class.

(Not tested on Windows - mileage may vary)



Related Topics



Leave a reply



Submit