Mengapa beberapa perintah 'hang' terminal sampai selesai?

22

Terkadang Anda menjalankan program dari terminal, katakan, lxpanel . Terminal tidak akan menjatuhkan Anda kembali ke prompt, itu akan menggantung. Anda dapat menekan Ctrl+ Cuntuk kembali ke prompt, tetapi itu akan mematikan lxpanel. Namun, menekan Alt+ F2(yang muncul jendela untuk mengambil perintah) dan menjalankan lxpanelbekerja dengan anggun.

Kenapa ini? Apa perbedaan antara menjalankan perintah dari terminal dan dari jendela 'jalankan' yang muncul ketika Anda menekan Alt+ F2?

lxpanel di sini baru saja digunakan sebagai contoh. Saya pernah mengalami ini dengan banyak program

sqram
sumber
1
Tip: Layar GNU ( screen) dapat, antara lain, digunakan untuk "membungkus" proses yang berjalan lebih lama. Anda dapat melepaskannya, kembali ke shell, lalu pasang kembali dan lihat output dari proses yang berjalan. Penyambungan kembali bahkan dapat dilakukan dari terminal lain, SSH dll. Mungkin juga ada program lain yang memungkinkan Anda melakukan hal semacam ini.
poplitea

Jawaban:

28

Secara default terminal akan menjalankan program di latar depan, sehingga Anda tidak akan kembali ke shell sampai program selesai. Ini berguna untuk program yang membaca dari stdin dan / atau menulis ke stdout - Anda biasanya tidak ingin banyak dari mereka berjalan sekaligus. Jika Anda ingin program dijalankan di latar belakang, Anda bisa memulainya seperti ini:

$ lxpanel &

Atau jika sudah berjalan, Anda dapat menangguhkannya dengan Ctrl+ Zdan kemudian jalankan bguntuk memindahkannya ke latar belakang. Bagaimanapun Anda akan berakhir dengan prompt shell baru, tetapi program ini masih berjalan dan hasilnya akan muncul di terminal (sehingga tiba-tiba dapat muncul saat Anda sedang mengetik)

Beberapa program (biasanya daemon) akan memotong proses yang terpisah ketika mereka mulai, dan kemudian membiarkan proses utama segera keluar. Ini memungkinkan program tetap berjalan tanpa memblokir shell Anda

Michael Mrozek
sumber
Jadi apa yang sebenarnya dilakukan sistem ketika Anda menjalankan program melalui jendela 'jalankan' dengan menekan Alt + f2? (setidaknya pada gnome dan openbox, alt + f2 melakukan itu). Saya bertanya karena begitu Anda mengetik perintah, program dimulai dan kotak hilang. apakah itu hanya menambahkan & ke dalamnya?
sqram
2
@lyrae: secara default, shell menunggu program untuk menyelesaikan sebelum melanjutkan sesi shell, itu tidak "hang", dengan definisi "hang"; alt + f2 tidak menunggu program. Alasan shell menunggu program untuk selesai adalah karena shell dapat mengarahkan ulang apa pun yang diketik pengguna ke shell ke input standar program dan / atau menampilkan output standar program. Karena alt + f2 terutama digunakan untuk memulai program GUI, alt + f2 tidak memberikan kemungkinan untuk menggunakan input / output standar sehingga tidak perlu menunggu.
Lie Ryan
1
@lyrae: alt + f2 tidak melakukan sesuatu yang istimewa untuk memulai program di latar belakang; itu adalah shell yang melakukan sesuatu yang istimewa, menambahkan '&' adalah fungsionalitas shell. Ketika memulai perintah tanpa tanda '&', shell mengarahkan ulang input standar program ke input standarnya sendiri dan output standar program ke output standarnya sendiri (sedikit dibuat-buat, karena shell juga menyediakan banyak layanan lain, seperti mencegat Ctrl -C, untuk mengirim perintah sinyal SIGINT ke program latar depan). Tanda '&' memberi tahu shell untuk tidak melakukan itu dan hanya memulai program (juga dibuat-buat).
Lie Ryan
1
@LieRyan beberapa dari apa yang Anda katakan shell lakukan sebenarnya ditangani oleh driver terminal kernel, dan "dengan &" umumnya lebih "spesial" daripada "tanpa &", selain itu shell memanggil menunggu () [atau waitpid or equivalent] yang tidak dikerjakan oleh alt-f2.
Random832
6

Ketika Anda memulai program di terminal, terminal akan "hang" sampai program Anda berhenti. Dengan menekan Ctrl+ cAnda menutup program Anda, dan dengan demikian kembali ke prompt. Anda akan melihat ini dengan semua aplikasi GUI, coba Firefox, misalnya.

Ketika Anda menggunakan beberapa metode lain seperti Alt + F2 atau mengklik menu, program Anda dimulai di latar belakang sehingga tidak ada yang aneh terjadi (dan toh tidak ada command prompt).

Jika Anda masih ingin meluncurkan aplikasi GUI dari terminal, tambahkan &di akhir perintah Anda, seperti itu

lxpanel &

Ini memberi tahu terminal untuk berjalan lxpaneldi latar belakang dan segera memberi Anda prompt.

phhehehe
sumber
3

Program dijalankan melalui menjalankan shell di latar depan shell itu secara default. Ini menyebabkan shell untuk menunda operasi dan mengarahkan stdin / stdout / sterr dari terminal ke program. Program yang dijalankan melalui lingkungan desktop adalah bercabang , yang menyebabkan mereka berjalan secara independen dari program yang menjalankannya. Ini dapat disimulasikan di sebagian besar shell dengan menambahkan &perintah, meskipun ini masih akan menghubungkan std * ke terminal (walaupun membaca dari stdin pada program latar belakang memiliki komplikasi lebih lanjut).

Ignacio Vazquez-Abrams
sumber
2

& Latar belakang dengan baik kecuali untuk program yang kembali yang memerlukan interaksi konsol nanti (misalnya, "pembaruan apt & y" yang akhirnya memasuki status STOP karena ingin memberi pengguna pertanyaan "benar-benar sangat memaksa?") .... ketika tidak ada yang menonton lagi).

Untuk menyumbat lubang itu dan menginformasikan proses terminal tidak akan pernah benar-benar tersedia untuk itu, saya menambahkan <& - untuk beberapa perintah saya, benar-benar melepaskan mereka dari terminal aktif memberitahu mereka STDIN tidak mungkin lagi. Pastikan / bin / bash adalah shell Anda jika Anda menggunakannya. Script akan terus mencatat kesalahan yang terkait dengan tidak ada pseudoterminal yang tersedia untuk memberikan prompt.

Sebagai contoh:

`./runme.sh &> runme.log <&- & disown`

adalah cara utama saya melepaskan diri dari sesi terminal saat ini. Baik STDOUT dan STDERR bisa masuk ke runme.log, tidak masalah jika konsol atau shell Anda berakhir lebih cepat atau jika Anda logout / su ke akun yang berbeda (tidak ada sampah terminal dari runme), dan terima kasih untuk menolak bahkan orang tua-anak Hubungan PID dihapus.

UPDATE: bahkan dengan itu saya punya masalah dengan semaphore mengaitkannya dengan nama induk asli, jadi sekarang saya sarankan sebagai gantinya:

at now <<< "(cmd1; cmd2; etc.) &> logfile.log"

Tentu saja, hapus &> jika Anda ingin mengirim output melalui email dari CRON, atau mengarahkan semuanya ke / dev / null alih-alih file.

Marcos
sumber
Cara yang sedikit berbelit-belit untuk mencapai yang mulai saya gunakan adalahat now <<< "(cmd1; cmd2; etc.) &> logfile.log"
Marcos