Comment créer un crontab via un script

153

J'ai besoin d'ajouter un travail cron à travers un script que j'exécute pour configurer un serveur. J'utilise actuellement Ubuntu. Je peux utiliser crontab -emais cela ouvrira un éditeur pour éditer le crontab actuel. Je veux faire cela par programme.

Est-il possible de le faire?

gaurav
la source
Si vous cherchez à modifier ou supprimer une entrée crontab, consultez ma solution ci-dessous.
Brian Smith

Réponses:

11

Les tâches Cron sont généralement stockées dans un fichier par utilisateur sous /var/spool/cron

La chose la plus simple à faire pour vous est probablement de créer simplement un fichier texte avec le travail configuré, puis de le copier dans le dossier de spool cron et de vous assurer qu'il dispose des bonnes autorisations (600).

Jason Stelzer
la source
20
Modifier les fichiers directement dans / var / spool / cron est mal vu. En fait, si vous regardez les fichiers là-bas, ils contiendront généralement des avertissements tels que "NE PAS MODIFIER CE FICHIER" comme première ligne.
Jared
12
@Jared Bien que je sois tout à fait d'accord avec l'idée, le dire "est mal vu" n'aide pas beaucoup. Indiquez plutôt quel autre fichier doit être modifié, le cas échéant, ou expliquez les risques liés à l'édition manuelle des fichiers. Je prévois de créer des tâches cron via une ligne de commande automatisée, et si l'édition de ce fichier est à la fois la seule option et sans effets secondaires significatifs, je ne vois pas pourquoi je ne devrais pas l'utiliser.
Balmipour
47
Faites défiler vers le bas pour la vraie réponse.
John Red
1
À mon avis, cette réponse est bien meilleure: stackoverflow.com/a/610860/2681752
galaux
2
J'ai adopté cette approche et je l'ai regretté. Sur RHEL, le répertoire / var / spool / cron n'est pas un exécutable universel, les utilisateurs ne peuvent donc pas parcourir le répertoire et modifier leurs fichiers manuellement. Si vous rendez / var / spool / cron world exécutable, votre administrateur système local convivial sera en colère contre vous, et le changement d'autorisation peut être écrasé si le paquet cronie est réinstallé ou mis à jour.
functionvoid
384

Voici une ligne unique qui n'utilise pas / n'exige pas que le nouveau travail soit dans un fichier:

(crontab -l 2>/dev/null; echo "*/5 * * * * /path/to/job -with args") | crontab -

Le 2>/dev/nullest important pour que vous n'obteniez pas le no crontab for usernamemessage que certains * nix produisent s'il n'y a actuellement aucune entrée crontab.

Joe Casadonte
la source
14
Cela devrait être la réponse acceptée. J'ai juste besoin d'un moyen maintenant de vérifier si le one-liner que j'ai l'intention d'ajouter est déjà là ou non ...
ChrisPrime
7
... oh attendez, voici comment vérifier si quelque chose se trouve dans la crontab de mon utilisateur avant de l'ajouter avec un script: stackoverflow.com/a/14451184/3686125
ChrisPrime
1
si ce script est conçu comme une commande à répéter et à modifier une tâche cron existante, il pourrait être intéressant de remplacer la ligne existante dans crontab. plusieurs marqueurs peuvent être utilisés pour contrôler différentes tâches cron (control-marker-1, control-marker-2, etc ...): (crontab -l 2> / dev / null | grep -v control-marker-1; echo '* / 5 * * * * / chemin / vers / travail -avec args # control-marker-1') | crontab -
chef
7
J'ai trouvé que cela supprimait les entrées crontab existantes et que j'avais également besoin d'utiliser un utilisateur différent (root), j'ai donc utilisé ce qui suit pour maintenir les entrées existantes: echo -e "$(sudo crontab -u root -l)\n* * * * * echo hello > /home/danny/temp.log 2>&1" | sudo crontab -u root -J'espère que cela aide quelqu'un
Danny
60

Pour les crontabs utilisateur (y compris root), vous pouvez faire quelque chose comme:

crontab -l -u user | cat - filename | crontab -u user -

où le fichier nommé "filename" contient des éléments à ajouter. Vous pouvez également manipuler du texte en utilisant sedou un autre outil à la place de cat. Vous devez utiliser la crontabcommande au lieu de modifier directement le fichier.

Une opération similaire serait:

{ crontab -l -u user; echo 'crontab spec'; } | crontab -u user -

Si vous modifiez ou créez des crontabs système, ceux-ci peuvent être manipulés comme vous le feriez pour des fichiers texte ordinaires. Ils sont stockés dans les /etc/cron.d, /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthlyrépertoires et dans les fichiers /etc/crontabet /etc/anacrontab.

Suspendu jusqu'à nouvel ordre.
la source
Cela avait l'air prometteur mais en essayant la deuxième approche (avec echo), j'ai obtenu "crontab: erreur d'utilisation: le nom du fichier doit être spécifié pour le remplacement." La page de manuel Cron affiche la syntaxe crontab [ -u user ] file, c'est-à-dire avec un nom de fichier obligatoire. Y a-t-il une astuce pour lui faire accepter les données acheminées à la place?
Mark Berry
1
@MarkBerry: Désolé pour ça. Dans un tube, un trait d'union doit être utilisé pour indiquer que l'entrée provient stdin. Je vais corriger ma réponse.
Suspendu jusqu'à nouvel ordre.
29

Dans Ubuntu et de nombreuses autres distributions, vous pouvez simplement placer un fichier dans le /etc/cron.drépertoire contenant une seule ligne avec une entrée crontab valide . Pas besoin d'ajouter une ligne à un fichier existant.

Si vous avez juste besoin de quelque chose à exécuter quotidiennement, mettez simplement un fichier dans /etc/cron.daily. De même, vous pouvez également déposer des fichiers dans /etc/cron.hourly, /etc/cron.monthlyet /etc/cron.weekly.

IvanGoneKrazy
la source
5
Mais vous devez être root pour faire cela.
Keith le
17

Une réponse encore plus simple à votre question serait:

echo "0 1 * * * /root/test.sh" | tee -a /var/spool/cron/root

Vous pouvez configurer des cronjobs sur des serveurs distants comme ci-dessous:

#!/bin/bash
servers="srv1 srv2 srv3 srv4 srv5"
for i in $servers
  do
  echo "0 1 * * * /root/test.sh" | ssh $i " tee -a /var/spool/cron/root"
done

Sous Linux, l'emplacement par défaut du crontabfichier est /var/spool/cron/. Ici vous pouvez trouver les crontabfichiers de tous les utilisateurs. Il vous suffit d'ajouter votre entrée cronjob au fichier de l'utilisateur respectif. Dans l'exemple ci-dessus, le fichier crontab de l'utilisateur racine est ajouté avec un cronjob à exécuter /root/test.shtous les jours à 1 heure du matin.

ganesh pathak
la source
Ce serait /var/spool/cron/crontabs/rootsur Ubuntu.
Íhor Mé le
17

Les fichiers Crontab sont simplement des fichiers texte et peuvent donc être traités comme n'importe quel autre fichier texte. Le but de la crontabcommande est de rendre l'édition des fichiers crontab plus sûre. Lorsqu'il est édité via cette commande, le fichier est vérifié pour les erreurs et enregistré uniquement s'il n'y en a pas.

crontab [path to file]peut être utilisé pour spécifier une crontab stockée dans un fichier. Comme crontab -e, cela installera le fichier uniquement s'il est sans erreur.

Par conséquent, un script peut soit écrire directement les fichiers de l'onglet cron, soit les écrire dans un fichier temporaire et les charger avec la crontab [path to temp file]commande. L'écriture directe évite d'avoir à écrire un fichier temporaire, mais évite également le contrôle de sécurité.

Cledoux
la source
2
Pour les noobs comme moi, notez que c'est le cas crontab [path to file]. C'était définitivement la meilleure option pour moi, car elle permet un code plus lisible. J'utilise crontab pour suivre les colis et changer mon fond d'écran avec l'état. Lorsque je n'attends pas de colis, il n'est pas nécessaire de vérifier toutes les heures. C'est pourquoi je voulais que le script édite automatiquement la fréquence cron.
Rasmus
1
@Rasmus Cela ressemble à un script génial que j'aimerais pouvoir voler. Une chance de partager via un contenu essentiel ou similaire?
cledoux
8

(Je n'ai pas assez de réputation pour commenter, donc j'ajoute à comme réponse: n'hésitez pas à l'ajouter comme commentaire à côté de sa réponse)

Le one-liner de Joe Casadonte est parfait, sauf si vous exécutez avec set -e, c'est-à-dire si votre script est configuré pour échouer en cas d'erreur, et s'il n'y a pas encore de cronjobs. Dans ce cas, le one-liner ne créera PAS le cronjob, mais n'arrêtera PAS le script. L'échec silencieux peut être très trompeur.

La raison en est que crontab -lretourne avec un 1code de retour, echoempêchant l'exécution de la commande suivante (le ) ... ainsi le cronjob n'est pas créé. Mais comme ils sont exécutés en tant que sous-processus (à cause de la parenthèse), ils n'arrêtent pas le script.

( Fait intéressant, si vous exécutez la même commande à nouveau, il fonctionnera: une fois que vous avez exécuté crontab -une fois, crontab -lrien encore sorties, mais il ne plus (vous ne recevez pas revenir pas d'erreur le no crontab for <user>message de plus) Ainsi , la suite. echoEst exécuté et le crontab est créé)

Dans tous les cas, si vous exécutez avec set -e, la ligne doit être:

(crontab -l 2>/dev/null || true; echo "*/5 * * * * /path/to/job -with args") | crontab -
Faria
la source
Oui, celui-ci est encore plus parfait.
Yngve Sneen Lindal le
7

Pour corriger ceux qui suggèrent crontab -l | crontab -: cela ne fonctionne pas sur tous les systèmes. Par exemple, j'ai dû ajouter un travail à la crontab racine sur des dizaines de serveurs exécutant une ancienne version SUSE (ne demandez pas pourquoi). Les anciens SUSE ajoutent des lignes de commentaires à la sortie de crontab -l, ce qui rend crontab -l | crontab -non idempotent (Debian reconnaît ce problème dans la page de manuel crontab et a patché sa version de Vixie Cron pour changer le comportement par défaut de crontab -l).

Pour modifier les crontabs par programmation sur les systèmes où crontab -lajoute des commentaires, vous pouvez essayer ce qui suit:

EDITOR=cat crontab -e > old_crontab; cat old_crontab new_job | crontab -

EDITOR=catdit à crontab de l'utiliser catcomme éditeur (pas le vi par défaut habituel), ce qui ne change pas le fichier, mais le copie à la place dans stdout. Cela peut toujours échouer si crontab -attend une entrée dans un format différent de celui des crontab -esorties. N'essayez pas de remplacer la finale crontab -par crontab -e- cela ne fonctionnera pas.

user2845840
la source
4

Eh bien, /etc/crontabjuste un fichier ascii donc le plus simple est de simplement

 echo "*/15 * * * *   root     date" >> /etc/crontab

qui ajoutera un travail qui vous enverra un e-mail toutes les 15 minutes. Ajustez-les selon vos goûts et testez via grepou d'autres moyens si la ligne a déjà été ajoutée pour rendre votre script idempotent.

Sur Ubuntu et al, vous pouvez également déposer des fichiers dans /etc/cron.*lesquels il est plus facile de faire et de tester --- plus vous ne jouez pas avec les fichiers de configuration (système) tels que /etc/crontab.

Dirk Eddelbuettel
la source
1
Je pense que techniquement crond n'est pas nécessaire pour surveiller les modifications apportées à crontab, même si en réalité la plupart des implémentations le font, je recommanderais donc un appel à crontab -e après pour le produire. crontab -e honore la variable EDITOR si la mémoire est bonne, donc la définir sur / bin / true pour le moment devrait simplement forcer la relecture de la crontab.
Ulrich Schwarz le
1
Vrai encore sur un système Linux récent crond ne contrôle, et il le fait sans aucun doute sur la plate - forme indiquée de l'OP.
Dirk Eddelbuettel
Seulement si vous êtes root et que vous souhaitez que le script s'exécute en tant que root. Cela pourrait ne pas être souhaitable dans le cas des PO.
Keith le
Pas ainsi, j'ai beaucoup d'entrées non root dans / etc / crontab. Vous avez «simplement» besoin de sudo pour l'ajouter au fichier. Quoi qu'il en soit, comme je l'ai dit, il y a aussi /etc/cron.*/ mais il faut aussi être root pour y écrire.
Dirk Eddelbuettel
2

Voici comment modifier cron une entrée sans éditer directement le fichier cron (ce qui est mal vu).

crontab -l -u <user> | sed 's/find/replace/g' | crontab -u <user> -

Si vous souhaitez supprimer une entrée cron, utilisez ceci:

crontab -l -u <user> | sed '/find/d' | crontab -u <user> -

Je me rends compte que ce n'est pas ce que demandait gaurav, mais pourquoi ne pas avoir toutes les solutions en un seul endroit?

Brian Smith
la source
1

J'ai écrit un outil de déploiement crontab en python: https://github.com/monklof/deploycron

pip install deploycron

L'installation de votre crontab est très simple, cela fusionnera la crontab dans la crontab existante du système.

from deploycron import deploycron
deploycron(content="* * * * * echo hello > /tmp/hello")
monklof
la source
1

C'est une approche pour ajouter progressivement le travail cron:

  ssh USER_NAME@$PRODUCT_IP nohup "echo '*/2 * * * * ping -c2 PRODUCT_NAME.com >> /var/www/html/test.html' | crontab -u USER_NAME -"
Oleksii Kyslytsyn
la source