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
nohupignore SIGHUP (déconnexion),setsiddétache du TTY (nouvelle session),disownretire le job du shell courant.- redirigez toujours
stdindepuis/dev/nulletstdout/stderrvers 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).