Bagaimana cara melepaskan proses dari Terminal, seluruhnya?

304

Saya menggunakan Tilda (terminal drop-down) di Ubuntu sebagai "pusat komando" saya - cukup banyak cara orang lain menggunakan GNOME Do, Quicksilver atau Launchy.

Namun, saya berjuang dengan cara sepenuhnya melepaskan proses (misalnya Firefox) dari terminal dari mana ia diluncurkan - yaitu mencegah proses anak (non-) seperti itu

  • diakhiri saat menutup terminal asal
  • "mencemari" terminal asal melalui STDOUT / STDERR

Misalnya, untuk memulai Vim di jendela terminal yang "tepat", saya telah mencoba skrip sederhana seperti berikut:

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

Namun, itu masih menyebabkan polusi (juga, memberikan nama file sepertinya tidak berhasil).

slhck
sumber
1
Itu juga pertanyaan yang bagus. Saya pikir itu adil untuk mempertimbangkan Bash sebagai bahasa pemrograman - meskipun memang ruang lingkup pertanyaan ini mungkin lebih pada sisi sysadmin ...
Ini adalah duplikat dari pertanyaan ini stackoverflow.com/questions/285015/…
Dana the Sane
Kasing penggunaan Anda tidak menjelaskan detasemen lengkap.
jiggunjer

Jawaban:

344

Pertama-tama; setelah Anda memulai suatu proses, Anda dapat melatar belakanginya dengan terlebih dahulu menghentikannya (tekan Ctrl- Z) dan kemudian mengetik bguntuk membiarkannya melanjutkan di latar belakang. Sekarang "pekerjaan", dan stdout/ stderr/ stdinmasih terhubung ke terminal Anda.

Anda dapat memulai proses sebagai latar belakang segera dengan menambahkan "&" di akhir:

firefox &

Untuk menjalankannya di latar yang dibungkam, gunakan ini:

firefox </dev/null &>/dev/null &

Beberapa info tambahan:

nohupadalah sebuah program yang dapat Anda gunakan untuk menjalankan aplikasi Anda sehingga stdout / stderr dapat dikirim ke file sebagai gantinya dan dengan demikian menutup skrip induk tidak akan SIGHUP anak. Namun, Anda harus memiliki pandangan ke depan untuk menggunakannya sebelum Anda memulai aplikasi. Karena cara nohupkerjanya, Anda tidak bisa hanya menerapkannya pada proses yang sedang berjalan .

disownadalah bash builtin yang menghilangkan pekerjaan shell dari daftar pekerjaan shell. Apa artinya ini pada dasarnya adalah bahwa Anda tidak dapat menggunakan fg, bgdi atasnya lagi, tetapi yang lebih penting, ketika Anda menutup shell Anda tidak akan menggantung atau mengirim SIGHUPke anak itu lagi. Berbeda nohup, disowndigunakan setelah proses telah diluncurkan dan dilatar belakangi.

Yang tidak bisa Anda lakukan, adalah mengubah stdout / stderr / stdin dari suatu proses setelah diluncurkan. Paling tidak dari shell. Jika Anda meluncurkan proses Anda dan memberi tahu bahwa stdout adalah terminal Anda (yang merupakan apa yang Anda lakukan secara default), maka proses itu dikonfigurasi untuk menghasilkan output ke terminal Anda. Shell Anda tidak memiliki urusan dengan penyiapan FD proses, itu murni sesuatu yang dikelola sendiri oleh proses itu. Proses itu sendiri dapat memutuskan apakah akan menutup stdout / stderr / stdin atau tidak, tetapi Anda tidak dapat menggunakan shell Anda untuk memaksanya melakukannya.

Untuk mengelola hasil proses latar belakang, Anda memiliki banyak opsi dari skrip, "nohup" mungkin menjadi yang pertama muncul di benak Anda. Tetapi untuk proses interaktif Anda mulai tetapi lupa untuk membungkam ( firefox < /dev/null &>/dev/null &) Anda tidak bisa berbuat banyak, sungguh.

Saya sarankan Anda mendapatkan GNU screen. Dengan layar Anda dapat menutup shell yang sedang berjalan saat output proses menjadi masalah dan membuka yang baru ( ^Ac).


Oh, dan omong-omong, jangan gunakan " $@" di mana Anda menggunakannya.

$@berarti, $1, $2, $3..., yang akan mengubah perintah Anda ke:

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

Itu mungkin bukan yang Anda inginkan karena -e hanya membutuhkan satu argumen. Gunakan $1untuk menunjukkan bahwa skrip Anda hanya dapat menangani satu argumen.

Sangat sulit untuk mendapatkan beberapa argumen yang berfungsi dengan baik dalam skenario yang Anda berikan (dengan gnome-terminal -e) karena -ehanya membutuhkan satu argumen, yang merupakan string perintah shell. Anda harus menyandikan argumen Anda menjadi satu. Cara terbaik dan paling kuat, tetapi agak kasar, adalah seperti ini:

gnome-terminal -e "vim $(printf "%q " "$@")"
lununath
sumber
Terima kasih banyak untuk ini! Sayangnya saya hanya bisa menerima satu jawaban. Saya berakhir dengan "nohup $ @ &> / dev / null &" dan "alias wvim = 'launch.sh gnome-terminal -x vim'"
20
Jawaban yang luar biasa detail dan informatif. +1
Teekin
1
@ Hai-Malaikat ketika Anda menutup bash shell interaktif, bash HUP semua pekerjaan aktif. Ketika Anda ^ Z dan bg suatu proses itu masih merupakan pekerjaan, baik itu sebagai latar belakang. Untuk menghapusnya sebagai pekerjaan, gunakan disown, maka proses akan tetap hidup setelah Anda menutup shell karena bash tidak akan HUP lagi.
lhunath
3
Tidak akan menggunakan $*bukannya $@memperbaiki masalah string terpisah sudah?
sjas
2
Yang tidak bisa Anda lakukan, adalah mengubah stdout / stderr / stdin dari suatu proses setelah diluncurkan. - tidak sepenuhnya benar. Gunakan reptyruntuk ini.
Stefan Seidel
198
nohup cmd &

nohup melepaskan proses sepenuhnya (memonemonikannya)

dsm
sumber
5
Meskipun ringkas itu berharga, kelengkapan lebih berharga. Meskipun nohup adalah GNU coreutil, jawaban bash-only (atau catatan tentang tidak adanya GNU) akan sesuai di sini. Meski begitu, jawaban yang bagus.
Penebusan Terbatas
23
nohupmengabaikan SIGHUPsinyal. Menjalankan proses secara normal. Tanpa daemonisasi.
nemo
1
@nemo Yang berarti proses ini tidak terlepas, tetapi akan terlepas (dan anak dari init) jika shell keluar ... kan?
Noldorin
@Noldorin Ya. Mengabaikan SIGHUP, yang dikirim ketika shell berakhir, akan membiarkan proses anak berjalan dan dipindahkan ke init.
nemo
@nemo nohup juga membisukan standar masuk / keluar. Tindak lanjuti dengan disown untuk melepaskan sepenuhnya.
jiggunjer
60

Jika Anda menggunakan bash, coba ; lihat bash (1) .disown [jobspec]

Pendekatan lain yang bisa Anda coba adalah at now. Jika Anda bukan pengguna super, izin Anda untuk menggunakan atmungkin dibatasi.

Randy Proctor
sumber
"disown" sepertinya bukan perintah bash internal (tidak tersedia di komputer saya, dan saya menggunakan bash). "nohup", seperti yang disarankan Ben, mungkin cara yang lebih baik (dan standar) untuk melakukan ini.
1
tidak pernah berpikir untuk menggunakan "at", terima kasih atas idenya!
cadrian
1
atuntuk mendelegasikan eksekusi kepada orang lain, saya menyukainya! +1
Ninsuo
1
Sebagai acuan, ini juga berfungsi zsh.
Coderer
1
Selain itu, disowntampaknya tidak memiliki efek yang diinginkan dengan gnome-terminal- disownproses ed masih terbunuh ketika terminal keluar. Saya ingin tahu mengapa / bagaimana.
Kyle Strand
38

Membaca jawaban ini, saya mendapat kesan awal bahwa penerbitan nohup <command> &akan cukup. Menjalankan zsh di terminal gnome, saya menemukan itu nohup <command> &tidak mencegah shell saya membunuh proses anak saat keluar. Meskipun nohupberguna, terutama dengan cangkang non-interaktif, itu hanya menjamin perilaku ini jika proses anak tidak mereset handler untuk SIGHUPsinyal.

Dalam kasus saya, nohupseharusnya mencegah sinyal hangup dari mencapai aplikasi, tetapi aplikasi anak (VMWare Player dalam kasus ini) sedang mereset SIGHUPhandlernya. Akibatnya ketika terminal emulator keluar, itu masih bisa membunuh subproses Anda. Setahu saya, ini hanya dapat diselesaikan dengan memastikan bahwa proses tersebut dihapus dari tabel pekerjaan shell. Jika nohupditimpa dengan shell builtin, seperti yang kadang-kadang terjadi, ini mungkin cukup, namun, dalam hal itu tidak ...


disownadalah shell builtin di bash, zsh, dan ksh93,

<command> &
disown

atau

<command> &; disown

jika Anda lebih suka one-liners. Ini memiliki efek yang umumnya diinginkan untuk menghapus subproses dari tabel pekerjaan. Ini memungkinkan Anda untuk keluar dari emulator terminal tanpa menandakan proses anak sama sekali. Tidak peduli seperti apa SIGHUPpawang itu, ini seharusnya tidak membunuh proses anak Anda.

Setelah disown, proses masih merupakan anak dari emulator terminal Anda (bermain dengan pstreejika Anda ingin menonton ini beraksi), tetapi setelah emulator terminal keluar, Anda harus melihatnya melekat pada proses init. Dengan kata lain, semuanya sudah sebagaimana mestinya, dan seperti yang mungkin Anda inginkan.

Apa yang harus dilakukan jika shell Anda tidak mendukung disown? Saya sangat menganjurkan beralih ke yang melakukannya, tetapi tanpa adanya opsi itu, Anda punya beberapa pilihan.

  1. screendan tmuxdapat memecahkan masalah ini, tetapi mereka adalah solusi yang jauh lebih berat, dan saya tidak suka menjalankannya untuk tugas yang begitu sederhana. Mereka jauh lebih cocok untuk situasi di mana Anda ingin mempertahankan tty, biasanya pada mesin jarak jauh.
  2. Bagi banyak pengguna, mungkin diinginkan untuk melihat apakah shell Anda mendukung kemampuan seperti milik zsh setopt nohup. Ini dapat digunakan untuk menentukan bahwa SIGHUPtidak boleh dikirim ke pekerjaan di tabel pekerjaan ketika shell keluar. Anda dapat menerapkan ini tepat sebelum keluar dari shell, atau menambahkannya ke konfigurasi shell seperti ~/.zshrcjika Anda selalu menginginkannya.
  3. Temukan cara untuk mengedit tabel pekerjaan. Saya tidak dapat menemukan cara untuk melakukan ini di tcshatau csh, yang agak mengganggu.
  4. Tulis program C kecil untuk memotong dan exec(). Ini adalah solusi yang sangat buruk, tetapi sumbernya hanya terdiri dari beberapa lusin baris. Anda kemudian dapat meneruskan perintah sebagai argumen baris perintah ke program C, dan karenanya menghindari entri khusus proses dalam tabel pekerjaan.
Stephen Rosen
sumber
29
  1. nohup $COMMAND &
  2. $COMMAND & disown
  3. setsid command

Saya telah menggunakan nomor 2 untuk waktu yang sangat lama, tetapi nomor 3 juga berfungsi. Juga, disownmemiliki nohupbendera -h, dapat menolak semua proses dengan -a, dan dapat menolak semua proses yang berjalan dengan -ar.

Diam dilakukan oleh $COMMAND &>/dev/null.

Semoga ini membantu!

Tn. Minty Fresh
sumber
Pendek dan manis; terima kasih untuk ringkasan yang sangat membantu ini!
Sheljohn
Saya tidak percaya saya masih mendapatkan pemberitahuan untuk posting ini ...
Tn. Minty Fresh
9

Saya pikir layar dapat menyelesaikan masalah Anda


sumber
9

di tcsh (dan mungkin di shell lain juga), Anda dapat menggunakan tanda kurung untuk melepaskan proses.

Bandingkan ini:

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

Untuk ini:

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

Ini menghapus firefox dari daftar pekerjaan, tetapi masih terikat ke terminal; jika Anda masuk ke simpul ini melalui 'ssh', mencoba keluar masih akan menggantung proses ssh.

Nathan Fellman
sumber
9

Paling sederhana dan satu-satunya jawaban yang tepat untuk bash:

command & disown

Anda tidak perlu melepaskan proses dari terminal, tetapi dari shell.

ManuelSchneid3r
sumber
7

Untuk memisahkan perintah tty shell run melalui sub-shell untuk mis

(perintah)&

Ketika keluar terminal yang digunakan ditutup tetapi proses masih hidup.

periksa -

(sleep 100) & exit

Buka terminal lain

ps aux | grep sleep

Proses masih hidup.

jitendra
sumber
Inilah yang saya butuhkan. Saya mencoba menambahkan pintasan konsol untuk teks sublime dan berfungsi dengan baik, inilah yang saya akhiri dengan: ("/ opt / Sublime Text 2 / sublime_text" $ @) &
Ron E
5

Latar belakang dan latar depan pekerjaan mungkin adalah salah satu hal pertama yang harus diketahui oleh setiap sys-admin Unix.

Inilah cara melakukannya dengan bash:

./script.sh
# suspend process
{ctrl-Z}
# background process
bg
# list all backgrounded jobs
jobs
# bring it back to foreground
fg
Djangofan
sumber
4

Anda dapat menjalankan perintah Anda menggunakan perintah nohup, ini melepaskan proses Anda dan mengarahkan output ke file yang diberikan ... tapi saya tidak yakin itu persis apa yang Anda butuhkan ..

Ben
sumber
Saya bisa bersumpah saya telah mencoba nohup sebelum menggunakan exec - tetapi ternyata tidak benar, karena ia bekerja seperti ini: nohup gnome-terminal -e "vim $ @" &> / dev / null &
2

Coba daemon - harus tersedia dari manajer paket Anda yang ramah dan secara komprehensif berhati-hati dalam setiap cara melepaskan diri dari terminal.

ShiDoiSi
sumber
2

Cukup tambahkan ini di bashrc / zshrc Anda:

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

Kemudian Anda dapat menjalankan perintah yang tidak diakui seperti ini:

detach gedit ~/.zshrc
B. Branchard
sumber
1

Di .bashrc saya, saya memiliki fungsi-fungsi ini untuk tujuan itu:

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

function dos() {
    # run_disowned and silenced

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

Awali perintah dengan dosmenjalankannya terlepas dari terminal.

Fungsi ini ditulis untuk bekerja dengan bashdan zsh.

mic_e
sumber
1
Saya sedikit bingung mengapa jawaban ini menggunakan satu fungsi dibungkus ke lain, ketika yang cukup untuk hanya menggunakan satu fungsi dengan tubuh seperti ini: ( "$@" & disown) &> /dev/null. Ini juga tidak masuk akal untuk digunakan 1>dan 2>, karena Anda menggunakan disown, yang berarti Anda menggunakan bash, dan dalam bash Anda dapat dengan mudah melakukannya &>untuk mengarahkan ulang stdout dan stderr
Sergiy Kolodyazhnyy
Saya memilikinya sebagai dua fungsi karena (1) Saya pikir lebih mudah untuk membaca dengan cara ini, dan (2) Saya membutuhkan run_disownedfungsionalitas di tempat lain di dotfiles saya. Anda benar tentang &>hal itu, tentu saja.
mic_e
0

Saya telah menemukan di Mac OS X bahwa saya perlu menggunakan nohup DAN disown untuk memastikan bahwa proses anak tidak dihancurkan dengan terminal.

Harun
sumber
0

Saya menggunakan skrip berikut untuk melakukan ini. Ini menghentikan proses pencetakan ke terminal, lepas dengan nohup, dan keluar dengan status pengembalian jika perintah selesai di dalam 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

Contoh penggunaan:

>>> run false
false
Error: false
>>> echo $?
1
>>> run true
true
>>> run sleep 10
sleep 10
>>>
jozxyqk
sumber
0

sudo apt install ucommon-utils

pdetach command

Ini dia :)

d4rk4ng31
sumber
-1

Banyak jawaban yang disarankan menggunakan nohup . Saya lebih suka menyarankan menggunakan PM2 . Menggunakan pm2 lebih dari nohup memiliki banyak keuntungan, seperti menjaga aplikasi tetap hidup, memelihara file log untuk aplikasi dan banyak lagi fitur lainnya. Untuk lebih detail lihat ini .

Untuk menginstal pm2 Anda harus mengunduh npm . Untuk sistem berbasis Debian

sudo apt-get install npm

dan untuk Redhat

sudo yum install npm

Atau Anda dapat mengikuti instruksi ini . Setelah menginstal npm, gunakan untuk menginstal pm2

npm install pm2@latest -g

Setelah selesai, Anda dapat memulai aplikasi dengan

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

Untuk pemantauan proses gunakan perintah berikut:

$ 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

Kelola proses menggunakan nama aplikasi atau id proses atau kelola semua proses bersama-sama:

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

File log dapat ditemukan di

$HOME/.pm2/logs #contain all applications logs
haccks
sumber
1
Menggunakan aplikasi NodeJS (versus perintah kecil dan kuat seperti nohup) untuk mengendalikan proses unix tampaknya ... benar-benar berlebihan, dan jujur, agak aneh. Saya akan menggunakan monit jika Anda memerlukan fungsi restart.
Sergio
@Sergio adalah pilihan Anda untuk menggunakan aplikasi yang sudah didepositkan.
pukul
Beberapa rilis telah dibuat tahun ini (satu 4 hari yang lalu), jadi saya tidak melihat bagaimana / mengapa Anda berpikir monit adalah aplikasi yang sudah usang. @see mmonit.com/monit/changes
Sergio
Saya sedang berbicara tentang nohup.
jam
1
nohupadalah perintah POSIX standar, jadi komentar yang sama: tidak mungkin ditinggalkan. @lihat unix.com/man-page/posix/1p/nohup
Sergio
-1

Jika tujuan Anda adalah hanya meluncurkan aplikasi baris perintah tanpa menjaga jendela terminal, maka Anda dapat mencoba menjalankan aplikasi setelah meluncurkan terminal dengan alt-F2.

MattKelly
sumber