Can PHP determine if it starts from a cron job or from the command line?

I am looking for a path to PHP to determine if a script was run from a manual call in the shell (I log in and run it), or if it was run from a crontab entry.

I have various service type scripts written in php that I installed to run in my crontab. Sometimes, and I need to start them manually ahead of schedule, or if something did not work / break, I need to start them a couple of times.

The problem is that I also have some external notifications set in tasks (sending to twitter, sending emails, etc.) that I DO NOT want to do every time I run the script manually.

I use php5 (if that matters), its a pretty standard linux server environment.

Any ideas?

+46
php cron
Oct 10 '08 at
source share
20 answers

Instead of detecting when a script is being run from crontab, it is probably easier to detect when you run it manually.

There are many environment variables (in the $ _ENV array) that are set when the script starts from the command line. What this will depend on your server setup and how you log in. In my environment, the following environment variables are set when you run the script manually, which are not available when starting from cron:

  • Term
  • SSH_CLIENT
  • SSH_TTY
  • SSH_CONNECTION

There are others. So, for example, if you always use SSH to access this field, then the following line will determine if the script from cron is running:

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

+38
Oct. 10 '08 at
source share

You can configure an additional parameter or add a line to your crontab, perhaps:

 CRON=running 

And then you can check the environment variables for "CRON". Also, try checking the $ SHELL variable, I'm not sure if / cron sets it.

+27
Oct 10 '08 at
source share

Here I use to find out where the script is running. Take a look at the php_sapi_name function for more information: http://www.php.net/manual/en/function.php-sapi-name.php

 $sapi_type = php_sapi_name(); if(substr($sapi_type, 0, 3) == 'cli' || empty($_SERVER['REMOTE_ADDR'])) { echo "shell"; } else { echo "webserver"; } 

EDIT: If php_sapi_name() does not include cli (maybe cli or cli_server), then we check if $_SERVER['REMOTE_ADDR'] empty. When invoked from the command line, this should be empty.

+24
Aug 26 2018-11-18T00:
source share
 if (php_sapi_name() == 'cli') { if (isset($_SERVER['TERM'])) { echo "The script was run from a manual invocation on a shell"; } else { echo "The script was run from the crontab entry"; } } else { echo "The script was run from a webserver, or something else"; } 
+23
Mar 19 2018-12-12T00:
source share

The correct approach is to use the posix_isatty () function, for example. file descriptor stdout, for example:

 if (posix_isatty(STDOUT)) /* do interactive terminal stuff here */ 
+14
Mar 11 '10 at 22:15
source share

I think the most universal solution is to add an environment variable to the cron command and search for it in the code. It will work on every system.

If the command executed by cron is, for example:

 "/usr/bin/php -q /var/www/vhosts/myuser/index.php" 

Change it to

 "CRON_MODE=1 /usr/bin/php -q /var/www/vhosts/myuser/index.php" 

Then you can check it for code:

 if (!getenv('CRON_MODE')) print "Sorry, only CRON can access this script"; 
+13
Oct 23 '11 at 19:46
source share

I don’t know about PHP specifically, but you can go to the process tree until you find either init or cron.

Assuming PHP can get its own process id and run external commands, ps -ef | grep pid ps -ef | grep pid , where pid is your own process identifier and extract the parent process identifier (PPID) from it.

Then do the same with this PPID until you reach cron as the parent or init as the parent.

For example, this is my process tree, and you can see the ownership chain, 1 → 6386 → 6390 → 6408.

 UID PID PPID C STIME TTY TIME CMD root 1 0 0 16:21 ? 00:00:00 /sbin/init allan 6386 1 0 19:04 ? 00:00:00 gnome-terminal --geom... allan 6390 6386 0 19:04 pts/0 00:00:00 bash allan 6408 6390 0 19:04 pts/0 00:00:00 ps -ef 

The same processes that run in cron will look like this:

 UID PID PPID C STIME TTY TIME CMD root 1 0 0 16:21 ? 00:00:00 /sbin/init root 5704 1 0 16:22 ? 00:00:00 /usr/sbin/cron allan 6390 5704 0 19:04 pts/0 00:00:00 bash allan 6408 6390 0 19:04 pts/0 00:00:00 ps -ef 

This “fit the process tree” solution means that you don’t have to worry about entering an artificial parameter to indicate whether it is running under cron or not - you can forget to do this in your interactive session and in other things up.

+6
Oct 10 '08 at 11:10
source share

Not what I know - perhaps the easiest solution is to provide an additional parameter yourself to tell the script how it was called.

+5
Oct 10 '08 at
source share

I would look at $_ENV (var_dump () it) and see if you noticed a difference when you start it and when cronjob starts. Other than that, I don’t think there is an “official” switch that tells you what happened.

+4
10 Oct '08 at 10:43
source share

In my environment, I found that TERM was installed in $_SERVER if it was run from the command line, but not installed if it was executed through Apache as a web request. I put this at the top of my script, which I could run from the command line, or can access through a web browser:

 if (isset($_SERVER{'TERM'})) { class::doStuffShell(); } else { class::doStuffWeb(); } 
+3
May 01 '09 at 10:59 p.m.
source share

Creepy. Try

 if (!isset($_SERVER['HTTP_USER_AGENT'])) { 

instead of this. PHP Client Binary does not send it. The Term type only works when PHP is used as a module (e.g. apache), but when running php through the CGI interface, use the example above!

+3
Apr 15 2018-11-11T00:
source share

In the cron command, add ?source=cron to the end of the script path. Then in the script, select $_GET['source'] .

EDIT: Sorry, this is a shell script, therefore cannot use qs. You can, I think, pass arguments in the form of a PHP .php arg1 arg2 , and then read them using $argv .

+2
Oct 10 '08 at
source share
 getenv('TERM') 

Filling for SO 30 char min.

+2
Aug 23 '13 at 20:27
source share

$_SERVER['SESSIONNAME'] contains the Console , if executed from the CLI. Perhaps this helps.

+1
Jan 22 '09 at 23:35
source share

Another option is to check a specific environment variable, which is set when the php file is called over the Internet and is not set if it is launched using the command line.

On my web server, I am testing if the environment variable APACHE_RUN_DIR is set as follows:

 if (isset($_ENV["APACHE_RUN_DIR"])) { // I'm called by a web user } else { // I'm called by crontab } 

To make sure that it will work on your web server, you can put a dummy php file on your web server using this single statement:

 <?php var_dump($_ENV); ?> 

Then 1) download it to your web browser and 2) download it from the command line as follows

 /usr/bin/php /var/www/yourpath/dummy.php 

Compare the differences and check the corresponding variable.

+1
Mar 03 '14 at 15:54
source share
 if(!$_SERVER['HTTP_HOST']) { blabla(); } 
0
Jan 30 '09 at 20:03
source share

I think it would be better to run cron commmand with an additional option on the command line that you did not start manually.

cron will do:

 command ext_updates=1 

the manual will do:

 command 

Just add the parameter to the script so that the ext_updates parameter is false by default.

0
Apr 27 '09 at 18:13
source share

posix_isatty(STDOUT) return FALSE if the output of the cli call is redirected (channel or file) ...

0
Nov 03 '10 at 16:18
source share

It is very simple. Cron Daemons always export the MAILTO environment MAILTO . Check if it exists and has a non-empty value - then you are working from cron.

0
Jun 23 2018-12-12T00:
source share

This is easy for me ... Just count($_SERVER['argc']) , and if you have a result above zero, it will work on the server. You just need to add your custom variable to your $_SERVER['argv'] , for example "CronJob"=true;

-four
Jan 02 '10 at 6:17
source share



All Articles