Come creare un cron job usando Bash automaticamente senza l'editor interattivo?


395

Crontab ha un argomento per creare cron job senza usare l'editor (crontab -e). In tal caso, quale sarebbe il codice creare un cronjob da uno script Bash?



5
Purtroppo, la maggior parte delle risposte migliori qui stanno solo mostrando come modificare crontab - sebbene in modi ragionevolmente sicuri - ma penso che sia nel complesso l'approccio sbagliato. Meglio, più sicuro e più semplice è rilasciare un file in {{cron.d}} e ci sono (attualmente) risposte a basso voto che spiegano come farlo se si guarda in basso.
Gregregac,

Risposte:


539

È possibile aggiungere al crontab come segue:

#write out current crontab
crontab -l > mycron
#echo new cron into cron file
echo "00 09 * * 1-5 echo hello" >> mycron
#install new cron file
crontab mycron
rm mycron

Spiegazione della linea cron

* * * * * "command to be executed"
- - - - -
| | | | |
| | | | ----- Day of week (0 - 7) (Sunday=0 or 7)
| | | ------- Month (1 - 12)
| | --------- Day of month (1 - 31)
| ----------- Hour (0 - 23)
------------- Minute (0 - 59)

Fonte nixCraft .


14
Dovresti usare tempfile o mktemp
Paweł Polewicz,

166
(crontab -l; echo "00 09 * * 1-5 echo hello") | crontab -
Edo,

32
(crontab -l ; echo "00 09 * * 1-5 echo hello") | crontab -- più facile copiare la risposta di Edo
WBAR,

8
Suggerirei di cambiarlo ;con &&una custodia di sicurezza contro il caso se crontab -lfallisce. quindi, come:(crontab -l && echo "0 0 0 0 0 some entry") | crontab -
MacUsers,

12
@MacUsers, crontab -lfallisce se non c'è crontab, quindi usando&& rende impossibile per lo script aggiungere la prima voce al crontab.
JPhi1618,

312

Potresti riuscire a farlo al volo

crontab -l | { cat; echo "0 0 0 0 0 some entry"; } | crontab -

crontab -lelenca i lavori crontab correnti, lo catstampa, echostampa il nuovo comando e crontab -aggiunge tutto il materiale stampato nel file crontab. Puoi vedere l'effetto facendo un nuovo crontab -l.


3
grazie, potresti spiegare la sintassi o indicare un URL che lo spiega?
siti

9
crontab -lelenca i lavori crontab correnti, lo catstampa, echostampa il nuovo comando e crontab -aggiunge tutto il materiale stampato nel file crontab. Puoi vedere l'effetto facendo un nuovocrontab -l
nha

3
Funziona a meraviglia per me. Se l'utente non ha crontab esistente, vedrai no crontab for <username>, ma funziona comunque.
Fazy

21
non funziona sulla mia istanza di Amazon EC2. Invece (crontab -l ; echo "00 09 * * 1-5 echo hello") | crontab -funziona.
Stéphane Bruckert,

11
Sembra un candidato per un UUcatA .
ceving

86

Questo più breve non richiede file temporanei, è immune da inserimenti multipli e consente di modificare la pianificazione di una voce esistente.

Di 'che hai questi:

croncmd="/home/me/myfunction myargs > /home/me/myfunction.log 2>&1"
cronjob="0 */15 * * * $croncmd"

Per aggiungerlo al crontab, senza duplicazioni:

( crontab -l | grep -v -F "$croncmd" ; echo "$cronjob" ) | crontab -

Per rimuoverlo dal crontab qualunque sia il suo programma attuale:

( crontab -l | grep -v -F "$croncmd" ) | crontab -

Appunti:

  • grep -F corrisponde letteralmente alla stringa, poiché non vogliamo interpretarla come un'espressione regolare
  • Ignoriamo anche la pianificazione dei tempi e cerchiamo solo il comando. Per di qua; il programma può essere modificato senza il rischio di aggiungere una nuova linea al crontab

@moeseth: puoi elaborare?
MoonCactus,

dovresti provarlo sul tuo computer
moeseth

2
@moeseth: ovviamente l'ho provato sul mio computer (Linux). Non suggerirei cose non funzionanti casuali: /
MoonCactus

2
A proposito, 27 persone non possono sbagliarsi (ad oggi). Descrivi quindi perché non funziona per la tua configurazione, quindi possiamo aiutarti.
MoonCactus,

2
Potrebbe essere un problema OSX.
Moeseth

40

Grazie a tutti per il vostro aiuto. Mettendo insieme quello che ho trovato qui e altrove, ho pensato a questo:

Il codice

command="php $INSTALL/indefero/scripts/gitcron.php"
job="0 0 * * 0 $command"
cat <(fgrep -i -v "$command" <(crontab -l)) <(echo "$job") | crontab -

Non riuscivo a capire come eliminare la necessità delle due variabili senza ripetermi.

commandè ovviamente il comando che voglio programmare. jobprende$command e aggiunge i dati di pianificazione. Avevo bisogno di entrambe le variabili separatamente nella riga di codice che fa il lavoro.

Dettagli

  1. Ringraziamo duckyflip, uso questo piccolo reindirizzamento thingy ( <(*command*)) per trasformare l'output di crontab -lin input per il fgrepcomando.
  2. fgrepquindi filtra eventuali corrispondenze di $command( -vopzione), senza distinzione tra maiuscole e minuscole (-i opzione).
  3. Ancora una volta, il piccolo reindirizzamento thingy ( <(*command*)) viene utilizzato per trasformare il risultato in input per ilcat comando.
  4. Il catcomando riceve anche echo "$job"(autoesplicativo), di nuovo, attraverso l'uso del cosa di reindirizzamento (<(*command*) ).
  5. Quindi l'output filtrato da crontab -le il semplice echo "$job", combinato, vengono reindirizzati ('|') crontab -per essere infine scritti.
  6. E vissero tutti felici e contenti!

In breve:

Questa riga di codice filtra tutti i lavori cron corrispondenti al comando, quindi scrive i lavori cron rimanenti con quello nuovo, agendo efficacemente come una funzione "aggiungi" o "aggiorna". Per usarlo, tutto ciò che devi fare è scambiare i valori per le variabili commande job.


5
A beneficio della lettura di altri, il vantaggio di questo approccio è che puoi eseguirlo più volte senza preoccuparti di voci duplicate nel crontab (a differenza di tutte le altre soluzioni). Questo a causa delfgrep -v
aleemb

5
Se preferisci il tradizionale modo da sinistra a destra di convogliare le cose, sostituisci l'ultima riga con: crontab -l | fgrep -i -v "$command" | { cat; echo "$job"; } | crontab -l
Antoine Lizée

1
@ AntoineLizée, alla fine hai aggiunto "l" alla fine, che non dovrebbe essere lì.
Henry,

26

EDIT (sovrascrittura fissa):

cat <(crontab -l) <(echo "1 2 3 4 5 scripty.sh") | crontab -

Questo sostituirà qualsiasi contenuto di crontab
TheBonsai,

1
@TheBonsai oh, vedo, l'ho risolto ora, quindi dovrei APPENDERE il nuovo comando ai contenuti crontab esistenti
duckyflip,

3
Tieni presente che la sostituzione del processo di Bash ingoia errori. Se crontab -lfallisce, ma ha crontab -successo, il tuo crontab sarà un one-liner.
ceving

13

Ci sono state molte buone risposte sull'uso di crontab, ma nessuna menzione di un metodo più semplice, come l'uso cron.

Utilizzando cronavrebbe approfittato dei file di sistema e le directory che si trovano a /etc/crontab, /etc/cron.daily,weekly,hourlyo /etc/cron.d/:

cat > /etc/cron.d/<job> << EOF
SHELL=/bin/bash 
PATH=/sbin:/bin:/usr/sbin:/usr/bin 
MAILTO=root HOME=/  
01 * * * * <user> <command>
EOF

In questo esempio, abbiamo creato un file /etc/cron.d/, fornito le variabili di ambiente per l'esecuzione corretta del comando e fornito useril comando e lo commandstesso. Questo file non deve essere eseguibile e il nome deve contenere solo caratteri alfanumerici e trattini (maggiori dettagli di seguito).

Per dare una risposta esauriente, diamo un'occhiata alle differenze tra crontabvs cron/crond:

crontab -- maintain tables for driving cron for individual users

Per coloro che desiderano eseguire il lavoro nel contesto del proprio utente sul sistema, l'utilizzo crontabpuò avere perfettamente senso.

cron -- daemon to execute scheduled commands

Per coloro che usano la gestione della configurazione o vogliono gestire i lavori per altri utenti, nel qual caso dovremmo usare cron .

Un breve estratto dalle pagine man offre alcuni esempi di cosa fare e cosa non fare:

/ etc / crontab e i file in /etc/cron.d devono essere di proprietà di root e non devono essere scrivibili in gruppo o altro. A differenza dell'area di spool, i file in /etc/cron.d oi file in /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly e /etc/cron.monthly possono anche essere symlink, a condizione che sia il symlink sia il file a cui punta appartengano a root. I file in /etc/cron.d non devono essere eseguibili, mentre i file in /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly e /etc/cron.monthly lo fanno, come sono gestiti da run-parts (vedere run-parts (8) per maggiori informazioni).

Fonte: http://manpages.ubuntu.com/manpages/trusty/man8/cron.8.html

Gestire i croni in questo modo è più facile e più scalabile dal punto di vista del sistema, ma non sarà sempre la soluzione migliore.


1
Vale la pena ricordare che <job>non dovrebbe includere un'estensione di file.
jww

7

È probabile che tu stia automatizzando questo e non desideri aggiungere un singolo lavoro due volte. In tal caso utilizzare:

__cron="1 2 3 4 5 /root/bin/backup.sh"
cat <(crontab -l) |grep -v "${__cron}" <(echo "${__cron}")

Funziona solo se stai usando BASH. Non sono a conoscenza della shsintassi DASH ( ) corretta .

Aggiornamento: questo non funziona se l'utente non ha ancora un crontab. Un modo più affidabile sarebbe:

(crontab -l ; echo "1 2 3 4 5 /root/bin/backup.sh") | sort - | uniq - | crontab - 

In alternativa, se la tua distribuzione lo supporta, puoi anche utilizzare un file separato:

echo "1 2 3 4 5 /root/bin/backup.sh" |sudo tee /etc/crond.d/backup

Ho trovato quelli in un'altra domanda SO .


Usi sh invece di bash forse?
kvz,

Sempre sh: 1: Syntax error: "(" unexpectedusando sh .
Batandwa,

Funziona solo se stai usando BASH. Non sono a conoscenza della sintassi DASH (sh) corretta. Aggiornata anche la risposta
kvz

1
prima, ottengo questo errore usando bash se c'è uno spazio tra il <e (. Ciò significa che < (fallisce ma <(funziona, a meno che non ci siano asterischi nel tuo programma ...
Raddoppia il

Credo che questo sia il modo corretto:cat <(crontab -l |grep -v "${CRON}") <(echo "${CRON}") | crontab -
Stanislav

5

Per una bella creazione / sostituzione rapida e sporca di un crontab con uno script BASH, ho usato questa notazione:

crontab <<EOF
00 09 * * 1-5 echo hello
EOF

5

Una variante che modifica crontab solo se la stringa desiderata non viene trovata lì:

CMD="/sbin/modprobe fcpci"
JOB="@reboot $CMD"
TMPC="mycron"
grep "$CMD" -q <(crontab -l) || (crontab -l>"$TMPC"; echo "$JOB">>"$TMPC"; crontab "$TMPC")

3

Se stai usando Vixie Cron, ad esempio sulla maggior parte delle distribuzioni Linux, puoi semplicemente mettere un file in /etc/cron.d con il singolo cronjob.

Questo funziona solo per root, ovviamente. Se il tuo sistema lo supporta, dovresti vedere diversi esempi. (Nota il nome utente incluso nella riga, nella stessa sintassi del vecchio / etc / crontab)

È una triste disfunzione in cron che non ci sia modo di gestirlo come un utente normale e che così tante implementazioni di cron non abbiano alcun modo di gestirlo.


2

Quindi, in Debian, Ubuntu e molte simili distribuzioni basate su Debian ...

Esiste un meccanismo di concatenazione delle attività cron che accetta un file di configurazione, li raggruppa e li aggiunge al servizio cron in esecuzione.

Puoi mettere un file sotto /etc/cron.d/somefilename dove somefilename è quello che vuoi.

sudo echo "0,15,30,45 * * * * ntpdate -u time.nist.gov" >> /etc/cron.d/vmclocksync

Smontiamo questo:

sudo - perché hai bisogno di privilegi elevati per cambiare le configurazioni cron nella directory / etc

echo - un veicolo per creare output su std out. printf, cat ... funzionerebbe pure

"- usa una doppia virgoletta all'inizio della stringa, sei un professionista

0,15,30,45 * * * * - il programma di esecuzione cron standard, questo viene eseguito ogni 15 minuti

ntpdate -u time.nist.gov - il comando effettivo che voglio eseguire

"- perché le mie prime virgolette doppie hanno bisogno di un amico per chiudere la riga in uscita

>> - il doppio reindirizzamento aggiunge anziché sovrascrive *

/etc/cron.d/vmclocksync - vmclocksync è il nome file che ho scelto, va in /etc/cron.d/


* se abbiamo utilizzato il reindirizzamento>, potremmo garantire di avere solo una voce di attività. Ma saremmo a rischio di eliminare qualsiasi altra regola in un file esistente. Puoi decidere tu stesso se la distruzione possibile con> è corretta o i possibili duplicati con >> sono per te. In alternativa, potresti fare qualcosa di contorto o coinvolto per verificare se il nome del file esiste, se c'è qualcosa al suo interno e se stai aggiungendo qualsiasi tipo di duplicato-- ma, ho delle cose da fare e non posso farlo per tu adesso.


2

Script Bash per l'aggiunta di cron job senza l'editor interattivo. Il codice seguente aiuta ad aggiungere un cronjob usando i file linux.

#!/bin/bash

cron_path=/var/spool/cron/crontabs/root

#cron job to run every 10 min.
echo "*/10 * * * * command to be executed" >> $cron_path

#cron job to run every 1 hour.
echo "0 */1 * * * command to be executed" >> $cron_path

1
So che è stato un periodo molto lungo, ma questa è ancora l'unica risposta valida, dal momento che tutti i più votati rimuovono i vecchi croni invece di aggiungere semplicemente quello nuovo.
AFE

1
Questo non installa un cron. Lo aggiunge solo a un file. Dovrai in qualche modo avvisare il processo cron per installare la nuova voce.
Apoorv Parijat,

1

Ecco una funzione bash per aggiungere un comando a crontabsenza duplicazione

function addtocrontab () {
  local frequency=$1
  local command=$2
  local job="$frequency $command"
  cat <(fgrep -i -v "$command" <(crontab -l)) <(echo "$job") | crontab -
}
addtocrontab "0 0 1 * *" "echo hello"

1
CRON="1 2 3 4 5 /root/bin/backup.sh" 
cat < (crontab -l) |grep -v "${CRON}" < (echo "${CRON}")

aggiungi il parametro -w al comando grep esatto, senza il parametro -w l'aggiunta del cronjob "testing" causa la cancellazione del cron job "testing123"

funzione di script per aggiungere / rimuovere cronjobs. nessuna voce di duplicazione:

cronjob_editor () {         
# usage: cronjob_editor '<interval>' '<command>' <add|remove>

if [[ -z "$1" ]] ;then printf " no interval specified\n" ;fi
if [[ -z "$2" ]] ;then printf " no command specified\n" ;fi
if [[ -z "$3" ]] ;then printf " no action specified\n" ;fi

if [[ "$3" == add ]] ;then
    # add cronjob, no duplication:
    ( crontab -l | grep -v -F -w "$2" ; echo "$1 $2" ) | crontab -
elif [[ "$3" == remove ]] ;then
    # remove cronjob:
    ( crontab -l | grep -v -F -w "$2" ) | crontab -
fi 
} 
cronjob_editor "$1" "$2" "$3"

testato:

$ ./cronjob_editor.sh '*/10 * * * *' 'echo "this is a test" > export_file' add
$ crontab  -l
$ */10 * * * * echo "this is a test" > export_file

Se hai lo stesso comando nel crontab due volte (in esecuzione in momenti diversi), la rimozione eliminerà entrambe le righe.
Michaelkay,

1

La mia soluzione preferita a questo sarebbe questa:

(crontab -l | grep . ; echo -e "0 4 * * * myscript\n") | crontab -

Ciò assicurerà di gestire correttamente la nuova riga vuota in fondo. Per evitare problemi con crontab dovresti normalmente terminare il file crontab con una nuova riga vuota. E lo script sopra si assicura che rimuova prima tutte le righe vuote con il "grep". parte e quindi aggiungere una nuova riga vuota alla fine con "\ n" alla fine dello script. Ciò impedirà inoltre di ottenere una riga vuota sopra il nuovo comando se il file crontab esistente termina con una riga vuota.


1
echo "0 * * * * docker system prune --force >/dev/null 2>&1" | sudo tee /etc/cron.daily/dockerprune

0

No, non esiste alcuna opzione in crontab per modificare i file cron.

Devi: prendere il file cron corrente (crontab -l> newfile), cambiarlo e mettere il nuovo file al suo posto (crontab newfile).

Se hai familiarità con perl, puoi usare questo modulo Config :: Crontab .

LLP, Andrea


0

funzione di script per aggiungere cronjobs. controlla voci duplicate, espressioni utilizzabili *> "

cronjob_creator () {         
# usage: cronjob_creator '<interval>' '<command>'

  if [[ -z $1 ]] ;then
    printf " no interval specified\n"
elif [[ -z $2 ]] ;then
    printf " no command specified\n"
else
    CRONIN="/tmp/cti_tmp"
    crontab -l | grep -vw "$1 $2" > "$CRONIN"
    echo "$1 $2" >> $CRONIN
    crontab "$CRONIN"
    rm $CRONIN
fi
}

testato:

$ ./cronjob_creator.sh '*/10 * * * *' 'echo "this is a test" > export_file'
$ crontab  -l
$ */10 * * * * echo "this is a test" > export_file

fonte: il mio cervello;)


-5

Probabilmente puoi modificare l'editor predefinito in ed e usare un heredoc per modificare.

EDITOR=ed
export EDITOR

crontab -e << EOF
> a
> * * * * * Myscript
> * * * * * AnotherScript
> * * * * * MoreScript
> .
> w
> q
> EOF

Nota il carattere > in quel codice indica che il tasto Invio / Invio viene premuto per creare una nuova riga.

Il a significa APPEND quindi non sovrascriverà nulla.

Il . significa che hai finito di modificare.

Il w mezzi scrivere le modifiche.

I q mezzi uscire o uscita ed.

puoi dare un'occhiata

crontab -l

Puoi anche cancellare una voce.

EDITOR=ed
export EDITOR

crontab -e << EOF
> /Myscript/
> d
> .
> w
> q
> EOF

Ciò eliminerà la voce crontab con Myscript al suo interno.

La d significa eliminare il modello all'interno di / / .

No, ricontrolla

crontab -l

Questa soluzione funziona all'interno di uno script anche meno del > ovviamente :-)

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.