Domanda PHP può rilevare se viene eseguito da un cron job o dalla riga di comando?


Sto cercando un modo per PHP per rilevare se uno script è stato eseguito da un'invocazione manuale su una shell (io accedo e l'ho eseguito), o se è stato eseguito dalla voce crontab.

Ho vari script di tipo manutenzione scritti in php che ho impostato per l'esecuzione nel mio crontab. Occasionalmente, e ho bisogno di eseguirli manualmente prima del previsto o se qualcosa non funziona / rotto, ho bisogno di eseguirli un paio di volte.

Il problema con questo è che ho anche alcune notifiche esterne impostate nelle attività (postare su Twitter, inviare una e-mail, ecc.) Che NON DEVO accadere ogni volta che eseguo lo script manualmente.

Sto usando php5 (se è importante), è un ambiente server Linux abbastanza standard.

Qualche idea?


47
2017-10-10 10:37


origine


risposte:


Invece di rilevare quando lo script viene eseguito da crontab, è probabilmente più facile da rilevare quando lo esegui manualmente.

Esistono molte variabili di ambiente (nell'array $ _ENV) impostate quando si esegue uno script dalla riga di comando. Cosa sono questi varieranno a seconda della configurazione di sever e del login. Nel mio ambiente, le seguenti variabili di ambiente sono impostate quando si esegue uno script manualmente che non è presente durante l'esecuzione da cron:

  • TERMINE
  • SSH_CLIENT
  • SSH_TTY
  • SSH_CONNECTION

Ce ne sono anche altri. Ad esempio, se usi sempre SSH per accedere alla casella, la seguente riga rileverà se lo script è in esecuzione da cron:

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


40
2017-10-10 13:31



Puoi impostare un parametro aggiuntivo o aggiungere una riga nel tuo crontab, forse:

CRON=running

E poi puoi controllare le variabili d'ambiente per "CRON". Inoltre, prova a controllare la variabile $ SHELL, non sono sicuro se / a cosa cron lo imposta.


29
2017-10-10 10:47



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

27
2018-03-19 05:46



Ecco cosa uso per scoprire da dove viene eseguito lo script. Guarda la funzione php_sapi_name per maggiori informazioni: 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";
}

MODIFICARE: Se php_sapi_name() non include cli (potrebbe essere cli o cli_server) quindi controlliamo se $_SERVER['REMOTE_ADDR'] è vuoto. Quando chiamato dalla riga di comando, questo dovrebbe essere vuoto.


24
2017-08-26 15:33



Penso che la soluzione più universale sia quella di aggiungere una variabile di ambiente al comando cron e cercarla sul codice. Funzionerà su ogni sistema.

Se il comando eseguito da cron è, ad esempio:

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

Cambiarlo in

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

Quindi puoi verificarlo sul codice:

if (!getenv('CRON_MODE'))
    print "Sorry, only CRON can access this script";

15
2017-10-23 19:46



L'approccio corretto consiste nell'utilizzare la funzione posix_isatty () su es. il descrittore del file stdout, in questo modo:

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

14
2018-03-11 22:15



Non conosco specificamente PHP, ma potresti risalire la struttura del processo fino a quando non hai trovato init o cron.

Supponendo che PHP possa ottenere il proprio ID di processo ed eseguire comandi esterni, dovrebbe essere una questione di esecuzione ps -ef | grep pid dove pid è il tuo ID di processo ed estrae l'ID del processo genitore (PPID) da esso.

Quindi fai lo stesso con quel PPID finché non raggiungi cron come genitore o init come genitore.

Ad esempio, questa è la mia struttura dei processi e puoi vedere la catena di proprietà, 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

Gli stessi processi eseguiti con cron saranno simili a:

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

Questa soluzione di "salire la struttura del processo" significa che non devi preoccuparti di introdurre un parametro artificiale per indicare se stai correndo con cron o meno - potresti dimenticarti di farlo nella tua sessione interattiva e roba da fare.


6
2017-10-10 11:10



Non che io sappia - probabilmente la soluzione più semplice fornisce da sé un parametro in più per dire allo script come è stato invocato.


5
2017-10-10 10:39