Test di un cron job settimanale [chiuso]


237

Ho un #!/bin/bashfile nella directory cron.week.

C'è un modo per testare se funziona? Non posso aspettare 1 settimana

Sono su Debian 6 con root


4
Non puoi semplicemente testare lo script eseguendolo dalla riga di comando?
Frédéric Hamidi,

5
basta aggiungere una voce separata nella tua crontabche esegue il tuo file ogni pochi minuti, vedere se ci sono i risultati previsti, quindi eliminare la voce di prova dal tuo crontab. provacrontab -e
davin,

61
No, eseguirlo dalla riga di comando non è un buon modo. Il semplice esecuzione dello script dalla riga di comando non garantisce che verrà eseguito come lo stesso utente quando veniva eseguito da cron. Anche se viene eseguito come lo stesso utente, non puoi mai essere sicuro che tutto il resto sarà lo stesso. Gli script che funzionano dalla riga di comando possono fallire per tutti i tipi di motivi quando eseguiti da cron.
andynormancx,

8
"tutti i tipi" potrebbero essere leggermente iperbolici ... permessi e variabili d'ambiente sono i due che mi vengono in mente, ma potresti facilmente avere altre condizioni iniziali come gli alias
andynormancx,

3
Ho appena provato un nuovo lavoro cron, aggiungerò un altro elemento a "tutti i tipi". Se hai delle cose in bash_profile, non vengono eseguite una volta in un lavoro cron, mentre testare il lavoro dalla riga di comando funziona perfettamente. Testare cron job sulla riga di comando standard non è affatto un buon test.
andynormancx,

Risposte:


233

Fai quello che fa cron, esegui quanto segue root:

run-parts -v /etc/cron.weekly

... o il prossimo se ricevi l'errore "Not a directory: -v":

run-parts /etc/cron.weekly -v

L'opzione -vstampa i nomi degli script prima che vengano eseguiti.


4
Se uso l'opzione -v che mostra l'errore "Not a directory: -v", non c'è una pagina man per questo comando nel mio sistema, -v significa prolisso, giusto? Sto usando centos 6.4
max

3
Per evitare l'errore "Not a directory", ho dovuto invece fare questo: run-parts /etc/cron.weekly -v
Craig Hyatt

22
Ma questo non tiene conto delle variabili d'ambiente che potrebbero essere impostate nel crontab
fcurella,

34
run-partsesegue solo gli script di una determinata directory. Niente a che fare con cron.
Nicolas,

23
Questo non avrebbe dovuto essere votato e accettato, oltre a eseguire lo script non fa nulla per dirti se lo script funzionerà effettivamente quando eseguito da cron. Usa l'eccellente script crontest in una delle altre risposte a questa domanda.
andynormancx,

87

Un po 'oltre lo scopo della tua domanda ... ma ecco cosa faccio.

Il "come testare un lavoro cron?" domanda è strettamente connessa a "come testare gli script eseguiti in contesti non interattivi lanciati da altri programmi?" In cron, il trigger è una condizione temporale, ma molte altre strutture * nix lanciano script o frammenti di script in modi non interattivi e spesso le condizioni in cui vengono eseguiti quegli script contengono qualcosa di inaspettato e causano la rottura fino a quando i bug non vengono risolti. (Vedi anche: https://stackoverflow.com/a/17805088/237059 )

È utile avere un approccio generale a questo problema.

Una delle mie tecniche preferite è usare una sceneggiatura che ho scritto chiamato " crontest " ". Avvia il comando target all'interno di una sessione dello schermo GNU dall'interno di cron, in modo che tu possa collegarti con un terminale separato per vedere cosa sta succedendo, interagire con lo script, persino usare un debugger.

Per impostarlo, dovresti usare "tutte le stelle" nella voce crontab e specificare crontest come primo comando sulla riga di comando, ad esempio:

* * * * * crontest /command/to/be/tested --param1 --param2

Quindi ora cron eseguirà il tuo comando ogni minuto, ma crontest assicurerà che venga eseguita solo un'istanza alla volta. Se l'esecuzione del comando richiede tempo, è possibile eseguire uno "schermo -x" per collegarlo e vederlo funzionare. Se il comando è uno script, puoi mettere un comando "leggi" in alto per fermarlo e attendere il completamento dell'allegato dello schermo (premi Invio dopo averlo allegato)

Se il tuo comando è uno script bash, puoi invece farlo:

* * * * * crontest --bashdb /command/to/be/tested --param1 --param2

Ora, se ti allego con "screen -x", ti troverai di fronte a una sessione interattiva bashdb e puoi scorrere il codice, esaminare le variabili, ecc.

#!/bin/bash

# crontest
# See https://github.com/Stabledog/crontest for canonical source.

# Test wrapper for cron tasks.  The suggested use is:
#
#  1. When adding your cron job, use all 5 stars to make it run every minute
#  2. Wrap the command in crontest
#        
#
#  Example:
#
#  $ crontab -e
#     * * * * * /usr/local/bin/crontest $HOME/bin/my-new-script --myparams
#
#  Now, cron will run your job every minute, but crontest will only allow one
#  instance to run at a time.  
#
#  crontest always wraps the command in "screen -d -m" if possible, so you can
#  use "screen -x" to attach and interact with the job.   
#
#  If --bashdb is used, the command line will be passed to bashdb.  Thus you
#  can attach with "screen -x" and debug the remaining command in context.
#
#  NOTES:
#   - crontest can be used in other contexts, it doesn't have to be a cron job.
#       Any place where commands are invoked without an interactive terminal and
#       may need to be debugged.
#
#   - crontest writes its own stuff to /tmp/crontest.log
#
#   - If GNU screen isn't available, neither is --bashdb
#

crontestLog=/tmp/crontest.log
lockfile=$(if [[ -d /var/lock ]]; then echo /var/lock/crontest.lock; else echo /tmp/crontest.lock; fi )
useBashdb=false
useScreen=$( if which screen &>/dev/null; then echo true; else echo false; fi )
innerArgs="$@"
screenBin=$(which screen 2>/dev/null)

function errExit {
    echo "[-err-] $@" | tee -a $crontestLog >&2
}

function log {
    echo "[-stat-] $@" >> $crontestLog
}

function parseArgs {
    while [[ ! -z $1 ]]; do
        case $1 in
            --bashdb)
                if ! $useScreen; then
                    errExit "--bashdb invalid in crontest because GNU screen not installed"
                fi
                if ! which bashdb &>/dev/null; then
                    errExit "--bashdb invalid in crontest: no bashdb on the PATH"
                fi

                useBashdb=true
                ;;
            --)
                shift
                innerArgs="$@"
                return 0
                ;;
            *)
                innerArgs="$@"
                return 0
                ;;
        esac
        shift
    done
}

if [[ -z  $sourceMe ]]; then
    # Lock the lockfile (no, we do not wish to follow the standard
    # advice of wrapping this in a subshell!)
    exec 9>$lockfile
    flock -n 9 || exit 1

    # Zap any old log data:
    [[ -f $crontestLog ]] && rm -f $crontestLog

    parseArgs "$@"

    log "crontest starting at $(date)"
    log "Raw command line: $@"
    log "Inner args: $@"
    log "screenBin: $screenBin"
    log "useBashdb: $( if $useBashdb; then echo YES; else echo no; fi )"
    log "useScreen: $( if $useScreen; then echo YES; else echo no; fi )"

    # Were building a command line.
    cmdline=""

    # If screen is available, put the task inside a pseudo-terminal
    # owned by screen.  That allows the developer to do a "screen -x" to
    # interact with the running command:
    if $useScreen; then
        cmdline="$screenBin -D -m "
    fi

    # If bashdb is installed and --bashdb is specified on the command line,
    # pass the command to bashdb.  This allows the developer to do a "screen -x" to
    # interactively debug a bash shell script:
    if $useBashdb; then
        cmdline="$cmdline $(which bashdb) "
    fi

    # Finally, append the target command and params:
    cmdline="$cmdline $innerArgs"

    log "cmdline: $cmdline"


    # And run the whole schlock:
    $cmdline 

    res=$?

    log "Command result: $res"


    echo "[-result-] $(if [[ $res -eq 0 ]]; then echo ok; else echo fail; fi)" >> $crontestLog

    # Release the lock:
    9<&-
fi

2
Fantastica, la soluzione perfetta. Tutte le altre tecniche che avevo provato non funzionavano davvero, crontest ha risolto facilmente il problema.
andynormancx,

1
Questo è stato molto più di quello di cui avevo bisogno, ma +1 per un'ottima soluzione comunque; impostare il cron per l'esecuzione più frequente e scaricare l'output su / tmp era abbastanza buono da individuare il mio problema.
jcollum,

2
Freddo. Sì, nessun motivo per accendere il bulldozer se hai solo bisogno di una vanga a mano :)
Stabledog

2
Roba fantastica. Nota su Mac ho dovuto brew tap discoteq/discoteq; brew install flocke quindi modificare lo script da utilizzare/usr/local/bin/flock
Claudiu,

1
bella utilità! Molto utile per diagnosticare problemi di autenticazione in contesti non interattivi.
Eric Blum,

44

Dopo aver fatto casino con alcune cose in cron che non erano immediatamente compatibili, ho scoperto che il seguente approccio era utile per il debug:

crontab -e

* * * * * /path/to/prog var1 var2 &>>/tmp/cron_debug_log.log

Questo eseguirà l'attività una volta al minuto e puoi semplicemente guardare nel /tmp/cron_debug_log.logfile per capire cosa sta succedendo.

Non è esattamente il "lavoro sul fuoco" che potresti cercare, ma questo mi ha aiutato molto nel debug di uno script che inizialmente non funzionava in cron.


9
Consiglierei questo approccio. Il problema nella maggior parte dei casi è che non vedi l'errore.
Yauhen Yakimovich,

8
Riga errata, nessuna distribuzione utilizza bash per cron shell e quindi & >> non funziona. Suggerisco di usare >>/tmp/cron_debug_log.log 2>&1Invece
drizzt

1
Cosa intendi con /path/to/progquale prog?
Nathan,

3
Il programma che eseguirai con cron. Questo può essere usr/home/myFancyScript.sho può essere un semplice lso qualunque cosa tu voglia eseguire regolarmente.
Automatico,

Questo ha funzionato per me. È stato il metodo più semplice per eseguire un test rapido per verificare se tutto va bene
abhijit,

25

Vorrei utilizzare un file di blocco e quindi impostare il processo cron per l'esecuzione ogni minuto. (usa crontab -e e * * * * * / path / to / job) In questo modo puoi semplicemente continuare a modificare i file e ogni minuto verranno testati. Inoltre, puoi interrompere il cronjob semplicemente toccando il file di blocco.

    #!/bin/sh
    if [ -e /tmp/cronlock ]
    then
        echo "cronjob locked"
        exit 1
    fi

    touch /tmp/cronlock
    <...do your regular cron here ....>
    rm -f /tmp/cronlock

4
Puoi anche usare flock(1)dalla shell; vedi man 1 flock. Abbastanza utile per tali usi poiché fornisce il blocco automatico.
Craig Ringer,

5

Che ne dici di metterlo in cron.hourly, in attesa fino alla prossima esecuzione di cron job orarie, quindi rimuoverlo? Ciò sarebbe eseguito una volta entro un'ora e nell'ambiente cron. Puoi anche eseguire ./your_script, ma questo non avrà lo stesso ambiente di cron.


questo è praticamente lo stesso della risposta di @ Cort3z, con meno dettagli
jcollum

5

Nessuna di queste risposte si adattava alla mia situazione specifica, che era che volevo eseguire un lavoro cron specifico, una sola volta, ed eseguirlo immediatamente.

Sono su un server Ubuntu e utilizzo cPanel per configurare i miei lavori cron.

Ho semplicemente annotato le mie impostazioni attuali, e poi le ho modificate per essere tra un minuto. Quando ho risolto un altro bug, l'ho appena modificato di nuovo a un minuto da ora. E quando ho finito, ho ripristinato le impostazioni su come erano prima.

Esempio: sono le 16:34 in questo momento, quindi ho messo 35 16 * * *, per farlo funzionare alle 16:35.

Funzionava come un incantesimo e il massimo che avessi mai dovuto aspettare era poco meno di un minuto.

Ho pensato che questa fosse un'opzione migliore di alcune delle altre risposte perché non volevo eseguire tutti i miei croni settimanali e non volevo che il lavoro venisse eseguito ogni minuto. Mi ci vogliono alcuni minuti per risolvere qualunque problema prima di essere pronto a testarlo di nuovo. Spero che questo aiuti qualcuno.


Perché dovresti usare cron per eseguire "solo una volta ed eseguirlo immediatamente"? Sembra che staresti meglio eseguendo direttamente lo script.
Ian Hunter il

4

A parte questo puoi anche usare:

http://pypi.python.org/pypi/cronwrap

per concludere il tuo cron per inviarti un'email in caso di esito positivo o negativo.


10
Cron non ha già inviato e-mail e output dallo script al momento dell'esecuzione?
Erik

Cron invia un'e-mail all'utente, e in genere l'utente per la maggior parte dei lavori cron è un utente root o un servizio non interattivo, quindi non vedrai mai le e-mail. Questo è il modo in cui i server si riempiono quando un errore innesca un enorme flusso di e-mail e rimbalzano alla radice.
dragon788,

3

La soluzione che sto usando è la seguente:

  1. Modifica crontab (usa il comando: crontab -e) per eseguire il lavoro con la frequenza necessaria (ogni 1 minuto o 5 minuti)
  2. Modifica lo script della shell che dovrebbe essere eseguito usando cron per stampare l'output in alcuni file (es: echo "Funziona bene" >>
    output.txt)
  3. Controlla il file output.txt usando il comando: tail -f output.txt, che stamperà le ultime aggiunte in questo file e quindi potrai tracciare l'esecuzione dello script

2

Normalmente eseguo il test eseguendo il lavoro che ho creato in questo modo:

Per fare ciò è più semplice utilizzare due terminali.

eseguire il lavoro:

#./jobname.sh

vai a:

#/var/log and run 

eseguire quanto segue:

#tailf /var/log/cron

Questo mi permette di vedere l'aggiornamento dei log cron in tempo reale. Puoi anche rivedere il registro dopo averlo eseguito, preferisco guardarlo in tempo reale.

Ecco un esempio di un semplice lavoro cron. Esecuzione di un aggiornamento yum ...

#!/bin/bash
YUM=/usr/bin/yum
$YUM -y -R 120 -d 0 -e 0 update yum
$YUM -y -R 10 -e 0 -d 0 update

Ecco la ripartizione:

Il primo comando aggiornerà yum stesso e il successivo applicherà gli aggiornamenti di sistema.

-R 120: imposta il tempo massimo che yum attenderà prima di eseguire un comando

-e 0: imposta il livello di errore su 0 (intervallo 0-10). 0 significa stampare solo errori critici di cui è necessario comunicare.

-d 0: imposta il livello di debug su 0 - aumenta o diminuisce la quantità di elementi stampati. (intervallo: 0 - 10).

-y: supponiamo di si; supponiamo che la risposta a qualsiasi domanda che venga posta sia sì

Dopo aver creato il processo cron, ho eseguito il comando seguente per rendere il mio lavoro eseguibile.

#chmod +x /etc/cron.daily/jobname.sh 

Spero che questo aiuti, Dorlack


2
sudo run-parts --test /var/spool/cron/crontabs/

i file in quella crontabs/directory devono essere eseguibili dal proprietario - ottale700

fonte: man crone NNRooth's


5
Due riflessi. Primo: per eseguire le cose come sudo usa un ambiente diverso (variabili definite). Quindi i bug nel tuo crontab potrebbero funzionare se eseguiti come 'sudo', ma non funzioneranno se eseguiti come 'root' (e viceversa). Secondo: 'man cron' non mi mostra queste informazioni (ok, il mio uomo sembra essere specifico di debian) ... 'man run-parts' dice che --test non esegue gli script, ma stampa solo i nomi di loro. Quindi gli script non sono nemmeno testati. Una cosa minore: "eseguibile dal proprietario": per quanto ne so, i cronjob vengono eseguiti solo come root.
Alex

-1

Sto usando Webmin perché è un gioiello di produttività per qualcuno che trova l'amministrazione della riga di comando un po 'scoraggiante e impenetrabile.

C'è un pulsante "Salva ed esegui ora" nell'interfaccia web "Sistema> Lavori cron programmati> Modifica lavoro cron".

Visualizza l'output del comando ed è esattamente ciò di cui avevo bisogno.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.