PHP è in grado di rilevare se viene eseguito da un processo cron o dalla riga di comando?

StackOverflow https://stackoverflow.com/questions/190759

  •  08-07-2019
  •  | 
  •  

Domanda

Sto cercando il modo per PHP di rilevare se uno script è stato eseguito da una chiamata manuale su una shell (io accedendo ed eseguendolo), o se è stato eseguito dalla voce crontab.

Ho vari script di tipo di manutenzione scritti in php che ho impostato per eseguire nel mio crontab. Occasionalmente, e devo eseguirli manualmente prima del previsto o se qualcosa non funziona / si rompe, devo eseguirli un paio di volte.

Il problema è che ho anche alcune notifiche esterne impostate nelle attività (pubblicazione su Twitter, invio di e-mail, ecc.) che NON VOGLIO accadere ogni volta che eseguo lo script manualmente.

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

Qualche idea?

È stato utile?

Soluzione

Invece di rilevare quando lo script viene eseguito dal crontab, è probabilmente più facile rilevare quando lo si esegue manualmente.

Esistono molte variabili di ambiente (nell'array $ _ENV) che vengono impostate quando si esegue uno script dalla riga di comando. Quali sono varieranno a seconda della configurazione del server e di come esegui l'accesso. Nel mio ambiente, le seguenti variabili di ambiente vengono impostate quando eseguo manualmente uno script che non sono presenti durante l'esecuzione da cron:

  • TERM
  • 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']);

Altri suggerimenti

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

Puoi impostare un parametro extra o aggiungere una linea nel tuo crontab, forse:

CRON=running

E quindi puoi controllare le variabili di ambiente per " CRON " ;. Inoltre, prova a controllare la variabile $ SHELL, non sono sicuro se / su quale cron la imposta.

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(

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

<*>

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

SERVER['REMOTE_ADDR'])) { echo "shell"; } else { echo "webserver"; }

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

L'approccio giusto è usare la funzione posix_isatty () su es. il descrittore di file stdout, in questo modo:

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

Penso che la soluzione più universale sia quella di aggiungere una variabile d'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"

Cambialo in

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

Quindi puoi controllarlo sul codice:

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

Non conosco specificamente PHP ma potresti camminare sull'albero del processo fino a quando non hai trovato init o cron.

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

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

Ad esempio, questo è il mio albero 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 in cron sembrano:

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

Questo "quotando sull'albero del processo" soluzione significa che non devi preoccuparti di introdurre un parametro artificiale per indicare se stai eseguendo sotto cron o no - potresti dimenticare di farlo nella tua sessione interattiva e riempire le cose.

Non che io sappia, probabilmente la soluzione più semplice è fornire un parametro aggiuntivo per dire allo script come è stato invocato.

Creepy. Prova

if (!isset(

Creepy. Prova

<*>

, invece. Il client binario PHP non lo invia. Term Type funziona solo quando PHP è usato come modulo (cioè apache) ma quando si esegue php attraverso l'interfaccia CGI, usare l'esempio sopra!

SERVER['HTTP_USER_AGENT'])) {

, invece. Il client binario PHP non lo invia. Term Type funziona solo quando PHP è usato come modulo (cioè apache) ma quando si esegue php attraverso l'interfaccia CGI, usare l'esempio sopra!

Vorrei esaminare $ _ENV (var_dump () esso) e verificare se si nota una differenza quando lo si esegue rispetto a quando il cronjob lo esegue. A parte questo, non credo che esista un "ufficiale". interruttore che ti dice cosa è successo.

Nel mio ambiente, ho scoperto che TERM era impostato in $ _SERVER se eseguito dalla riga di comando, ma non impostato se eseguito tramite Apache come richiesta web. Ho messo questo nella parte superiore del mio script che potrei eseguire dalla riga di comando o cui potrei accedere tramite un browser Web:

if (isset(

Nel mio ambiente, ho scoperto che TERM era impostato in $ _SERVER se eseguito dalla riga di comando, ma non impostato se eseguito tramite Apache come richiesta web. Ho messo questo nella parte superiore del mio script che potrei eseguire dalla riga di comando o cui potrei accedere tramite un browser Web:

<*>SERVER{'TERM'})) { class::doStuffShell(); } else { class::doStuffWeb(); }
getenv('TERM')

Imbottitura per min 30 di SO.

$ _SERVER ['SESSIONNAME'] contiene Console se eseguito dalla CLI. Forse questo aiuta.

Nel comando cron, aggiungi ? source = cron alla fine del percorso dello script. Quindi, nel tuo script, seleziona $ _GET ['source'] .

EDIT: scusate, è uno script di shell quindi non posso usare qs. A mio avviso, puoi passare argomenti nel formato php script.php arg1 arg2 e poi leggerli con $ argv .

Un'altra opzione sarebbe quella di testare una specifica variabile d'ambiente che viene impostata quando il file php viene invocato attraverso il web e non impostato se gestito dalla riga di comando.

Sul mio server Web sto testando se la variabile d'ambiente APACHE_RUN_DIR è impostata in questo modo:

if (isset(

Un'altra opzione sarebbe quella di testare una specifica variabile d'ambiente che viene impostata quando il file php viene invocato attraverso il web e non impostato se gestito dalla riga di comando.

Sul mio server Web sto testando se la variabile d'ambiente APACHE_RUN_DIR è impostata in questo modo:

<?php var_dump(

Un'altra opzione sarebbe quella di testare una specifica variabile d'ambiente che viene impostata quando il file php viene invocato attraverso il web e non impostato se gestito dalla riga di comando.

Sul mio server Web sto testando se la variabile d'ambiente APACHE_RUN_DIR è impostata in questo modo:

if (isset(

Un'altra opzione sarebbe quella di testare una specifica variabile d'ambiente che viene impostata quando il file php viene invocato attraverso il web e non impostato se gestito dalla riga di comando.

Sul mio server Web sto testando se la variabile d'ambiente APACHE_RUN_DIR è impostata in questo modo:

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

Per assicurarsi che funzioni sul tuo server web, puoi mettere un file php fittizio sul tuo server web con questa singola dichiarazione:

<*>

Quindi 1) caricalo con il tuo browser e 2) caricalo dalla riga di comando in questo modo

<*>

Confronta le differenze e verifica la variabile appropriata.

ENV["APACHE_RUN_DIR"])) { // I'm called by a web user } else { // I'm called by crontab }

Per assicurarsi che funzioni sul tuo server web, puoi mettere un file php fittizio sul tuo server web con questa singola dichiarazione:

<*>

Quindi 1) caricalo con il tuo browser e 2) caricalo dalla riga di comando in questo modo

<*>

Confronta le differenze e verifica la variabile appropriata.

ENV); ?>

Per assicurarsi che funzioni sul tuo server web, puoi mettere un file php fittizio sul tuo server web con questa singola dichiarazione:

<*>

Quindi 1) caricalo con il tuo browser e 2) caricalo dalla riga di comando in questo modo

<*>

Confronta le differenze e verifica la variabile appropriata.

ENV["APACHE_RUN_DIR"])) { // I'm called by a web user } else { // I'm called by crontab }

Per assicurarsi che funzioni sul tuo server web, puoi mettere un file php fittizio sul tuo server web con questa singola dichiarazione:

<*>

Quindi 1) caricalo con il tuo browser e 2) caricalo dalla riga di comando in questo modo

<*>

Confronta le differenze e verifica la variabile appropriata.

posix_isatty (STDOUT) restituisce FALSE se l'output della chiamata cli viene reindirizzato (pipe o file) ...

if(!<*>SERVER['HTTP_HOST']) {
 blabla();
}

Penso che sarebbe meglio eseguire cron commmand con un'opzione aggiuntiva nella riga di comando che non avresti eseguito manualmente.

cron farebbe:

command ext_updates=1

manuale farebbe:

command 

Basta aggiungere un'opzione nello script stesso per avere il parametro ext_updates per avere un valore predefinito di false.

Questo è molto semplice. I demoni Cron esportano sempre la variabile d'ambiente MAILTO . Controlla se esiste e ha un valore non vuoto, quindi esegui cron.

Sul mio server Amazon Linux questo è ciò che ha funzionato per me:

$ isCron = ($ _SERVER ['HOME'] == '/');

La home directory è impostata sulla tua se la esegui. Se usi sudo per eseguirlo, la home directory è impostata su / root.

Per me è facile ... Conta solo ($ _ SERVER ['argc']) e se hai un risultato maggiore di zero si esaurirà un server. Devi solo aggiungere al tuo $ _SERVER ['argv'] la tua variabile personalizzata, come "CronJob"=true;

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top