it-swarm-eu.dev

Jak mohu spustit příkaz, který přežije terminál blízko?

Někdy chci zahájit proces a zapomenout na to. Pokud to spustím z příkazového řádku, takto:

redshift

Nemohu zavřít terminál, jinak to zabije proces. Mohu spustit příkaz takovým způsobem, že mohu terminál zavřít, aniž by to zabilo tento proces?

339
Matthew

Jedna z následujících 2 by měla fungovat:

$ Nohup redshift &

nebo

$ redshift &
$ disown

Níže naleznete několik dalších informací o tom, jak to funguje:

342
Steven D

Pokud je váš program již běží, můžete jej pozastavit pomocí Ctrl-Z, přetáhněte ji na pozadí pomocí bg a poté disown it, takto:

$ sleep 1000
^Z
[1]+  Stopped                 sleep 1000
$ bg
$ disown
$ exit
147
Stefan

Dobrá odpověď je již zaslána @StevenD, přesto si myslím, že by to mohlo vyjasnit trochu víc.

Důvodem, proč je proces ukončen při ukončení terminálu, je to, že proces, který zahájíte, je podřízený proces terminálu. Jakmile zavřete terminál, zabijete také tyto podřízené procesy. Strom procesů můžete vidět s pstree, například při spuštění kate & v Konsole:

init-+
     ├─konsole─┬─bash─┬─kate───2*[{kate}]
     │         │      └─pstree
     │         └─2*[{konsole}]

Chcete-li, aby byl proces kate odpojen od konsole, když ukončíte konsole, použijte s příkazem Nohup takto:

Nohup kate &

Po uzavření konsole bude pstree vypadat takto:

init-+
     |-kate---2*[{kate}]

a kate přežije. :)

Alternativou je použití screen/tmux/byobu, které udržuje prostředí v chodu nezávislé na terminálu.

50
gertvdijk

Tento proces můžete spustit v terminálu

setsid process

Tím se program spustí v nové relaci. Jak je vysvětleno http://hanoo.org/index.php?article=run-program-in-new-session-linux

31
hanoo

Přestože všechny návrhy fungují dobře, našel jsem jinou alternativu k použití screen, programu, který na vaší obrazovce nastavuje virtuální terminál.

Můžete zvážit zahájení s screen -S session_name. Obrazovku lze nainstalovat prakticky na všechny deriváty Linux a Unix. Bít Ctrl+A a (malá písmena) C zahájí druhou relaci. To vám umožní přepínat sem a tam mezi počáteční relací zasažením Ctrl+A a  nebo novější relace zasažením Ctrl+A a 1. Na jednom terminálu můžete mít až deset relací. Začínal jsem v práci, chodil jsem domů, ssh do mého pracovního stroje a pak vyvolal screen -d -R session_name. Tím se znovu připojíte k této vzdálené relaci.

10
apolinsky

Preferuji:

(název aplikace a)

například: [email protected]:~$ (chromium-browser &)

Při zadávání příkazu používejte závorky!

8
daGo

Mám skript pro:

  • Spusťte libovolné příkazy na pozadí

  • Přestaňte je zabíjet oknem terminálu

  • Potlačte jejich výstup

  • Zpracovává stav ukončení

Používám jej hlavně pro gedit, evince, inkscape atd., Které mají spoustu nepříjemných výstupů terminálu. Pokud příkaz skončí před TIMEOUT, bude místo nula vrácen stav ukončení Nohup.

#!/bin/bash

TIMEOUT=0.1

#use Nohup to run the command, suppressing its output and allowing the terminal to be closed
#also send Nohup's output to /dev/null, supressing Nohup.out
#run Nohup in the background so this script doesn't block
Nohup "${@}" >/dev/null 2>&1 &
Nohup_PID=$!

#kill this script after a short time, exiting with success status - command is still running
#this is needed as there is no timeout argument for `wait` below
MY_PID=$$
trap "exit 0" SIGINT SIGTERM
sleep $TIMEOUT && kill $MY_PID 2>/dev/null & #ignore "No such process" error if this exits normally

#if the command finishes before the above timeout, everything may be just fine or there could have been an error
wait $Nohup_PID
Nohup_STATUS=$?
#print an error if there was any. most commonly, there was a typo in the command
[ $Nohup_STATUS != 0 ] && echo "Error ${@}"
#return the exit status of Nohup, whatever it was
exit $Nohup_STATUS

příklady ...

>>> run true && echo success || echo fail
success
>>> run false && echo success || echo fail
Error false
fail
>>> run sleep 1000 && echo success || echo fail
success
>>> run notfound && echo success || echo fail
Error notfound
fail
7
jozxyqk

Shell-jediný způsob, jak to udělat, je zavřít stdin a pozadí příkazu:

command <&- & 

Poté, co ukončíte Shell, to nebude ukončeno. Přesměrování stdout je pěkná volitelná věc.

Nevýhodou je, že to po tom nemůžete udělat.

7
w00t

Můžete nastavit proces (PID) tak, aby po odhlášení a ukončení relace terminálu nepřijal signál HUP. Použijte následující příkaz:

Nohup -p PID
4
tony

Pravděpodobně podobné odpověď, kterou nabízí apolinsky , používám variantu na screen. Příkaz Vanilla je takový

screen bash -c 'long_running_command_here; echo; read -p "ALL DONE:"'

Relace může být odpojena Ctrl ACtrl D a v jednoduchém případě znovu připojeno pomocí screen -r. Mám to zabalené ve skriptu s názvem session, který žije v mém PATH a je připraven pro pohodlný přístup:

#!/bin/bash
#
if screen -ls | awk '$1 ~ /^[1-9][0-9]*\.'"$1"'/' >/dev/null
then
    echo "WARNING: session is already running (reattach with 'screen -r $1')" >&2
else
    exec screen -S "$1" bash -c "[email protected]; echo; echo '--------------------'; read -p 'ALL DONE (Enter to exit):'"
    echo "ERROR: 'screen' is not installed on this system" >&2
fi
exit 1

Funguje to pouze tehdy, pokud předem víte, že chcete program odpojit. Nezajišťuje odpojení již spuštěného programu.

3
roaima

Podobně jako v případě jiných odpovědí, které jsme zveřejnili dříve, lze pomocí reptyr přenést běžící proces tak, aby se zpětně používalo „screen“ a terminál se uzavřel. Kroky jsou popsány v tomto post . Kroky, které je třeba podniknout, jsou:

  1. Pozastavte proces
  2. Pokračujte v procesu na pozadí
  3. Zrušit proces
  4. Spusťte relaci obrazovky
  5. Najděte PID procesu
  6. K převzetí procesu použijte reptyr
2
user308879