Comment créer un travail cron en utilisant Bash automatiquement sans l'éditeur interactif?

395

Crontab a-t-il un argument pour créer des tâches cron sans utiliser l'éditeur (crontab -e). Si oui, quel serait le code pour créer un cronjob à partir d'un script Bash?

Raúl Roa
la source
5
Malheureusement, la plupart des principales réponses ici montrent simplement comment modifier crontab - bien que de manière raisonnablement sûre - mais je pense que c'est globalement la mauvaise approche. Mieux, plus sûr et plus simple consiste à déposer un fichier dans {{cron.d}}, et il existe (actuellement) des réponses à faible vote expliquant comment procéder si vous regardez plus loin.
gregmac

Réponses:

539

Vous pouvez ajouter à la crontab comme suit:

#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

Explication de la ligne 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)

Source nixCraft .

dogbane
la source
14
Vous devez utiliser tempfile ou mktemp
Paweł Polewicz
166
(crontab -l; écho "00 09 * * 1-5 écho bonjour") | crontab -
Edo
32
(crontab -l ; echo "00 09 * * 1-5 echo hello") | crontab -- plus facile à copier le répondeur d'Edo
WBAR
8
Je suggérerais de changer cela ;avec &&comme garde-fou contre le cas en cas d' crontab -léchec. donc, comme:(crontab -l && echo "0 0 0 0 0 some entry") | crontab -
MacUsers
12
@MacUsers, crontab -léchoue s'il n'y a pas de crontab, donc l'utilisation &&rend impossible pour le script d'ajouter la première entrée à la crontab.
JPhi1618
312

Vous pourrez peut-être le faire à la volée

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

crontab -lrépertorie les travaux crontab actuels, l' catimprime, echoimprime la nouvelle commande et crontab -ajoute tous les éléments imprimés dans le fichier crontab. Vous pouvez voir l'effet en faisant une nouvelle crontab -l.

TheBonsai
la source
3
merci, pourriez-vous expliquer la syntaxe, ou pointer vers une URL qui l'explique?
sites
9
crontab -lrépertorie les travaux crontab actuels, l' catimprime, echoimprime la nouvelle commande et crontab -ajoute tous les éléments imprimés dans le fichier crontab. Vous pouvez voir l'effet en faisant une nouvellecrontab -l
nha
3
Fonctionne un régal pour moi. Si l'utilisateur n'a pas de crontab existant, vous le verrez no crontab for <username>, mais cela fonctionne quand même.
fazy
21
ne fonctionne pas sur mon instance Amazon EC2. Au lieu de cela, (crontab -l ; echo "00 09 * * 1-5 echo hello") | crontab -fonctionne.
Stéphane Bruckert
11
Cela ressemble à un candidat pour un UUcatA .
ceving
86

Celui-ci, plus court, ne nécessite aucun fichier temporaire, il est à l'abri de plusieurs insertions et il vous permet de modifier la planification d'une entrée existante.

Dites que vous en avez:

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

Pour l'ajouter à la crontab, sans duplication:

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

Pour le supprimer de la crontab quelle que soit sa programmation actuelle:

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

Remarques:

  • grep -F correspond littéralement à la chaîne, car nous ne voulons pas l'interpréter comme une expression régulière
  • Nous ignorons également la programmation horaire et ne recherchons que la commande. Par ici; l'horaire peut être modifié sans risque d'ajouter une nouvelle ligne à la crontab
MoonCactus
la source
@moeseth: pouvez-vous élaborer?
MoonCactus
vous devriez l'essayer sur votre ordinateur
moeseth
2
@moeseth: Je l'ai évidemment essayé sur mon ordinateur (linux). Je ne suggérerais pas de choses aléatoires non fonctionnelles: /
MoonCactus
2
Soit dit en passant, 27 personnes ne peuvent pas se tromper (à ce jour). Veuillez donc expliquer pourquoi cela ne fonctionne pas pour votre configuration, afin que nous puissions vous aider.
MoonCactus
2
Ce pourrait être un problème OSX.
moeseth
40

Merci à tous pour votre aide. Assemblant ce que j'ai trouvé ici et ailleurs, j'ai trouvé ceci:

Le code

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

Je ne pouvais pas comprendre comment éliminer le besoin des deux variables sans me répéter.

commandest évidemment la commande que je veux programmer. jobprend $commandet ajoute les données de planification. J'avais besoin des deux variables séparément dans la ligne de code qui fait le travail.

Détails

  1. Crédit à duckyflip, j'utilise ce petit truc de redirection ( <(*command*)) pour transformer la sortie de crontab -len entrée pour la fgrepcommande.
  2. fgrepfiltre ensuite toutes les correspondances de $command( -voption), insensible à la casse ( -ioption).
  3. Encore une fois, la petite chose de redirection ( <(*command*)) est utilisée pour transformer le résultat en entrée pour la catcommande.
  4. La catcommande reçoit égalementecho "$job" (auto-explicative), encore une fois, grâce à l'utilisation de la chose de redirection ( <(*command*)).
  5. Ainsi, la sortie filtrée de crontab -let la simple echo "$job", combinée, sont redirigées ('|') verscrontab - pour être finalement écrites.
  6. Et ils ont tous vécu heureux pour toujours!

En un mot:

Cette ligne de code filtre tous les travaux cron qui correspondent à la commande, puis écrit les travaux cron restants avec le nouveau, agissant efficacement comme une fonction "ajouter" ou "mettre à jour". Pour l'utiliser, tout ce que vous avez à faire est de remplacer les valeurs des variables commandet job.

Stoutie
la source
5
Pour le bénéfice des autres lecteurs, l'avantage de cette approche est que vous pouvez l'exécuter plusieurs fois sans vous soucier des entrées en double dans la crontab (contrairement à toutes les autres solutions). C'est à cause dufgrep -v
aleemb
5
Si vous préférez la façon traditionnelle de tuyauterie de gauche à droite, remplacez la dernière ligne par: crontab -l | fgrep -i -v "$command" | { cat; echo "$job"; } | crontab -l
Antoine Lizée
1
@ AntoineLizée, vous répondez a un "l" supplémentaire à la fin, qui ne devrait pas être là.
Henry
26

EDIT (écrasement fixe):

cat <(crontab -l) <(echo "1 2 3 4 5 scripty.sh") | crontab -
duckyflip
la source
Cela remplacera tout contenu crontab
TheBonsai
1
@TheBonsai oh je vois, je l'ai corrigé maintenant donc il devrait AJOUTER la nouvelle commande au contenu crontab existant
duckyflip
3
Gardez à l'esprit que la substitution de processus de Bash avale les erreurs. Si crontab -léchoue, mais crontab -réussit, votre crontab sera un one-liner.
ceving
13

Il y a eu beaucoup de bonnes réponses autour de l'utilisation de crontab, mais aucune mention d'une méthode plus simple, comme l'utilisation cron.

L'utilisation cronprofiterait des fichiers système et des répertoires situés dans /etc/crontab, /etc/cron.daily,weekly,hourlyou /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

Dans cet exemple ci-dessus, nous avons créé un fichier dans /etc/cron.d/, fourni les variables d'environnement pour que la commande s'exécute avec succès, et fourni le userpour la commande et le commandlui - même. Ce fichier ne doit pas être exécutable et le nom ne doit contenir que des caractères alphanumériques et des tirets (plus de détails ci-dessous).

Pour donner une réponse approfondie, examinons les différences entre crontabvs cron/crond:

crontab -- maintain tables for driving cron for individual users

Pour ceux qui souhaitent exécuter le travail dans le contexte de leur utilisateur sur le système, l'utilisation crontabpeut être parfaitement logique.

cron -- daemon to execute scheduled commands

Pour ceux qui utilisent la gestion de configuration ou qui souhaitent gérer des travaux pour d'autres utilisateurs, auquel cas nous devrions utiliser cron.

Un extrait rapide des pages de manuel vous donne quelques exemples de ce qu'il faut faire et ne pas faire:

/ etc / crontab et les fichiers dans /etc/cron.d doivent appartenir à root et ne doivent pas être accessibles en écriture groupée ou autre. Contrairement à la zone de spoule, les fichiers sous /etc/cron.d ou les fichiers sous /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly et /etc/cron.monthly peuvent également être liens symboliques, à condition que le lien symbolique et le fichier vers lequel il pointe appartiennent à root. Les fichiers sous /etc/cron.d n'ont pas besoin d'être exécutables, tandis que les fichiers sous /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly et /etc/cron.monthly le font, comme ils sont exécutés par run-parts (voir run-parts (8) pour plus d'informations).

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

La gestion de crons de cette manière est plus facile et plus évolutive du point de vue du système, mais ne sera pas toujours la meilleure solution.

Mike Mackintosh
la source
1
Il peut être utile de mentionner qu'il <job>ne doit pas inclure d'extension de fichier.
2019
7

Il y a de fortes chances que vous automatisiez cela et que vous ne souhaitiez pas qu'un seul travail soit ajouté deux fois. Dans ce cas, utilisez:

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

Cela ne fonctionne que si vous utilisez BASH. Je ne connais pas la shsyntaxe DASH ( ) correcte .

Mise à jour: cela ne fonctionne pas si l'utilisateur n'a pas encore de crontab. Un moyen plus fiable serait:

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

Alternativement, si votre distribution le prend en charge, vous pouvez également utiliser un fichier distinct:

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

Trouvé ceux dans une autre question SO .

kvz
la source
Utiliser sh au lieu de bash peut-être?
kvz
Toujours obtenir l' sh: 1: Syntax error: "(" unexpectedaide sh .
Batandwa
Cela ne fonctionne que si vous utilisez BASH. Je ne connais pas la syntaxe DASH (sh) correcte. Mise à jour de la réponse également
kvz
1
fwiw, j'obtiens cette erreur en utilisant bash s'il y a un espace entre le <et (. Cela signifie qu'il < (échoue mais <(fonctionne, sauf s'il y a des astérisques dans votre emploi du temps ...
doublesharp
Je crois que c'est la bonne façon:cat <(crontab -l |grep -v "${CRON}") <(echo "${CRON}") | crontab -
Stanislav le
5

Pour une belle création / remplacement rapide et sale d'une crontab avec un script BASH, j'ai utilisé cette notation:

crontab <<EOF
00 09 * * 1-5 echo hello
EOF
Gibbsoft
la source
5

Une variante qui n'édite crontab que si la chaîne souhaitée n'y est pas trouvée:

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

Si vous utilisez Vixie Cron, par exemple sur la plupart des distributions Linux, vous pouvez simplement mettre un fichier dans /etc/cron.d avec le cronjob individuel.

Cela ne fonctionne bien sûr que pour root. Si votre système le prend en charge, vous devriez y voir plusieurs exemples. (Notez le nom d'utilisateur inclus dans la ligne, dans la même syntaxe que l'ancien / etc / crontab)

C'est une triste erreur dans cron qu'il n'y a aucun moyen de gérer cela en tant qu'utilisateur régulier, et que tant d'implémentations cron n'ont aucun moyen de gérer cela.

mandrin
la source
2

Donc, dans Debian, Ubuntu et de nombreuses distributions similaires basées sur Debian ...

Il existe un mécanisme de concaténation des tâches cron qui prend un fichier de configuration, les regroupe et les ajoute à votre service cron en cours d'exécution.

Vous pouvez placer un fichier sous /etc/cron.d/somefilename où somefilename est ce que vous voulez.

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

Démontons ceci:

sudo - parce que vous avez besoin de privilèges élevés pour modifier les configurations cron sous le répertoire / etc

echo - un véhicule pour créer une sortie en sortie standard. printf, cat ... fonctionnerait aussi

"- utilisez un guillemet double au début de votre chaîne, vous êtes un professionnel

0,15,30,45 * * * * - le programme de cron standard, celui-ci s'exécute toutes les 15 minutes

ntpdate -u time.nist.gov - la commande réelle que je veux exécuter

"- parce que mes premiers guillemets doubles ont besoin d'un copain pour fermer la ligne en cours de sortie

>> - la double redirection s'ajoute au lieu d'écraser *

/etc/cron.d/vmclocksync - vmclocksync est le nom de fichier que j'ai choisi, il va dans /etc/cron.d/


* si nous avons utilisé la redirection>, nous pourrions garantir que nous n'avions qu'une seule entrée de tâche. Mais nous risquerions de supprimer toute autre règle dans un fichier existant. Vous pouvez décider par vous-même si la destruction possible avec> est correcte ou si les doublons possibles avec >> sont pour vous. Alternativement, vous pouvez faire quelque chose de compliqué ou d'impliquer pour vérifier si le nom de fichier existe, s'il y a quelque chose dedans et si vous ajoutez n'importe quel type de doublon - mais, j'ai des choses à faire et je ne peux pas le faire pour vous maintenant.

BradChesney79
la source
2

Script Bash pour ajouter un travail cron sans l'éditeur interactif. Le code ci-dessous permet d'ajouter un cronjob à l'aide de fichiers 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
akash
la source
1
Je sais que cela fait longtemps, mais c'est toujours la seule bonne réponse, car tous les plus votés suppriment les anciens crons au lieu de simplement ajouter le nouveau.
afe
1
Celui-ci n'installe pas de cron. Il l'ajoute simplement à un fichier. Vous devrez en quelque sorte notifier le processus cron pour installer la nouvelle entrée.
Apoorv Parijat
2
echo "0 * * * * docker system prune --force >/dev/null 2>&1" | sudo tee /etc/cron.daily/dockerprune
user11547308
la source
1

Voici une fonction bash pour ajouter une commande à crontabsans duplication

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"
Klas Mellbourn
la source
1
CRON="1 2 3 4 5 /root/bin/backup.sh" 
cat < (crontab -l) |grep -v "${CRON}" < (echo "${CRON}")

ajouter le paramètre -w à la commande grep exacte, sans que le paramètre -w ajoute le cronjob "testing" entraîne la suppression du travail cron "testing123"

fonction de script pour ajouter / supprimer des cronjobs. aucune entrée de duplication:

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"

testé:

$ ./cronjob_editor.sh '*/10 * * * *' 'echo "this is a test" > export_file' add
$ crontab  -l
$ */10 * * * * echo "this is a test" > export_file
speefak
la source
Si vous avez deux fois la même commande dans la crontab (exécutée à des moments différents), la suppression supprimera les deux lignes.
Michaelkay
1

Ma solution préférée serait la suivante:

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

Cela garantira que vous gérez correctement la nouvelle ligne vierge en bas. Pour éviter les problèmes avec crontab, vous devez généralement terminer le fichier crontab par une nouvelle ligne vierge. Et le script ci-dessus s'assure qu'il supprime d'abord toutes les lignes vides avec le "grep". partie, puis ajoutez une nouvelle ligne vierge à la fin avec le "\ n" à la fin du script. Cela empêchera également d'obtenir une ligne vierge au-dessus de votre nouvelle commande si votre fichier crontab existant se termine par une ligne vierge.

gsus
la source
0

Non, il n'y a pas d'option dans crontab pour modifier les fichiers cron.

Vous devez: prendre le fichier cron actuel (crontab -l> newfile), le changer et mettre le nouveau fichier en place (crontab newfile).

Si vous connaissez Perl, vous pouvez utiliser ce module Config :: Crontab .

LLP, Andrea

andcoz
la source
0

fonction de script pour ajouter des tâches cron. vérifier les entrées en double, les expressions utilisables *> "

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
}

testé:

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

source: mon cerveau;)


la source
-5

Vous pouvez probablement changer l'éditeur par défaut en ed et utiliser un hérédoc pour éditer.

EDITOR=ed
export EDITOR

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

Notez le début > dans ce code signifie que la touche retour / entrée est enfoncée pour créer une nouvelle ligne.

Le a signifie APPEND afin qu'il n'écrase rien.

Le . signifie que vous avez terminé l'édition.

Le w signifie ÉCRIRE les modifications.

Le q signifie QUIT ou exit ed.

vous pouvez le vérifier

crontab -l

Vous pouvez également supprimer une entrée.

EDITOR=ed
export EDITOR

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

Cela supprimera l'entrée crontab contenant Myscript.

Le d signifie supprimer le motif à l'intérieur du / / .

Non, revérifiez

crontab -l

Cette solution fonctionne à l'intérieur d'un script trop moins > bien sûr :-)

Jetchisel
la source