2008-10-10 2 views
47

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

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

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

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

Любые идеи?

+2

Добавление в качестве связанного вопроса: [Обнаружение, если скрипт PHP запущен в интерактивном режиме или нет) (http://stackoverflow.com/questions/11327367/detect-if-a-php-script-is-being-run -interactively-or-not/11327451) – Leigh 2012-07-04 11:30:20

+0

@Leigh: Спасибо за ссылку! – hakre 2015-11-06 11:04:32

ответ

39

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

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

  • TERM
  • SSH_CLIENT
  • SSH_TTY
  • SSH_CONNECTION

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

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

+1

, посмотрев на него, это похоже на лучший метод. между _ENV + _SERVER, я уверен, что могу уверенно определить, кто/где/кто его запускает, и действовать соответствующим образом. CRON = бегущая строка в crontab тоже поможет. – Uberfuzzy 2008-10-10 14:15:32

+1

Похоже, что по умолчанию php.ini со временем изменился, чтобы НЕ заполнять глобальный $ _ENV по умолчанию. Безопасный способ - использовать getenv ('SSH_CLIENT') - см. Здесь дополнительную информацию http://stackoverflow.com/questions/3780866/why-is-my-env-empty – GuruBob 2015-09-17 20:53:46

5

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

4

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

2

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

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

+2

Это сценарий оболочки, а не веб-страница. – 2008-10-10 10:50:20

27

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

CRON=running 

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

+0

Я никогда не знал, что вы можете поместить другие команды/переменные строки в crontab. Я только когда-либо изучал синтаксис для команд времени. это плюс php $ _ENV и $ _SERVER, поможет то, что я пытаюсь достичь. спасибо – Uberfuzzy 2008-10-10 15:44:21

+0

«человек 5 crontab» для всех подробных деталей. Но да, вы можете установить переменные среды. Обычно это используется для установки PATH или, возможно, SHELL, но вы можете установить все, что вам нравится. – 2008-10-10 21:48:28

+1

Просто хотел заметить, что `variables_order` должен включать 'E' в php.ini для того, чтобы массив `$ _ENV` был заполнен – andrewtweber 2012-04-12 21:19:23

6

Я не знаю конкретно о 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 

Те же процессы работают под хрон будет выглядеть следующим образом:

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 или нет - вы можете забыть сделать это в своем интерактивном сеансе и все в порядке.

+0

Предположительно, вы бы установили его таким образом, что «no parameter» означает, что вы работаете в интерактивном режиме, таким образом вы не можете его забыть. Интересное решение. – 2008-10-10 11:24:55

+0

Да, очень интересный подход. Может также использоваться для других не-php-вещей. – Uberfuzzy 2008-10-10 13:48:43

1

$_SERVER['SESSIONNAME'] содержит Console при запуске из командной строки. Может быть, это помогает.

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

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

хрон бы:

command ext_updates=1 

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

command 

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

3

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

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

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

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

posix_isatty(STDOUT) return FALSE если выход вызова АОН перенаправлены (труба или файл) ...

-4

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

3

Creepy. Попробуйте

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

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

24

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

14

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

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

2
getenv('TERM') 

Прокладка для SO's 30 char min.

1

Другой вариант - проверить определенную переменную среды, которая задается, когда 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 

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

 Смежные вопросы

  • Нет связанных вопросов^_^