2010-07-09 11 views
21

Non ho molta fortuna a cercare su Google questa domanda e ho pensato di postarla su SF, ma in realtà sembra una domanda di sviluppo. In caso contrario, non esitare a migrare.Può uno script bash indicare se viene eseguito tramite cron?

Quindi, ho uno script che viene eseguito tramite cron ogni mattina alle 3 del mattino. A volte eseguo manualmente anche gli stessi script. Il problema è che ogni volta che eseguo il mio script manualmente e fallisce, mi invia un'e-mail; anche se posso guardare l'output e visualizzare l'errore nella console.

C'è un modo per lo script di bash per dire che viene eseguito tramite cron (forse usando whoami) e solo inviare l'e-mail in caso affermativo? Mi piacerebbe smettere di ricevere email quando sto facendo i miei test ...

+1

Stai inviando email dal tuo script? Non cron per impostazione predefinita della posta inviata al proprietario di crontab? – Cascabel

+0

Sto inviando l'e-mail dall'interno, ma ho dovuto inviare l'output.Non avevo realizzato che cron lo facesse. –

+0

Ehi, stai usando l'e-mail in uscita ACTUAL come in "mail", non solo usando il sistema di posta unix. – gbtimmon

risposta

23

puoi provare "tty" per vedere se è gestito da un terminale o meno. che non ti dirà che è specificamente gestito da cron, ma puoi dire se è "non un utente come prompt".

puoi anche ottenere il tuo genitore-pid e seguirlo sull'albero per cercare cron, anche se è un po 'pesante.

+13

Grazie per questa risposta! La prima risposta che ho scelto non era in realtà ciò che volevo (shell interattiva). Grazie alla tua risposta, ho trovato ciò di cui avevo veramente bisogno con Google "bash tty test". Fondamentalmente, chiama 'tty -s' nel tuo script e poi controlla' $? ': Se è 0, sei in un tty, se è maggiore di 0, non lo sei. –

+1

'tty' è un comando esterno (concesso parte di coreutils, ma è sempre un fork), ci sono diversi modi per usare le cose incorporate per fare lo stesso descritto su https://unix.stackexchange.com/a/46801/103306 –

9

Perché non avere un argomento della riga di comando che è -t per il test o -c per cron.

O meglio ancora:

[email protected]

Se non è specificato, non inviare una e-mail.

+0

Sto lasciando cadere lo script in /etc/cron.daily, quindi non posso aggiungere facilmente argomenti, ma credo che potrei spostarlo su un crontab reale. Speravo semplicemente di non dover aggiungere argomenti o impostare variabili di ambiente sulla riga di comando ... anche se: impostare una variabile di ambiente TESTING nel mio file .bashrc farebbe il trucco. Grazie per i suggerimenti. –

+0

Non c'è alcun problema nel mettere myscript.sh arg1 arg2 arg3 in un file di script in /etc/cron.daily. Di solito non metto il mio script/file binario direttamente nelle directory /etc/cron.*. Di solito lo lascio per gli script che eseguono il lavoro cron (potrebbe essere un altro script). Quindi posso scrivere il mio script in modo più generico e utilizzabile in altri ambienti. –

8

Ecco due diverse opzioni per voi:

  • prendere l'email dal vostro script/programma e lasciare gestire cron esso. Se imposti la variabile MAILTO nel tuo crontab, cron invierà qualsiasi cosa stampata a quell'indirizzo email. ad esempio:

    [email protected] 
    # run five minutes after midnight, every day 
    5 0 * * *  $HOME/bin/daily.job 
    
  • impostare una variabile di ambiente nel vostro crontab che viene utilizzato per determinare se in esecuzione con cron. ad esempio:

    THIS_IS_CRON=1 
    # run five minutes after midnight, every day 
    5 0 * * *  $HOME/bin/daily.job 
    

    e nello script qualcosa come

    if [ -n "$THIS_IS_CRON" ]; then echo "I'm running in cron"; else echo "I'm not running in cron"; fi 
    
6

So che la domanda è vecchio, ma ho appena incontrato lo stesso problema. Questa è stata la mia soluzione:

CRON=$(pstree -s $$ | grep -q cron && echo true || echo false) 

poi prova con

if $CRON 
then 
    echo "Being run by cron" 
else 
    echo "Not being run by cron" 
fi 

stessa idea di quello che @eruciform citato - segue il PID l'albero processo di verifica di cron.

Nota: questa soluzione funziona solo specificamente per cron, a differenza di alcune delle altre soluzioni, che funzionano ogni volta che lo script viene eseguito in modo non interattivo.

+0

Mi piace la semplicità di impostare var su true o false (comandi) in modo che se $ CRON funziona (in contrasto con il solito se ["$ CRON"]), ma nota che se $ CRON finisce indefinito per qualche motivo, la versione data viene valutata come vera. Non bene. –

+0

Mi è piaciuta anche l'idea, ma vedo anche il rischio di avere ritorni indefiniti. Ho finito con una versione leggermente modificata, che sembra funzionare molto liscia a mio parere: CRON = "$ (pstree -s $$ | grep -c cron)" Quindi puoi controllare se $ CRON è 1 o 0. – frank42

4

Ciò che funziona per me è controllare $TERM. Sotto cron è "stupido" ma sotto una shell è qualcos'altro.Utilizzare il comando set nel vostro terminale, poi in un cron-script e check it out

if [ "dumb" == "$TERM" ] 
then 
    echo "cron" 
else 
    echo "term" 
fi 
+1

Vorrei anche controllare se $ TERM non è vuoto. '[-n" $ TERM "-a" $ TERM "==" dumb "] && echo" interattivo "|| echo "cron o no tty" ' – Andor

6

ho avuto un problema simile. L'ho risolto controllando se lo stdout era un TTY. Si tratta di un controllo per vedere se lo script viene eseguito in modalità interattiva:

if [ -t 1 ] ; then 
    echo "interacive mode"; 
else 
    #send mail 
fi 

ho ricevuto questo da: How to detect if my shell script is running through a pipe?

Il ritorno di prova -t vero se descrittore di file è aperto e si riferisce ad un terminale. '1' è stdout.

4

Vorrei proporre una nuova risposta a questa domanda altamente votata. Funziona solo su sistemi systemd con loginctl (ad esempio Ubuntu 14.10+, RHEL/CentOS 7+) ma è in grado di fornire una risposta molto più autorevole rispetto alle soluzioni presentate in precedenza.

service=$(loginctl --property=Service show-session $(</proc/self/sessionid)) 
if [[ ${service#*=} == 'crond' ]]; then 
    echo "running in cron" 
fi 

In sintesi: se usato con systemd, crond (come sshd e altri) crea un nuovo session quando inizia un lavoro per un utente. Questa sessione ha un ID che è unico per l'intera operatività della macchina. Ogni sessione ha alcune proprietà, una delle quali è il nome del servizio che l'ha avviata. loginctl può dirci il valore di questa proprietà, che sarà "crond" se e solo se la sessione è stata effettivamente avviata da crond.


vantaggi rispetto all'utilizzo delle variabili di ambiente:

  • Non c'è bisogno di modificare le voci cron aggiungere invocazioni speciali o variabili d'ambiente
  • No possibilità di un processo intermedio di modificare le variabili di ambiente per creare un falso positivo o falso negativo

Vantaggi rispetto ai test per tty:

  • senza falsi positivi in ​​tubazioni, script di avvio, ecc

Vantaggi rispetto controllando l'albero processo:

  • senza falsi positivi dai processi che hanno anche crond nel loro nome
  • No falsi negativi se la sceneggiatura è sconosciuta
0

Mi è piaciuto anche il idea da Tal, ma anche vedere il rischio di avere ritorni indefiniti. Ho finito con una versione leggermente modificata, che sembra funzionare molto regolare, a mio parere:

CRON="$(pstree -s $$ | grep -c cron)"

modo da poter controllare a $ CRON essere 1 o 0 in qualsiasi momento.

Problemi correlati