Cegah tugas linux yang sedang berjalan untuk dimatikan setelah keluar dari SSH

18

Saya memiliki tugas komputasi yang berjalan selama beberapa hari di server linux melalui koneksi SSH. Itu tidak di latar belakang, sehingga koneksi SSH sedang dalam tugas.

Saya ingin me-restart mesin lokal (bukan server) dari mana saya telah membuka sesi ssh, tetapi ingin tetap menjalankan tugas. Apakah itu mungkin?

Ali
sumber

Jawaban:

22

Jika tugas Anda sudah diluncurkan, sudah terlambat *untuk mempertimbangkan solusi alternatif yang menyisipkan lapisan tambahan antara Anda sshsesi dan shell menjalankan perintah, seperti screen, tmux, byobu, nohupdan sejenisnya.

Jika proses Anda mendukung untuk ditempatkan di latar belakang dan terutama tidak menggantung kapan stdoutdan stderrtidak dapat ditulis / ditutup, Anda dapat meletakkannya di latar belakang sebelum keluar dengan ControlZdan bgkemudian lepaskan dari shell Anda dengan disownbuiltin.

misalnya:

$ ssh localhost
You have new mail.
Last login: Fri Jun  6 11:26:56 2014

$ /bin/sleep 3600    


^Z[1] + Stopped                  /bin/sleep 3600
$ bg
[1] /bin/sleep 3600&
$ jobs
[1] +  Running                 /bin/sleep 3600
$ disown %1
$ exit
Connection to localhost closed.
$ ps -ef|grep sleep
jlliagre 12864     1  0 21:12 ?        00:00:00 /bin/sleep 3600
jlliagre 13056 12477  0 21:13 pts/18   00:00:00 grep sleep
$ 

*Seperti yang dikomentari Bob, sebenarnya ada beberapa cara hack untuk memperbaiki sesi tty di Linux. repty, retty , injcode dan neercs . Terlihat paling canggih untuk reptyr tetapi Anda mungkin perlu hak akses root untuk mengaktifkan ptrace untuk meretas proses Anda.

Jlliagre
sumber
Saya menggunakan Ctrl + Z, pekerjaan berhenti dan pindah ke latar belakang, lalu melakukan disownperintah. Ini dikembalikan: bash: peringatan: menghapus pekerjaan yang dihentikan 1 dengan grup proses 24876. Sekarang pekerjaan saya terdaftar ps -alltetapi tampaknya tidak berfungsi (penggunaan CPU adalah 0%)
Ali
Sepertinya proses saya terhenti. Saya kira saya seharusnya memberikan ID proses dengan disownperintah
Ali
@ Ali Saya pikir Anda lupa menjalankan perintah bg untuk melanjutkan pekerjaan yang ditangguhkan.
Jason Zhu
1
@JasonZhu Terima kasih telah menunjukkan itu. Tidak jelas bgperintah itu diperlukan di bagian pertama dari balasan saya. Diedit.
jlliagre
2
Jika Anda lupa perintah bg dan hanya menjalankan perintah disown, Anda harus bisa menjalankan proses lagi kill -CONTyang kira-kira sama dengan yang dilakukan bg.
kasperd
5

Salah satu solusinya adalah menggunakan layar GNU . Anda dapat memulai screen, menjalankan perintah, lalu melepaskan C-a d. Kemudian, untuk menyambung kembali, lakukan screen -r, dan Anda kembali ke sesi sebelumnya.

Manfaat lain dari layar adalah manajemen jendela (sehingga Anda dapat beralih ke shell lain saat perintah Anda sedang berjalan, tanpa memerlukan koneksi SSH baru), dan itu memungkinkan perintah Anda untuk tetap berada di latar depan, baik dalam sesi saat ini atau nanti.

Sunting: Seperti disebutkan dalam komentar, ini hanya akan berfungsi jika Anda ingat untuk memulai screensebelum menjalankan perintah. Jika perintah sudah berjalan, maka Anda membutuhkan solusi @ jlliagre.

Scott Weldon
sumber
2
tmuxadalah program lain seperti screenitu yang memungkinkan Anda memiliki sesi jarak jauh yang tidak terikat dengan koneksi SSH Anda saat ini.
Darth Android
2
Solusi Anda sangat bagus. Namun itu tidak sepenuhnya sesuai dengan pertanyaan saya - saya bertanya tentang proses yang sedang berjalan, bukan proses yang harus dijalankan di masa depan menggunakan screen.
Ali
Ah, baiklah. Dalam hal ini, saya pikir Anda perlu menggunakan solusi @ jlliagre. (Sejauh yang saya tahu, tidak ada cara untuk menghubungkan proses yang sudah berjalan dengan sesuatu seperti screenatau tmux.)
Scott Weldon
1

Salah satu cara "standar" untuk melakukannya, adalah dengan menggunakan nohupperintah, termasuk dalam coreutils, seperti ini:

nohup COMMAND [ARGS] &

Tetapi perintah itu akan mengarahkan output ( STDOUT& STDERRAFAIK) dari program ke dalam file nohup.out, membuatnya kadang-kadang menjengkelkan (seperti menghasilkan file log besar), jadi Anda mungkin ingin membuat pengalihan sendiri, atau mengarahkannya ke / dev / null jika kamu mau.

wangguoqin1001
sumber
2
Baca lagi. Prosesnya sudah berjalan .
Lightness Races with Monica
Aku malu tidak membaca dengan cermat. Maaf.
wangguoqin1001
Sebenarnya nohupbisa digunakan untuk ini. Tangguhkan saja proses yang sedang berjalan dan kirim ke latar belakang ( Ctrl+ Zdan jalankan bg) lalu Anda dapat menerbitkan nohup %1.
Mike
0

Selain itu, nohupAnda dapat meluncurkan proses di latar belakang menggunakan "&" dan subkulit:

Sufiks perintah dengan & dan bungkus dalam tanda kurung

$ (thecommand args &)

Katakanlah proses Anda mendapatkan pid 1922:

$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
usr      11473  2643  0 15:07 pts/1    00:00:00 bash
usr      11922     1  0 15:11 pts/1    00:00:00 thecommand

Terlihat bahwa itu tidak terikat dari proses shell 11473 yang merupakan induk aslinya. Jadi, jika Anda keluar atau membunuh shell saat ini (11473), proses 11922 terus berjalan, dan itu akan terputus dari Poin.

Cobalah untuk keluar dari shell, dan masukkan shell baru. Meskipun, shell ini terhubung ke Poin yang sama, Anda dapat melihat prosesnya sekarang tanpa Poin:

$ ps -fp 11922
UID        PID  PPID  C STIME TTY          TIME CMD
usr      11922     1  0 15:11 ?        00:00:00 thecommand

Saya tidak tahu bagaimana namanya atau didokumentasikan di Posix, tapi saya menggunakan cara ini sejak 1990 di bsh, ksh dan sekarang di bash.

Terakhir, Anda dapat menggunakan bgperintah shell builtin:

Cukup luncurkan program Anda dan jika Anda memutuskan untuk menjeda, atau berencana untuk menyimpannya di latar belakang, ketik CTRL + Z:

$ thecommand
^Z
[1] Stopped          thecommand

Sekarang biarkan terus berjalan di latar:

$ bg
[1]+ thecommand &

Jika Anda melihat ke proses info, ini belum memiliki proses induk:

$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
usr      12046  2643  0 15:18 pts/6    00:00:00 bash
usr      12571 12046  0 16:00 pts/6    00:00:00 thecommand
usr      12601 12046  0 16:04 pts/6    00:00:00 ps -f

Jadi, keluar dari proses saat ini. Proses yang berjalan di latar belakang tidak terikat dari induk aslinya dan tetap berjalan di latar belakang:

$ exit

Login lagi dan lihat info proses:

$ ps -f 12571
UID        PID  PPID  C STIME TTY          TIME CMD
usr      12571     1  0 16:00 ?        00:00:00 thecommand
Luciano
sumber