Docs/ Opérations/ Tâches cron

Tâches cron

Exécutez une commande ou une requête HTTP selon un planning. Lisez « Où la commande s'exécute » avant votre première tâche : une tâche planifiée ne s'exécute pas dans le conteneur en marche de votre application, mais dans un conteneur jetable qui reçoit les mêmes variables.

Création d'une tâche cron

Les tâches planifiées se gèrent depuis la page Tâches cron du tableau de bord, ou avec sh0 cron. Une tâche est en général rattachée à une application.

  1. Ouvrez Tâches cron dans la barre latérale et cliquez sur Créer une tâche planifiée.
  2. Nom -- un libellé, par exemple nightly-report.
  3. Application -- l'application à laquelle la tâche appartient. Sans application, seules les commandes HTTP sont acceptées (voir plus bas).
  4. Planification -- une expression cron à 5 champs, évaluée en UTC.
  5. Commande -- une requête HTTP (curl, wget ou une URL seule), ou un programme à lancer dans un conteneur.
  6. Facultatif : une Image du conteneur (vide = l'image de l'application) et un Délai d'expiration (secondes), 300 par défaut. Créez ensuite la tâche.

La même chose en ligne de commande, sur un serveur où ces commandes ont été exécutées :

Terminal
$ sh0 cron create --app my-api --name nightly-report \
    --schedule "0 3 * * *" \
    --command "curl -s -X POST https://api.example.com/internal/report"
Cron job 'nightly-report' created (id: 72173a56-1962-47dc-88e5-2a276ef3bfcc)

$ sh0 cron trigger 72173a56-1962-47dc-88e5-2a276ef3bfcc
Cron job 'nightly-report' triggered.

$ sh0 cron runs 72173a56-1962-47dc-88e5-2a276ef3bfcc
RUN ID                                STATUS      EXIT    DURATION    STARTED
----------------------------------------------------------------------------------------------------
9e329bc7-01c5-41ec-9eb5-5ab745fde533  success     0       295ms       2026-10-02 02:33:23

Où la commande s'exécute

sh0 choisit le mode d'exécution d'après la commande et les réglages de la tâche, dans cet ordre :

  • Requête HTTP -- une commande commençant par curl ou wget, ou une URL seule, n'est pas exécutée par un shell : sh0 envoie lui-même la requête, depuis le serveur, avec une limite de 30 secondes. -X, -H et -d sont pris en compte. Un statut de réponse de 400 ou plus marque l'exécution comme échouée. Pour une tâche rattachée à une application, un nom interne de son projet (my-api.internal, ou my-api seul) est résolu vers ce service.
  • Image de l'application -- toute autre commande s'exécute dans un nouveau conteneur jetable démarré depuis l'image actuelle de l'application, sous un utilisateur non root, sur le réseau sh0 et sur le réseau de son projet. Ce n'est pas votre conteneur en marche : les fichiers écrits par l'application pendant son exécution n'y sont pas, et le conteneur est supprimé après l'exécution.
  • Image explicite -- si Image du conteneur est renseignée, le conteneur jetable part de cette image.
  • Ni application ni image -- une commande non HTTP est refusée au moment de l'exécution. sh0 n'exécute jamais une commande planifiée sur l'hôte.
Note
Depuis 1.10.3 : Le conteneur reçoit les variables de votre application. Une tâche rattachée à une application reçoit ses variables d'exécution et celles de son projet, la valeur de l'application l'emportant, exactement comme les conteneurs de l'application. Les variables de build ne sont pas transmises. La sortie d'une tâche est conservée dans son historique : une commande qui affiche un secret l'y laisse, lisible par toute personne ayant l'accès développeur à l'application.

Mesuré sur une application Node.js portant GREETING sur l'application et REGION sur son projet : la tâche env affiche les deux, à côté des variables intégrées à l'image.

env -- app image (Node.js 22)
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=0.0.0.0
REGION=eu431
GREETING=hello431
NODE_VERSION=22.23.3
YARN_VERSION=1.22.22
PORT=3000
HOME=/home/node

GREETING et REGION sont bien présentes. La ligne HOME=/home/node montre l'utilisateur non root.

Règles de commande

Une commande est un seul programme suivi de ses arguments. sh0 la vérifie à la création de la tâche :

  • Pas de shell. Les caractères ; | & > < et l'accent grave, $( et les sauts de ligne sont refusés. Pas de tubes, pas d'enchaînements &&, pas d'expansion de variables.
  • Les guillemets ne comptent que pour les requêtes HTTP. Dans un conteneur, la commande est découpée sur les espaces : sh -c "echo hi" ne fait pas ce que ferait un shell. Pour les requêtes HTTP, les guillemets sont respectés, donc -H "Authorization: Bearer …" fonctionne.
  • Les redirections sont retirées plutôt que refusées : > /dev/null, 2>/dev/null, &> /dev/null et 2>&1 sont supprimées avant la vérification, si bien qu'une ligne collée depuis une crontab est acceptée.
  • 4 096 caractères au plus.
Terminal
$ sh0 cron create --app my-api --name cleanup --schedule "0 3 * * *" --command "env | grep X"
Error: Invalid command: Command contains forbidden character '|'. Use simple commands without shell operators. (VALIDATION_ERROR)

Tâches qui ont besoin de la base ou de secrets

Une tâche rattachée à une application voit ses variables et résout les noms internes de son projet : une commande comme python manage.py cleanup lit la même DATABASE_URL et joint le même db.internal. Quand le travail a sa place dans votre application en marche, deux autres voies restent possibles :

  • Un point d'accès HTTP. Exposez la tâche comme une route de votre application, protégée par un jeton, et laissez la tâche planifiée l'appeler par son nom interne. Le travail s'exécute dans votre application en marche, avec sa connexion à la base et ses secrets.
  • Ou planifiez dans l'application, avec l'ordonnanceur de votre framework (par exemple Celery beat, node-cron ou le planificateur de Laravel), quand la tâche ne doit pas du tout être joignable en HTTP.
Command
curl -s -X POST -H "Authorization: Bearer <token>" http://my-api.internal:3000/internal/cleanup
Note
sh0 envoie la requête depuis le serveur et résout my-api.internal (ou my-api) parmi les services en marche du seul projet de la tâche. Un nom qui ne désigne aucun service en marche échoue avec un message explicite ; une application hors projet, ou qui tourne sur un nœud distant, doit être appelée par son URL publique. Le jeton figure en clair dans la commande de la tâche, visible par quiconque peut lire la tâche : ne lui donnez aucun autre usage.

Syntaxe des expressions cron

sh0 utilise des expressions cron standard à 5 champs. Chaque champ représente une unité de temps :

Cron expression format
┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-6, Sunday = 0)
│ │ │ │ │
* * * * *
SymboleSignificationExemple
*Toutes les valeurs* * * * * = chaque minute
,Liste de valeurs0 8,12,18 * * * = 8h, midi, 18h
-Plage0 9-17 * * * = toutes les heures de 9h à 17h
/Pas*/15 * * * * = toutes les 15 minutes

Schémas courants

Frequently used cron schedules
# Every minute
* * * * *

# Every 5 minutes
*/5 * * * *

# Every hour at minute 0
0 * * * *

# Every day at midnight
0 0 * * *

# Every day at 3:30 AM
30 3 * * *

# Every Monday at 9:00 AM
0 9 * * 1

# First day of every month at midnight
0 0 1 * *

# Every weekday (Mon-Fri) at 6:00 AM
0 6 * * 1-5
Note
Les planifications sont évaluées en UTC, quel que soit le fuseau horaire du serveur. 0 3 * * * s'exécute à 03:00 UTC. L'ordonnanceur cherche les tâches dues toutes les 60 secondes : une exécution peut donc démarrer jusqu'à une minute après son heure.

Historique d'exécution et logs

Chaque exécution est enregistrée avec son statut (success, failed ou timeout), son code de sortie, sa durée, ses heures de début et de fin, et sa sortie. Dans le tableau de bord, ouvrez Historique d'exécution sur une tâche, puis affichez la sortie d'une exécution. En ligne de commande : sh0 cron runs <id>.

Note
sh0 conserve les 100 dernières exécutions de chaque tâche et supprime les plus anciennes. La sortie standard et la sortie d'erreur sont conservées chacune jusqu'à 64 Ko.

Activation et désactivation des tâches

  • Désactiver arrête les exécutions planifiées sans supprimer la tâche ni son historique ; Activer les reprend.
  • Déclencher maintenant (ou sh0 cron trigger <id>) lance une exécution immédiatement, quel que soit le calendrier.
  • Supprimer une tâche (sh0 cron delete <id>) supprime aussi son historique.

Délais, chevauchement et limites

  • Délai d'expiration -- 300 secondes par défaut (--timeout en ligne de commande). Une exécution qui le dépasse est enregistrée avec le statut timeout et le message « Job timed out after Ns ».
  • Chevauchement -- tant qu'une exécution d'une tâche est en cours, l'ordonnanceur n'en lance pas d'autre. L'occurrence sautée n'apparaît pas dans l'historique.
  • 50 tâches par application.
  • Ni nouvelle tentative ni notification d'échec. Une exécution en échec n'est pas relancée et ne déclenche aucune alerte : consultez l'historique, ou faites signaler ses propres échecs par le point d'entrée qu'appelle la tâche.