Может ли PHP определить, запускается ли он из задания cron или из командной строки? - PullRequest
49 голосов
/ 10 октября 2008

Я ищу способ PHP, чтобы определить, был ли скрипт запущен из ручного вызова на оболочке (я вошел в систему и запустил его), или он был запущен из записи crontab.

У меня есть различные сценарии типа обслуживания, написанные на php, которые я настроил для запуска в моем crontab. Иногда, и мне нужно запускать их вручную досрочно или, если что-то не получилось / сломалось, мне нужно запустить их пару раз.

Проблема в том, что у меня также есть несколько внешних уведомлений, установленных в задачах (публикация в твиттере, отправка электронной почты и т. Д.), Которые я НЕ хочу делать каждый раз, когда запускаю скрипт вручную.

Я использую php5 (если это имеет значение), это довольно стандартная среда Linux-сервера.

Есть идеи?

Ответы [ 21 ]

43 голосов
/ 10 октября 2008

Вместо того, чтобы определять, когда скрипт запускается из crontab, вероятно, легче определить, когда вы запускаете его вручную.

Существует множество переменных среды (в массиве $ _ENV), которые устанавливаются при запуске сценария из командной строки. Что это будет, зависит от настроек вашего сервера и способа входа в систему. В моей среде при запуске скрипта вручную устанавливаются следующие переменные среды, которых нет при запуске из cron:

  • TERM
  • SSH_CLIENT
  • SSH_TTY
  • SSH_CONNECTION

Есть и другие тоже. Так, например, если вы всегда используете SSH для доступа к блоку, то следующая строка определит, запущен ли скрипт из cron:

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

31 голосов
/ 19 марта 2012
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";   
}
29 голосов
/ 10 октября 2008

Вы можете установить дополнительный параметр или добавить строку в ваш crontab, например:

CRON=running

И тогда вы можете проверить переменные окружения на "CRON". Кроме того, попробуйте проверить переменную $ SHELL, я не уверен, что / cron устанавливает ее.

26 голосов
/ 26 августа 2011

Вот что я использую, чтобы узнать, откуда выполняется скрипт. Посмотрите на функцию php_sapi_name для получения дополнительной информации: 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: Если php_sapi_name() не включает cli (может быть cli или cli_server ), тогда мы проверяем, пусто ли $_SERVER['REMOTE_ADDR']. При вызове из командной строки он должен быть пустым.

15 голосов
/ 23 октября 2011

Я думаю, что наиболее универсальным решением является добавление переменной окружения в команду cron и поиск ее в коде. Это будет работать на любой системе.

Если команда, выполняемая cron, например:

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

Измените его на

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

Тогда вы можете проверить это по коду:

if (!getenv('CRON_MODE'))
    print "Sorry, only CRON can access this script";
15 голосов
/ 12 марта 2010

Правильный подход заключается в использовании функции posix_isatty (), например, дескриптор файла stdout, например так:

if (posix_isatty(STDOUT))
    /* do interactive terminal stuff here */
6 голосов
/ 10 октября 2008

Я не знаю конкретно о PHP, но вы можете пройтись по дереву процессов, пока не найдете init или cron.

Предполагая, что PHP может получить свой собственный идентификатор процесса и запускать внешние команды, необходимо выполнить ps -ef | grep pid, где pid - это ваш собственный идентификатор процесса и извлечь из него идентификатор родительского процесса (PPID) .

Затем делайте то же самое с этим PPID, пока не достигнете cron как родителя или init как родителя.

Например, это мое дерево процессов, и вы можете увидеть цепочку владения, 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

Те же процессы, выполняемые в cron, выглядят так:

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

Это решение «ходить по дереву процессов» означает, что вам не нужно беспокоиться о введении искусственного параметра, указывающего, работает ли вы под управлением cron или нет - вы можете забыть сделать это в интерактивном сеансе и все такое до.

5 голосов
/ 10 октября 2008

Не то, что я знаю - возможно, самое простое решение - предоставить дополнительный параметр самостоятельно, чтобы сообщить сценарию, как он был вызван.

5 голосов
/ 15 апреля 2011

Жуткие. Попробуйте

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

вместо этого. Бинарный PHP-клиент не отправляет его. Term Type работает только тогда, когда PHP используется как модуль (т.е. apache), но при запуске php через интерфейс CGI используйте приведенный выше пример!

4 голосов
/ 10 октября 2008

Я бы посмотрел на $_ENV (var_dump () it) и проверил, замечаете ли вы разницу, когда вы ее запускаете, и когда cronjob ее запускает. Кроме того, я не думаю, что есть «официальный» переключатель, который сообщает вам, что произошло.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...