Bagaimana saya bisa menolak proses yang sedang berjalan dan menghubungkannya dengan shell layar baru?

159

Saya memiliki program yang berjalan pada shell SSH. Saya ingin menjeda dan dapat menghentikan sementara eksekusi ketika saya kembali.

Salah satu cara saya berpikir untuk melakukan itu adalah untuk mentransfer kepemilikannya ke shell layar, sehingga tetap berjalan di sana.

Apakah ada cara lain untuk melanjutkan?

levesque
sumber
8
Lihat juga Dapatkah saya nohup / menyaring proses yang sudah dimulai? dan Lanjutkan perintah yang berjalan di sesi SSH yang dijatuhkan , yang menyebutkan beberapa solusi berbasis ptrace yang (saat ini) tidak disebutkan di sini.
Gilles
Dari pertanyaan seperti unix.stackexchange.com/a/4039/13496 Saya mendengar tentang retty dan neercs . Hmmm ... bertanya-tanya apakah ada sesuatu seperti lapisan " layar di sini" sebelum saya menjalankan proses lain kali saya harus kehilangan terminal teratas di masa depan, yang akan membuatnya mudah untuk kembali ke stdin / out / err
Marcos
Masalah sekunder / implisit dalam pertanyaan ini yang tidak dapat saya pahami adalah ... mengapa shell memilih untuk menolak pekerjaan yang ditangguhkan ketika ada yang lebih baru / baru saja meluncurkan satu di latar belakang yang bahkan tidak perlu / menunggu stdin? Ini adalah perawatan yang telah saya gunakan sehingga tidak tahu apa yang berbeda di sini ...
Marcos

Jawaban:

86

Menggunakan GNU screenadalah taruhan terbaik Anda.

Mulai layar berjalan ketika Anda pertama kali masuk - saya menjalankan screen -D -R, menjalankan perintah Anda, dan putuskan atau tunda dengan CTRL-Zdan kemudian putuskan dari layar dengan menekan CTRL-Akemudian D.

Saat Anda masuk lagi ke mesin, sambungkan kembali dengan menjalankan screen -D -R. Anda akan berada di shell yang sama seperti sebelumnya. Anda dapat menjalankan jobsuntuk melihat proses yang ditangguhkan jika Anda melakukannya, dan menjalankan %1(atau pekerjaan masing-masing #) untuk foreground lagi.

Andrew Yochum
sumber
2
Wow, saya tidak percaya jawaban Layar GNU saat ini berperingkat paling rendah. Apakah saya melewatkan sesuatu?
Faheem Mitha
1
Mungkin! Sepertinya yang terbaik untukku.
Andrew Yochum
1
Menengok ke belakang, itu jelas merupakan solusi yang paling mudah, asalkan Anda dapat merencanakan dan meluncurkan proses Anda dari dalam lingkungan layar. Bagaimanapun, saya membuatnya menjadi jawaban resmi!
levesque
28
Saya pikir ini tidak menjawab pertanyaan. Pertanyaannya dimulai dengan " Saya punya program yang berjalan ". Jawaban ini mengasumsikan itu belum berjalan ...
Anko
ya dia jelas menulis dia ingin masuk ke sesi layar :-)
Florian Heigl
112

Anda dapat mencabut "kepemilikan" program dari shell dengan disownbuilt-in:

# press Ctrl+Z to suspend the program
bg
disown

Namun ini hanya memberi tahu shell untuk tidak mengirim SIGHUPsinyal ke program ketika shell keluar. Program akan mempertahankan koneksi apa pun yang dimilikinya dengan terminal, biasanya sebagai input standar, output dan stream error. Tidak ada cara untuk memasang kembali mereka ke terminal lain. ( Layar berfungsi dengan mengemulasi terminal untuk setiap jendela, sehingga program-programnya melekat pada jendela layar.)


Dimungkinkan untuk memasang kembali arsip yang diajukan ke file yang berbeda dengan melampirkan program dalam debugger (yaitu menggunakan ptrace) dan membuatnya memanggil open, dupdan close. Ada beberapa alat yang melakukan ini; ini adalah proses yang rumit, dan kadang-kadang mereka malah menghentikan proses itu. Kemungkinannya termasuk (tautan yang dikumpulkan dari jawaban untuk Bagaimana saya bisa menolak proses yang sedang berjalan dan menghubungkannya dengan shell layar baru? Dan Dapatkah saya nohup / menyaring proses yang sudah dimulai? ):

Gilles
sumber
disownmenghapus proses dari daftar kontrol-pekerjaan.
ctrl-alt-delor
3
Mengapa tidak disown -h?
Cees Timmerman
@CeesTimmerman Meninggalkan pekerjaan di meja kerja shell, tapi apa keuntungannya?
Gilles
@Gilles: jadi Anda masih bisa fgatau killtidak, dan lihat apakah itu berakhir sendiri.
Peter Cordes
Utilitas apa yang disebutkan bekerja dengan sekelompok proses (misalnya bzcat a.bz2 | grep text)? Man for reptyrmengatakan bahwa itu tidak mendukung memindahkan proses dengan anak-anak.
dma_k
64

Untuk memindahkan proses antar terminal atau untuk memasang kembali pembangkrutan, Anda dapat menggunakan mis . Reptyr .

Jofel
sumber
1
Ya itu menyelamatkannya, terima kasih! Saya membaca situs web penulis cara kerjanya lebih baik daripada alat yang sama atau lebih tua misalnya. untuk program ncurses.
Marcos
4
Ini luar biasa; itu harus menyelesaikan kesulitan seorang teman untuk terus-menerus kehilangan pekerjaannya dengan menjalankannya langsung di ssh dan kemudian perlu naik kereta. "Ups, lupa menggunakan layar. Lagi."
Adam Katz
3
+1 Meskipun screenjawaban yang diterima tentu saja ideal, itu tidak benar-benar menjawab pertanyaan, yang secara khusus meminta cara untuk memindahkan proses yang sedang berjalan ke screenatau sejenisnya. Lihat juga jawaban ini: serverfault.com/a/284795
toxefa
1
Penghemat hidup absolut. Izinkan saya untuk melampirkan kembali menjalankan apt-upgrade yang sedang menunggu konfirmasi pengguna.
andig
28

Solusi favorit saya adalah menggunakan tmux, Anda dapat melepaskan sesi, dan melampirkannya kembali di terminal lain.

Ketika Anda terlepas dari sesi sebelumnya, Anda dapat menutup terminal dengan aman; nanti gunakan tmux attachuntuk kembali ke sesi, bahkan jika Anda keluar.

bunga aster
sumber
1
Anda juga dapat berbagi sesi dengan teman Anda dan menggunakan banyak jendela dan panel dan banyak lagi! love it ^ _ ^
igor
contoh menggunakan tolong?
Vitaly Zdanevich
21

Ada juga utilitas kecil bernama retty yang memungkinkan Anda memasang kembali program yang sedang berjalan ke terminal lain.

adamg
sumber
19

Saya tidak menggunakannya secara teratur, tetapi neercs mengklaim untuk mendukung ini. Ini adalah screen-seperti program dengan aneka fitur mewah seperti manajemen panel yang lebih baik, tetapi hal utama yang ditawarkannya adalah kemampuan untuk mengimpor proses ke dalam panel

Michael Mrozek
sumber
2
Menarik. Itu bermain kotor ( ptrace), tetapi itu tidak hanya memanipulasi deskriptor file, itu garpu proses. Itu bisa diraih find /, tetapi gagal di bash interaktif.
Gilles
@Gilles Saya tidak ingat bagaimana hasilnya ketika saya mencoba, tetapi tidak memiliki reputasi yang bagus, saya diberitahu bahwa kegagalan itu cukup sering
Michael Mrozek
9

Jika Anda hanya ingin pause dan restart setelah itu, Anda dapat menggunakan killdengan STOPatau CONTsinyal.

Pada awalnya cari tahu proses PID dengan

$ ps aux

Kemudian kirim sinyal ke PID yang terdaftar untuk proses

$ kill -STOP <PID>

$ kill -CONT <PID>
Yunzen
sumber
9

"injcode" dari ThomasHabets tampaknya persis seperti yang saya butuhkan:

https://github.com/ThomasHabets/injcode

Program injcode memungkinkan kode sewenang-wenang untuk disuntikkan ke dalam proses yang berjalan, apakah Anda tahu sebelumnya dan sedang menjalankan layar atau tmux

Dari README:

Contoh 1: pindahkan irssi dari satu terminal ke terminal lainnya

Mungkin memindahkannya ke layar.

Pertama mulai irssi di satu terminal.

Jalankan injcode di terminal lain: $ injcode -m retty

Irssi sekarang harus dipindahkan ke terminal kedua, termasuk memiliki terminal pengendali baru.

pengguna2688272
sumber
1

Ini bekerja untuk saya:

  1. bg proses
  2. jobs -l cari nomor proses
  3. tmux mulai shell window manager
  4. reptyr -L PROCESSNUMBER

reptyr's -Lyang diperlukan untuk mendapatkan ini untuk bekerja:

-L Like '-l', but also redirect the child's stdio to the slave.

karena kesalahan ini:

$ reptyr 30622

[-] Unable to open the tty in the child.
Unable to attach to pid 30622: Permission denied

Dan dengan -L

$ reptyr -L 30622
Opened a new pty: /dev/pts/4
guaka
sumber