Jawaban:
Menggunakan Kontrol Pekerjaan bash untuk mengirim proses ke latar belakang:
bg
untuk menjalankannya di latar belakang.disown -h [job-spec]
di mana [job-spec] adalah nomor pekerjaan (seperti %1
untuk pekerjaan pertama yang berjalan; cari nomor Anda dengan jobs
perintah) sehingga pekerjaan tersebut tidak terbunuh saat terminal ditutup.disown -h
mungkin adalah jawaban yang lebih tepat: "membuat disown bersikap lebih seperti nohup (yaitu pekerjaan akan tetap berada di pohon proses shell Anda saat ini sampai Anda keluar dari shell Anda) Ini memungkinkan Anda untuk melihat semua pekerjaan yang dimulai shell ini. " (dari [ quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/… )
disown
, disown menjadikan sebuah proses daemon, yang berarti input / output standar dialihkan ke / dev / null. Jadi, jika Anda berencana untuk menolak suatu pekerjaan, lebih baik memulainya dengan masuk ke file, misalnyamy_job_command | tee my_job.log
disown
lepaskan semua pipa dari proses. Untuk memasang kembali pipa, gunakan gdb
seperti yang dijelaskan di utas ini . Lebih khusus lagi, posting ini .
Misalkan karena beberapa alasan Ctrl+ Zjuga tidak berfungsi, pergi ke terminal lain, cari id proses (menggunakan ps
) dan jalankan:
kill -SIGSTOP PID
kill -SIGCONT PID
SIGSTOP
akan menunda proses dan SIGCONT
akan melanjutkan proses, di latar belakang. Jadi sekarang, menutup kedua terminal Anda tidak akan menghentikan proses Anda.
disown %1
terminal pertama sebelum menutupnya.
kwin
setelah crash tanpa memikirkan konsekuensinya). Jadi, jika saya berhenti kwin, semuanya akan membeku dan saya tidak memiliki kemungkinan untuk lari bg
!
Perintah untuk memisahkan pekerjaan yang sedang berjalan dari shell (= membuatnya nohup) adalah disown
dan perintah dasar shell.
Dari bash-manpage (man bash):
menolak [-ar] [-h] [jobspec ...]
Tanpa opsi, setiap jobspec dihapus dari tabel pekerjaan aktif. Jika opsi -h diberikan, setiap jobspec tidak dihapus dari tabel, tetapi ditandai sehingga SIGHUP tidak dikirim ke pekerjaan jika shell menerima SIGHUP. Jika tidak ada jobspec, dan opsi -a atau -r tidak disediakan, pekerjaan saat ini digunakan. Jika tidak ada jobspec yang disediakan, opsi -a berarti menghapus atau menandai semua pekerjaan; opsi -r tanpa argumen jobspec membatasi operasi untuk menjalankan pekerjaan. Nilai pengembaliannya adalah 0 kecuali jika suatu jobspec tidak menentukan pekerjaan yang valid.
Itu artinya, itu sederhana
disown -a
akan menghapus semua pekerjaan dari tabel pekerjaan dan membuatnya tidak ada
disown -a
menghapus semua pekerjaan. Sederhana disown
hanya menghilangkan pekerjaan saat ini. Seperti halaman manual dalam jawaban mengatakan.
Ini adalah jawaban yang bagus di atas, saya hanya ingin menambahkan klarifikasi:
Anda tidak dapat disown
melakukan pid atau proses, Anda disown
pekerjaan, dan itu adalah perbedaan penting.
Pekerjaan adalah sesuatu yang merupakan gagasan tentang proses yang melekat pada shell, oleh karena itu Anda harus membuang pekerjaan ke latar belakang (tidak menangguhkannya) dan kemudian menolaknya.
Isu:
% jobs
[1] running java
[2] suspended vi
% disown %1
Lihat http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ untuk diskusi lebih rinci tentang Kontrol Pekerjaan Unix.
Sayangnya disown
khusus untuk bash dan tidak tersedia di semua shell.
Rasa Unix tertentu (misalnya AIX dan Solaris) memiliki opsi pada nohup
perintah itu sendiri yang dapat diterapkan untuk proses yang berjalan:
nohup -p pid
AIX
dan Solaris
. "Versi nohup AIX dan Solaris memiliki opsi -p yang memodifikasi proses yang berjalan untuk mengabaikan sinyal SIGHUP masa depan. Tidak seperti bawaan yang dijelaskan di atas yang dibangun oleh bash, nohup -p menerima ID proses.". Sumber
Jawaban Node benar-benar hebat, tetapi tetap membuka pertanyaan bagaimana stdout dan stderr diarahkan. Saya menemukan solusi di Unix & Linux , tetapi juga tidak lengkap. Saya ingin menggabungkan dua solusi ini. Ini dia:
Untuk pengujian saya, saya membuat skrip bash kecil yang disebut loop.sh, yang mencetak pid itu sendiri dengan tidur sebentar dalam loop tak terbatas.
$./loop.sh
Sekarang dapatkan PID dari proses ini entah bagaimana. Biasanya ps -C loop.sh
cukup baik, tetapi dicetak dalam kasus saya.
Sekarang kita dapat beralih ke terminal lain (atau tekan ^ Z dan di terminal yang sama). Sekarang gdb
harus dilampirkan ke proses ini.
$ gdb -p <PID>
Ini menghentikan skrip (jika berjalan). Keadaannya dapat diperiksa oleh ps -f <PID>
, di mana STAT
bidangnya adalah 'T +' (atau dalam kasus ^ Z 'T'), yang artinya (man ps (1))
T Stopped, either by a job control signal or because it is being traced
+ is in the foreground process group
(gdb) call close(1)
$1 = 0
Tutup (1) mengembalikan nol jika berhasil.
(gdb) call open("loop.out", 01102, 0600)
$6 = 1
Buka (1) mengembalikan deskriptor file baru jika berhasil.
Terbuka ini sama dengan open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)
. Alih-alih O_RDWR
O_WRONLY
bisa diterapkan, tetapi /usr/sbin/lsof
mengatakan 'u' untuk semua penangan file std * ( FD
kolom), yaitu O_RDWR
.
Saya memeriksa nilai di file header /usr/include/bits/fcntl.h.
File output dapat dibuka dengan O_APPEND
, seperti yang nohup
akan dilakukan, tetapi ini tidak disarankan oleh man open(2)
, karena kemungkinan masalah NFS.
Jika kita mendapatkan -1 sebagai nilai kembali, lalu call perror("")
mencetak pesan kesalahan. Jika kita membutuhkan errno, gunakan p errno
perintah gdb.
Sekarang kita dapat memeriksa file yang baru diarahkan. /usr/sbin/lsof -p <PID>
cetakan:
loop.sh <PID> truey 1u REG 0,26 0 15008411 /home/truey/loop.out
Jika kita mau, kita dapat mengarahkan stderr ke file lain, jika kita ingin menggunakan call close(2)
dan call open(...)
lagi menggunakan nama file yang berbeda.
Sekarang yang terlampir bash
harus dilepaskan dan kita dapat berhenti gdb
:
(gdb) detach
Detaching from program: /bin/bash, process <PID>
(gdb) q
Jika skrip dihentikan oleh gdb
dari terminal lain itu terus berjalan. Kita dapat beralih kembali ke terminal loop.sh. Sekarang tidak menulis apa pun ke layar, tetapi menjalankan dan menulis ke dalam file. Kita harus meletakkannya di latar belakang. Jadi tekan ^Z
.
^Z
[1]+ Stopped ./loop.sh
(Sekarang kita berada dalam kondisi yang sama seolah-olah ^Z
ditekan di awal.)
Sekarang kita dapat memeriksa status pekerjaan:
$ ps -f 24522
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID><PPID> 0 11:16 pts/36 S 0:00 /bin/bash ./loop.sh
$ jobs
[1]+ Stopped ./loop.sh
Jadi proses harus berjalan di latar belakang dan terlepas dari terminal. Angka dalam jobs
output perintah dalam tanda kurung mengidentifikasi pekerjaan di dalam bash
. Kita bisa menggunakan bash
perintah bawaan berikut yang menerapkan tanda '%' sebelum nomor pekerjaan:
$ bg %1
[1]+ ./loop.sh &
$ disown -h %1
$ ps -f <PID>
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID><PPID> 0 11:16 pts/36 S 0:00 /bin/bash ./loop.sh
Dan sekarang kita bisa berhenti dari bash panggilan. Proses terus berjalan di latar belakang. Jika kita menghentikan PPID-nya menjadi proses 1 (init (1)) dan terminal kontrol menjadi tidak dikenal.
$ ps -f <PID>
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID> 1 0 11:16 ? S 0:00 /bin/bash ./loop.sh
$ /usr/bin/lsof -p <PID>
...
loop.sh <PID> truey 0u CHR 136,36 38 /dev/pts/36 (deleted)
loop.sh <PID> truey 1u REG 0,26 1127 15008411 /home/truey/loop.out
loop.sh <PID> truey 2u CHR 136,36 38 /dev/pts/36 (deleted)
KOMENTAR
Hal-hal gdb dapat secara otomatis membuat file (misalnya loop.gdb) yang berisi perintah dan jalankan gdb -q -x loop.gdb -p <PID>
. Loop.gdb saya terlihat seperti ini:
call close(1)
call open("loop.out", 01102, 0600)
# call close(2)
# call open("loop.err", 01102, 0600)
detach
quit
Atau seseorang dapat menggunakan liner berikut sebagai gantinya:
gdb -q -ex 'call close(1)' -ex 'call open("loop.out", 01102, 0600)' -ex detach -ex quit -p <PID>
Saya harap ini adalah deskripsi solusi yang cukup lengkap.
lsof
(nama file menangani adalah pipe
tidak suka /dev/pts/1
) atau dengan ls -l /proc/<PID>/fd/<fd>
(ini menunjukkan symlink dari pegangan). Selain itu, subproses masih belum dapat mengalihkan keluaran, yang harus diarahkan ke file.
Untuk mengirim proses yang sedang berjalan ke nohup ( http://en.wikipedia.org/wiki/Nohup )
nohup -p pid
, itu tidak berhasil untuk saya
Kemudian saya mencoba perintah berikut dan itu bekerja dengan sangat baik
Jalankan beberapa SOMECOMMAND, katakanlah /usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1
.
Ctrl+ Zuntuk menghentikan (menghentikan sementara) program dan kembali ke shell.
bg
untuk menjalankannya di latar belakang.
disown -h
sehingga proses tidak terbunuh saat terminal ditutup.
Ketik exit
untuk keluar dari shell karena sekarang Anda baik untuk pergi karena operasi akan berjalan di latar belakang dalam prosesnya sendiri, sehingga tidak terkait dengan shell.
Proses ini setara dengan berjalan nohup SOMECOMMAND
.
bg
- ini akan menempatkan pekerjaan di latar belakang dan kembali dalam proses yang berjalandisown -a
- ini akan memotong semua lampiran dengan pekerjaan (sehingga Anda dapat menutup terminal dan itu akan tetap berjalan)Langkah-langkah sederhana ini akan memungkinkan Anda untuk menutup terminal sambil menjaga proses tetap berjalan.
Itu tidak akan memakai nohup
(berdasarkan pemahaman saya tentang pertanyaan Anda, Anda tidak membutuhkannya di sini).
Ini bekerja untuk saya di Ubuntu linux saat di tcshell.
CtrlZ untuk menghentikannya
bg
untuk berjalan di latar belakang
jobs
untuk mendapatkan nomor pekerjaannya
nohup %n
di mana n adalah nomor pekerjaan
nohup: failed to run command '%1': No such file or directory
yourExecutable &
dan output terus muncul di layar danCtrl+C
tampaknya tidak menghentikan apa pun, ketik saja secara membabi butadisown;
dan tekanEnter
bahkan 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.