Bagaimana saya bisa menjalankan perintah yang akan selamat dari penutupan terminal?

313

Terkadang saya ingin memulai suatu proses dan melupakannya. Jika saya memulainya dari baris perintah, seperti ini:

redshift

Saya tidak bisa menutup terminal, atau itu akan mematikan prosesnya. Bisakah saya menjalankan perintah sedemikian rupa sehingga saya bisa menutup terminal tanpa membunuh prosesnya?

Matius
sumber
4
Bukan penginstalan bawaan pada semua distro, tetapi layar adalah teman Anda: en.wikipedia.org/wiki/GNU_Screen
Zayne S Halsall
Untuk siapa pun yang menghadapi masalah yang sama: Ingat, bahwa bahkan jika Anda mengetik yourExecutable &dan output terus muncul di layar dan Ctrl+Ctampaknya tidak menghentikan apa pun, ketik saja secara membabi buta disown;dan tekan Enterbahkan jika layar bergulir dengan output dan Anda tidak dapat melihat apa Anda sedang mengetik. Proses ini akan ditolak dan Anda akan dapat menutup terminal tanpa proses sekarat.
Nav
Anda dapat menggunakan layar multiplexer seperti tmux . Ini tersedia melalui apt-get di mesin ubuntu
Himanshu

Jawaban:

311

Salah satu dari 2 berikut ini harus berfungsi:

$ nohup redshift &

atau

$ redshift &
$ disown

Lihat berikut ini untuk informasi lebih lanjut tentang cara kerjanya:

Steven D
sumber
5
Yang kedua ( redshift & disown) bekerja untuk saya di Ubuntu 10.10. Tampaknya bekerja dengan baik menempatkan semuanya pada satu baris. Apakah ada alasan saya tidak boleh melakukan ini?
Matius
4
@ Matius Yang pertama harus bekerja dengan baik juga, itu tidak latar belakang seperti yang kedua (Anda mungkin ingin nohup redshift &jadi latar belakang). Dan menempatkan yang kedua pada satu baris tidak masalah, meskipun biasanya Anda berpisah dengan ;( redshift &; disown)
Michael Mrozek
10
@ Michael: Keduanya ;dan &pemisah perintah dan memiliki prioritas yang sama. Satu-satunya perbedaan adalah eksekusi sinkron versus asinkron (masing-masing). Tidak perlu menggunakan &;preferensi untuk adil &(berfungsi, tetapi agak berlebihan).
Chris Johnsen
4
jawaban yang baik, orang mungkin menambahkan bahwa itu akan menjadi ide yang baik untuk mengarahkan stdout dan stderr sehingga terminal tidak akan di-spam dengan output debug
Kim
12
Juga, redshift &!akan menolak redshift segera.
143

Jika program Anda sudah berjalan, Anda dapat menjeda dengan Ctrl-Z, tarik ke latar belakang dengan bgdan kemudian disown, seperti ini:

$ sleep 1000
^Z
[1]+  Stopped                 sleep 1000
$ bg
$ disown
$ exit
Stefan
sumber
3
setelah ditolak bagaimana saya bisa lagi membaca stdout dari proses yang berjalan?
Necktwi
1
Ini tidak berhasil bagi saya untuk beberapa alasan (centos)
Ian
Bagaimana cara mematikan proses setelah prosedur ini?
Palak Darji
2
@necktwi disowntidak memutuskan stdout atau stderr. Namun nohupdemikian, seperti halnya >/dev/null(putuskan standar keluar), 2>/dev/null(putuskan kesalahan standar). Ini ( disown) memutuskan kontrol-pekerjaan.
ctrl-alt-delor
45

Jawaban yang bagus sudah diposting oleh @StevenD, namun saya pikir ini mungkin akan sedikit memperjelasnya.

Alasan bahwa proses tersebut terbunuh pada terminasi terminal adalah bahwa proses yang Anda mulai adalah proses anak terminal. Setelah Anda menutup terminal, ini akan membunuh proses anak ini juga. Anda dapat melihat pohon proses dengan pstree, misalnya saat menjalankan kate &di Konsole:

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

Untuk membuat kateproses terlepas dari konsolesaat Anda mengakhiri konsole, gunakan nohupdengan perintah, seperti ini:

nohup kate &

Setelah ditutup konsole, pstreeakan terlihat seperti ini:

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

dan kateakan bertahan. :)

Alternatif menggunakan screen/ tmux/ byobu, yang akan membuat shell tetap berjalan, terlepas dari terminal.

gertvdijk
sumber
Saya punya masalah dengan metode yang ditolak. Ini saat ini bekerja untuk saya, jadi upvoting. Saya juga suka ini karena saya bisa mengikuti-nohup.out untuk melihat apa yang terjadi, tetapi tidak khawatir tentang kegagalan sesi saya
Ian
27

Anda dapat menjalankan proses seperti ini di terminal

setsid process

Ini akan menjalankan program dalam sesi baru. Seperti dijelaskan http://hanoo.org/index.php?article=run-program-in-new-session-linux

hanoo
sumber
1
Apa yang Anda lihat sebagai keuntungan dari setsid dibandingkan nohup?
itsbruce
1
1) Itu tidak mencetak pesan yang mengganggu tentang nohup.out. 2) Itu tidak tetap dalam daftar pekerjaan shell Anda, sehingga tidak mengacaukan output jobs.
Mikel
Ini adalah satu-satunya solusi yang bekerja dengan skrip yang berjalan di lxterminal, meluncurkan pcmanfm dan keluar (dengan setid terminal dapat ditutup sementara pcmanfm terus berjalan). Terima kasih banyak!
desgua
9

Meskipun semua saran bekerja dengan baik, saya telah menemukan alternatif saya adalah menggunakan screen, sebuah program yang mengatur terminal virtual di layar Anda.

Anda dapat mempertimbangkan memulainya dengan . Layar dapat diinstal pada hampir semua turunan Linux dan Unix. Menekan + dan (huruf kecil) akan memulai sesi kedua. Ini akan memungkinkan Anda untuk beralih antara sesi awal dengan menekan + dan atau sesi yang lebih baru dengan menekan + dan . Anda dapat memiliki hingga sepuluh sesi dalam satu terminal. Saya biasa memulai sesi di tempat kerja, pulang, ssh ke mesin kerja saya, dan kemudian memohon . Ini akan menghubungkan Anda kembali ke sesi jarak jauh itu.screen -S session_nameCtrlACCtrlA0CtrlA1screen -d -R session_name

apolinsky
sumber
screen -d -m commandakan memulainya dalam layar yang sudah terlepas: ~# screen -d -m top ~# screen -ls There is a screen on: 10803..Server-station (Detached) 1 Socket in /root/.screen. ~# screen -x .... dan Anda masuk
Dr. Alexander
7

Cara khusus shell untuk melakukan semua ini adalah dengan menutup stdin dan latar belakang perintah:

command <&- & 

Maka itu tidak akan berhenti ketika Anda keluar dari shell. Mengarahkan stdout adalah hal opsional yang baik untuk dilakukan.

Kerugiannya adalah Anda tidak bisa melakukan ini setelah faktanya.

w00t
sumber
Saya mencoba di ubuntu. Terminal pembunuhan juga menutup proses yang diluncurkan. Adakah yang tahu mengapa ini bisa terjadi?
Ashok Koyi
7

Saya punya skrip untuk:

  • Jalankan perintah sewenang-wenang di latar belakang

  • Hentikan mereka agar tidak terbunuh dengan jendela terminal

  • Menekan output mereka

  • Menangani status keluar

Saya menggunakannya terutama untuk gedit, evince, inkscapedll yang semua memiliki banyak terminal output menjengkelkan. Jika perintah selesai sebelumnya TIMEOUT, status keluar nohup dikembalikan bukan nol.

#!/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

contoh ...

>>> 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
jozxyqk
sumber
7

Aku lebih memilih:

(nama aplikasi &)

sebagai contoh: linux@linux-desktop:~$ (chromium-browser &)

Pastikan untuk menggunakan tanda kurung saat mengetik perintah!

daGo
sumber
1
Menutup terminal akan membunuh proses , yang persisnya ingin dihindari OP (dan saya, yang datang ke sini)
gromit190
1
Mungkin Anda memiliki perintah cepat yang saya gunakan dalam jawaban saya tanpa tanda kurung, jika demikian menutup terminal akan mematikan prosesnya, jika tidak maka TIDAK akan terjadi. Saya sudah mengedit solusi di atas untuk memperjelasnya.
daGo
bekerja untuk saya, tnx
noadev
Saya bertanya-tanya mengapa ini tidak mendapatkan lebih banyak suara. nohupmencegah output tty dan saya sebenarnya hanya ingin mengarahkan output ke file dan mencegahnya jadi ini adalah solusi yang lebih baik untuk saya.
redanimalwar
4

Anda dapat mengatur proses (PID) untuk tidak menerima sinyal HUP saat keluar dan menutup sesi terminal. Gunakan perintah berikut:

nohup -p PID
tony
sumber
3

Bisa dibilang mirip dengan jawaban yang ditawarkan oleh apolinsky , saya menggunakan varian on screen. Perintah vanilla seperti ini

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

Sesi dapat diputus dengan Ctrl ACtrl Ddan dihubungkan kembali dalam kasus sederhana dengan screen -r. Saya memiliki ini dibungkus dengan skrip yang disebut sessiontinggal di PATHsiap untuk akses mudah saya:

#!/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 "$@; echo; echo '--------------------'; read -p 'ALL DONE (Enter to exit):'"
    echo "ERROR: 'screen' is not installed on this system" >&2
fi
exit 1

Ini hanya berfungsi ketika Anda tahu sebelumnya bahwa Anda ingin memutuskan suatu program. Itu tidak menyediakan untuk program yang sudah berjalan terputus.

roaima
sumber
2

Demikian pula dengan jawaban lain yang diposting sebelumnya, seseorang dapat mentransfer proses yang berjalan untuk menggunakan "layar" secara retrospektif berkat reptyr dan kemudian menutup terminal. Langkah-langkahnya dijelaskan dalam posting ini . Langkah-langkah yang harus diambil adalah:

  1. Tangguhkan prosesnya
  2. Lanjutkan proses di latar belakang
  3. Abaikan prosesnya
  4. Luncurkan sesi layar
  5. Temukan PID dari proses tersebut
  6. Gunakan reptyr untuk mengambil alih proses
pengguna308879
sumber