Подтвердить что ты не робот

Может ли PHP определить, выполняется ли его запуск из задания cron или из командной строки?

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

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

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

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

Любые идеи?

4b9b3361

Ответ 1

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

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

  • TERM
  • SSH_CLIENT
  • SSH_TTY
  • SSH_CONNECTION

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

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

Ответ 2

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

CRON=running

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

Ответ 3

Здесь я использую, чтобы узнать, где выполняется script. Посмотрите на функцию 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'] пустым. При вызове из командной строки это должно быть пустым.

Ответ 4

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";   
}

Ответ 5

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

if (posix_isatty(STDOUT))
    /* do interactive terminal stuff here */

Ответ 6

Я думаю, что наиболее универсальным решением является добавление переменной среды в команду 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";

Ответ 7

Я не знаю о 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 или нет - вы можете забыть сделать это в своем интерактивном сеансе и в других вещах вверх.

Ответ 8

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

Ответ 9

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

Ответ 10

В моей среде я обнаружил, что TERM был установлен в $_SERVER, если он запущен из командной строки, но не установлен, если выполняется через Apache в качестве веб-запроса. Я поставил это в верхней части моего script, который я мог бы запустить из командной строки, или может получить доступ через веб-браузер:

if (isset($_SERVER{'TERM'}))
{
    class::doStuffShell();
}
else
{
    class::doStuffWeb();
}

Ответ 11

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

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

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

Ответ 12

В команде cron добавьте ?source=cron в конец пути script. Затем в script выберите $_GET['source'].

EDIT: извините, это оболочка script, поэтому не может использовать qs. Вы можете, я думаю, передать аргументы в форме PHP скрипт.php arg1 arg2, а затем прочитать их с помощью $argv.

Ответ 13

getenv('TERM')

Заполнение для SO 30 char мин.

Ответ 14

$_SERVER['SESSIONNAME'] содержит Console, если выполняется из CLI. Возможно, это помогает.

Ответ 15

Другой вариант - проверить определенную переменную среды, которая устанавливается, когда php файл вызывается через Интернет и не устанавливается, если он запускается с помощью командной строки.

На моем веб-сервере я тестирую, если переменная среды APACHE_RUN_DIR установлена ​​следующим образом:

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

Чтобы убедиться, что он будет работать на вашем веб-сервере, вы можете поместить фиктивный php файл на свой веб-сервер с помощью этого единственного оператора:

<?php var_dump($_ENV);  ?>

Затем 1) загрузите его в свой веб-браузер и 2) загрузите его из командной строки следующим образом

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

Сравните различия и проверьте соответствующую переменную.

Ответ 16

if(!$_SERVER['HTTP_HOST']) {
 blabla();
}

Ответ 17

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

cron сделает:

command ext_updates=1

руководство будет делать:

command 

Просто добавьте параметр в script, чтобы параметр ext_updates имел значение false по умолчанию.

Ответ 18

posix_isatty(STDOUT) return FALSE, если вывод вызова cli перенаправляется (канал или файл)...

Ответ 19

Это очень просто. Cron Daemons всегда экспортируют переменную среды MAILTO. Проверьте, существует ли он и имеет непустое значение - тогда вы работаете из cron.

Ответ 20

Это легко для меня... Просто count($_SERVER['argc']), и если у вас есть результат выше нуля, он будет работать на сервере. Вам просто нужно добавить в свою $_SERVER['argv'] свою настраиваемую переменную, например "CronJob"=true;