2009-03-23 11:59:25 +0000 2009-03-23 11:59:25 +0000
311
311

Jak całkowicie odłączyć proces od Terminala?

Używam Tilda (terminal rozwijalny) na Ubuntu jako “centrum dowodzenia” - tak jak inni mogą używać GNOME Do, Quicksilver lub Launchy.

Jednak mam problem z tym, jak całkowicie odłączyć proces (np. Firefox) od terminala, z którego został uruchomiony - tzn. zapobiec temu, aby taki (nie)dziecięcy proces

  • został zakończony podczas zamykania terminala inicjującego
  • “zanieczyszcza” terminal inicjujący przez STDOUT/STDERR

Na przykład, aby uruchomić Vima w “właściwym” oknie terminala, wypróbowałem prosty skrypt jak:

exec gnome-terminal -e "vim $@" &> /dev/null &

Jednak to nadal powoduje zanieczyszczenie (również podanie nazwy pliku nie wydaje się działać).

Odpowiedzi (18)

355
355
355
2009-03-23 13:18:35 +0000

Po pierwsze, po rozpoczęciu procesu, możesz go zatuszować, najpierw zatrzymując go (naciśnij Ctrl-Z), a następnie wpisując bg, aby pozwolić mu wznowić w tle. Teraz jest to “zadanie”, a jego stdout/stderr/stdin są nadal podłączone do Twojego terminalu.

Możesz natychmiast rozpocząć proces w tle, dodając na końcu “&”:

firefox &

Aby uruchomić go w tle wyciszonym, użyj tego:

firefox </dev/null &>/dev/null &
  • *

Kilka dodatkowych informacji:

nohup to program, którego możesz użyć do uruchomienia aplikacji z tak, aby jego stdout/stderr mógł być wysłany do pliku, a zamknięcie skryptu nadrzędnego nie wzruszyło dziecka. Musisz jednak mieć dalekowzroczność, aby z niego skorzystać, zanim uruchomisz aplikację. Ze względu na sposób działania nohup, nie można po prostu zastosować go do uruchomionego procesu.

disown jest wbudowanym bashem, który usuwa zadanie powłoki z listy zadań powłoki. W zasadzie oznacza to, że nie możesz już używać fg, bg na niej, ale co ważniejsze, gdy zamkniesz swoją powłokę, nie będzie ona już wisieć ani wysyłać SIGHUP do tego dziecka. W przeciwieństwie do nohup, disown jest używany poniżej proces został uruchomiony i osadzony w tle.

To czego _nie możesz zrobić, to zmienić stdout/stderr/stdin procesu po jego uruchomieniu. Przynajmniej nie z powłoki. Jeśli uruchomisz swój proces i powiesz mu, że jego stdout jest twoim terminalem (co domyślnie robisz), to proces ten jest skonfigurowany tak, by wyświetlać go na twoim terminalu. Twoja powłoka nie ma nic wspólnego z konfiguracją FD procesów, jest to wyłącznie coś, czym sam proces zarządza. Sam proces może zdecydować, czy zamknąć swój stdout/stderr/stdin czy nie, ale nie możesz użyć powłoki, aby go do tego zmusić.

Aby zarządzać wyjściem procesu w tle, masz wiele opcji ze skryptów, “nohup” jest prawdopodobnie pierwszym, który przychodzi na myśl. Ale dla interaktywnych procesów zaczynasz, ale zapomniałeś uciszyć (firefox < /dev/null &>/dev/null &), nie możesz zrobić wiele, naprawdę.

Polecam ci GNU screen. Z ekranem możesz po prostu zamknąć swoją działającą powłokę, gdy wyjście procesu stanie się kłopotem i otworzyć nową (^Ac).

  • *

Oh, a przy okazji, nie używaj “$@” tam, gdzie go używasz.

$@ oznacza, $1, $2, $3 …, co zamieniłoby twoją komendę w:

gnome-terminal -e "vim $1" "$2" "$3" ...

To chyba nie to, czego chcesz, bo -e tylko bierze jeden argument. Użyj $1, aby pokazać, że Twój skrypt może obsługiwać tylko jeden argument.

Naprawdę trudno jest uzyskać poprawne działanie wielu argumentów w podanym przez Ciebie scenariuszu (z gnome-terminal -e), ponieważ -e bierze tylko jeden argument, który jest łańcuchem poleceń powłoki. Musiałbyś zakodować swoje argumenty w jeden. Najlepszy i najbardziej solidny, ale raczej nieporęczny, sposób jest taki:

gnome-terminal -e "vim $(printf "%q " "$@")"
202
202
202
2009-03-23 12:17:32 +0000
nohup cmd &

nohup całkowicie odłącza proces (demonizuje go)

62
62
62
2009-03-23 12:05:02 +0000

Jeśli używasz bash, spróbuj disown [jobspec]; zobacz bash(1) .

Innym podejściem, które możesz wypróbować jest at now. Jeśli nie jesteś superużytkownikiem, twoje pozwolenie na używanie at może być ograniczone.

41
41
41
2014-01-22 17:08:16 +0000

Czytając te odpowiedzi, odniosłem wstępne wrażenie, że wydanie nohup <command> & będzie wystarczające. Biegnąc zsh w gnome-terminalu, stwierdziłem, że nohup <command> & nie powstrzymuje mojej powłoki przed zabiciem procesów dziecięcych na wyjściu. Chociaż nohup jest użyteczny, zwłaszcza w przypadku nieinteraktywnych powłok, to jednak gwarantuje takie zachowanie tylko wtedy, gdy proces dziecięcy nie zresetuje swojego handlera dla sygnału SIGHUP.

W moim przypadku, nohup powinien był zapobiec dotarciu sygnałów hangup do aplikacji, ale aplikacja dziecięca (w tym przypadku VMWare Player) resetowała swój handler SIGHUP. W rezultacie, gdy emulator terminala zakończy pracę, może on nadal zabijać Twoje podprocesy. Można to rozwiązać, według mojej wiedzy, tylko poprzez zapewnienie, że proces ten zostanie usunięty z tabeli zadań powłoki. Jeżeli nohup zostanie zastąpiony przez wbudowaną powłokę, jak to czasami bywa, może to być wystarczające, jednak w przypadku, gdy nie jest…

  • *

disown jest wbudowaną powłoką w bash, zsh, oraz ksh93,

<command> &
disown

lub

<command> &; disown

jeśli wolisz single-liners. Ma to ogólnie pożądany efekt w postaci usunięcia podprocesu z tabeli zadań. Pozwala to na wyjście z emulatora terminala bez przypadkowej sygnalizacji procesu dziecięcego. Bez względu na to, jak wygląda obsługa SIGHUP, nie powinno to zabić Twojego procesu potomnego.

Po dezaktywacji, proces nadal jest dzieckiem Twojego emulatora terminala (zagraj z pstree, jeśli chcesz oglądać to w akcji), ale po wyjściu z emulatora terminala, powinieneś zobaczyć go dołączonego do procesu init. Innymi słowy, wszystko jest tak, jak powinno być, i jak przypuszczalnie chcesz, aby było.

Co zrobić, jeśli Twoja powłoka nie obsługuje disown? Zdecydowanie opowiadałbym się za przełączeniem się na taką, która obsługuje, ale w przypadku braku tej opcji, masz kilka możliwości.

  1. screen i tmux mogą rozwiązać ten problem, ale są to rozwiązania znacznie cięższe, a ja nie lubię ich uruchamiać do tak prostego zadania. Są one o wiele bardziej odpowiednie do sytuacji, w których chcesz utrzymać tty, zazwyczaj na zdalnej maszynie.
  2. Dla wielu użytkowników może być pożądane sprawdzenie, czy Twoja powłoka obsługuje takie możliwości jak zsh’s setopt nohup. Można jej użyć do określenia, że SIGHUP nie powinien być wysyłany do zadań z tabeli zadań po zakończeniu pracy powłoki. Można albo zastosować to tuż przed zakończeniem pracy powłoki, albo dodać to do konfiguracji powłoki, takiej jak ~/.zshrc, jeżeli zawsze chcemy ją włączyć.
  3. Znajdź sposób na edycję tabeli zadań. Nie mogłem znaleźć sposobu, aby to zrobić w tcsh lub csh, co jest nieco niepokojące.
  4. Napisz mały program C do rozwidlenia i exec(). Jest to bardzo słabe rozwiązanie, ale źródło powinno składać się tylko z kilkudziesięciu linii. Możesz wtedy przekazać komendy jako argumenty wiersza poleceń do programu C, a tym samym uniknąć wpisywania konkretnych procesów w tabeli zadań.
30
30
30
2015-08-25 14:39:31 +0000
  1. nohup $COMMAND &
  2. $COMMAND & disown
  3. setsid command

Używam numeru 2 od bardzo dawna, ale numer 3 działa równie dobrze. Ponadto, disown ma flagę nohup, może dezaktywować wszystkie procesy z -h, oraz może dezaktywować wszystkie działające procesy z -a.

Wyciszanie jest realizowane przez -ar.

Mam nadzieję, że to pomoże!

9
9
9
2017-05-05 11:55:05 +0000

Najprostsza i tylko poprawna odpowiedź dla basha:

command & disown

Nie musisz odłączać procesu od terminala, ale od powłoki.

9
9
9
2009-03-23 14:55:15 +0000

w tcsh (a być może także w innych powłokach), możesz użyć nawiasów do odłączenia procesu.

Porównaj to:

> jobs # shows nothing
> firefox &
> jobs
[1] + Running firefox

Do tego:

> jobs # shows nothing
> (firefox &)
> jobs # still shows nothing
>

To usuwa firefoxa z listy zadań, ale wciąż jest powiązany z terminalem; jeśli zalogowałeś się do tego węzła przez ‘ssh’, próba wylogowania nadal zawiesi proces ssh.

7
7
7
2012-08-07 05:18:25 +0000

Aby zdezasocjować tty shell uruchamia komendę przez podpowłokę np.

(komenda)

Po zamknięciu używanego terminala, ale proces wciąż żyje.

check -

(sleep 100) & exit

Open other terminal

ps aux | grep sleep

Proces wciąż żyje.

5
5
5
2013-05-22 23:00:56 +0000

Backgrounding i foregrounding pracy jest prawdopodobnie jedną z pierwszych rzeczy, które każdy Unix sys-admin powinien wiedzieć.

Oto jak to się robi z bash:

./script.sh
# suspend process
{ctrl-Z}
# background process
bg
# list all backgrounded jobs
jobs
# bring it back to foreground
fg
4
4
4
2009-03-23 12:03:50 +0000

Możesz uruchomić swoją komendę za pomocą komendy nohup, to oderwie twój proces i przekieruje wyjścia do danego pliku… ale nie jestem pewien czy to jest dokładnie to czego potrzebujesz…

2
2
2
2018-02-05 16:14:17 +0000

Po prostu dodaj to do swojego bashrc/zshrc:

detach() {
  "$@" 1>/dev/null 2>/dev/null &; disown
}

Wtedy będziesz mógł uruchomić komendy disowned takie jak:

detach gedit ~/.zshrc
2
2
2
2009-03-23 12:10:49 +0000

Spróbuj demon – powinien być dostępny u Twojego przyjaznego menedżera pakietów i kompleksowo zadbać o każdy sposób oddzielenia się od terminalu.

1
1
1
2015-06-14 17:53:47 +0000

W mojej .bashrc, mam te funkcje właśnie w tym celu:

function run_disowned() {
    "$@" & disown
}

function dos() {
    # run_disowned and silenced

    run_disowned "$@" 1>/dev/null 2>/dev/null
}

Przedrostek komendy z dos aby uruchomić ją odłączoną od terminala.

Funkcja jest napisana do pracy z bash i zsh.

0
0
0
2010-06-19 16:46:44 +0000

Znalazłem na Mac OS X, że muszę używać zarówno nohup i disown w celu zapewnienia, że proces dziecka nie jest zburzony z terminalu.

0
0
0
2014-09-21 04:42:43 +0000

Używam do tego następującego skryptu. Zatrzymuje on drukowanie procesu na terminalu, rozłącza się z nohup i kończy ze statusem zwrotu, jeśli polecenie zakończy się w obrębie TIMEOUT.

#!/bin/bash

TIMEOUT=0.1

CMD=( "$@" )
#Could have some shortcuts here, e.g. replace "somefile.c" with "gedit somefile.c"

#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
#print the command for debugging and to see bash variable expansion
printf "%q " "${CMD[@]}"
echo
nohup "${CMD[@]}" >/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: $CMD"
#return the exit status of nohup, whatever it was
exit $NOHUP_STATUS

Przykład użycia:

>>> run false
false
Error: false
>>> echo $?
1
>>> run true
true
>>> run sleep 10
sleep 10
>>>
0
0
0
2019-06-21 07:14:46 +0000

sudo apt install ucommon-utils

pdetach command

Tam jesteś :)

-1
-1
-1
2017-02-15 04:16:48 +0000

Wiele odpowiedzi sugerowało użycie nohup. Wolałbym zasugerować użycie pm2 . Korzystanie z pm2 ponad nohup ma wiele zalet, takich jak utrzymanie aplikacji przy życiu, utrzymanie plików dziennika aplikacji i wiele innych funkcji. Po więcej szczegółów sprawdź to .

Aby zainstalować pm2 musisz pobrać npm. Dla systemu opartego na Debianie

sudo apt-get install npm

oraz dla Redhat

sudo yum install npm

Albo możesz zastosować się do tej instrukcji . After installation npm use it to install pm2

npm install pm2@latest -g

Once its done you can start your application by

$ pm2 start app.js # Start, Daemonize and auto-restart application (Node)
$ pm2 start app.py # Start, Daemonize and auto-restart application (Python)

For process monitoring use following commands:

$ pm2 list # List all processes started with PM2
$ pm2 monit # Display memory and cpu usage of each app
$ pm2 show [app-name] # Show all informations about application

Manage processes using either app name or process id or manage all processes together:

$ pm2 stop <app_name|id|'all'|json_conf>
$ pm2 restart <app_name|id|'all'|json_conf>
$ pm2 delete <app_name|id|'all'|json_conf>

Log files can be found in

$HOME/.pm2/logs #contain all applications logs
-1
-1
-1
2017-04-05 13:47:37 +0000

Jeśli twoim celem jest po prostu uruchomienie aplikacji z linii poleceń bez trzymania okna terminala w pobliżu, to możesz spróbować uruchomić aplikację po uruchomieniu terminala z alt-F2.