← retour aux snippets

nohup/setsid/disown: détacher un processus proprement

Lancer une tâche qui survit à la déconnexion (SSH), sans TTY, avec logs et contrôle du PID.


objectif

Exécuter une commande longue (build, import, crawl) qui continue après la fermeture du terminal/SSH. Détacher correctement du TTY, rediriger les logs et récupérer le PID pour superviser/arrêter.

code minimal

# détacher proprement: pas de TTY, ignore SIGHUP, logs dédiés
nohup setsid bash -lc 'npm run build' > ./build.out 2> ./build.err < /dev/null &
echo $! > ./build.pid
disown

utilisation

# 1) lancer un job (ex: génération data.pm) avec logs datés
ts="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
nohup setsid bash -lc "npm ci && npm run build" \
  > "./logs/build-$ts.out" 2> "./logs/build-$ts.err" < /dev/null &
echo $! > "./run/build-$ts.pid"
disown

# 2) vérifier qu'il tourne encore (par PID)
pid="$(cat "./run/build-$ts.pid")"
ps -p "$pid" -o pid,ppid,stat,etime,cmd | sed -n '2p'

# 3) stopper proprement (SIGTERM), puis (si besoin) SIGKILL
kill -TERM "$pid" 2>/dev/null || true
sleep 2
ps -p "$pid" >/dev/null && kill -KILL "$pid" 2>/dev/null || true

# 4) récupérer la sortie en live
tail -n 50 -F "./logs/build-$ts.out"

# 5) variante simple en one-liner (log unique, PID)
nohup setsid bash -lc 'curl -fsS https://api.data.pm/health > /dev/null' \
  > ./job.out 2>&1 < /dev/null & echo $! > ./job.pid; disown

variante(s) utile(s)

# rendre l'exécution plus discrète (baisser priorité CPU/IO sur Linux)
nohup setsid bash -lc 'nice -n 10 ionice -c3 npm run build' \
  > ./build.out 2>&1 < /dev/null & echo $! > ./build.pid; disown

# wrapper réutilisable
run_detached() {
  local name="${1:-job}"; shift
  local logdir="./logs" rundir="./run"
  mkdir -p "$logdir" "$rundir"
  local ts pid out="$logdir/$name-$(date -u +%Y%m%dT%H%M%SZ).log"
  nohup setsid bash -lc "$*" > "$out" 2>&1 < /dev/null &
  pid=$!; echo "$pid" > "$rundir/$name.pid"; disown
  echo "started $name pid=$pid log=$out"
}
# usage:
run_detached "build-data.pm" "npm ci && npm run build"

# empêcher la relance multiple (lock fichier)
lock="/tmp/build.lock"
exec 9>"$lock" && flock -n 9 || { echo "already running"; exit 0; }
nohup setsid bash -lc 'npm run build' > ./build.out 2>&1 < /dev/null & echo $! > ./build.pid; disown

# réattaquer proprement la sortie d'un process déjà détaché (sans tmux)
less +F ./build.out

# exécuter via un proxy SOCKS si nécessaire (voir ALL_PROXY)
ALL_PROXY="socks5h://127.0.0.1:1080" \
nohup setsid bash -lc 'curl -fsS https://api.data.pm/export -o export.json' \
  > ./export.out 2>&1 < /dev/null & echo $! > ./export.pid; disown

notes

  • nohup ignore SIGHUP (déconnexion), setsid détache du TTY (nouvelle session), disown retire le job du shell courant.
  • redirigez toujours stdin depuis /dev/null et stdout/stderr vers des fichiers pour éviter les blocages liés au TTY.
  • conservez le PID ($!) pour superviser et terminer le job proprement plus tard.
  • pour des services durables et limités en ressources, préférez systemd (voir snippet systemd-run). Pour un besoin ponctuel, ce trio est suffisant.
  • évitez d’utiliser ceci dans un service déjà géré par systemd (double-démonisation inutile).