GNU/Linux >> Belajar Linux >  >> Linux

Saat Mengetik Ctrl-c Di Terminal, Mengapa Pekerjaan Latar Depan Tidak Dihentikan Sampai Selesai??

Tutup . Pertanyaan ini membutuhkan detail atau kejelasan. Saat ini tidak menerima jawaban.

Ingin memperbaiki pertanyaan ini? Tambahkan detail dan klarifikasi masalahnya dengan mengedit postingan ini.

Ditutup 3 tahun yang lalu.


Perbaiki pertanyaan ini

Untuk memahami

Jika Bash menunggu perintah untuk diselesaikan dan menerima sinyal untuk
mana jebakan telah ditetapkan, jebakan tidak akan dijalankan hingga
perintah selesai.

Saat Bash menunggu perintah asinkron melalui fitur wait bawaan ,
penerimaan sinyal yang perangkapnya telah ditetapkan akan menyebabkan
builtin tunggu untuk segera kembali dengan status keluar lebih besar dari
128, segera setelah perangkap dijalankan.

dari manual Bash,
Saya menjalankan yang berikut:

  1. Dalam dua contoh saya, SIGINT (dikirim dengan Ctrl-C) mengakhiri
    pekerjaan latar depan (kasus pertama dalam kutipan) dan pekerjaan latar belakang
    (kasus kedua dalam kutipan) keduanya segera, tanpa menunggu untuk
    mereka selesaikan.

    Apakah kalimat pertama dalam kutipan berarti bahwa jika Bash menjalankan
    pekerjaan latar depan dan menerima sinyal SIGINT , perangkap sinyal
    SIGINT , jika disetel, akan dijalankan hingga perintah selesai?
    Jika ya, mengapa pada contoh pertama saya, apakah ctrl-C buat pekerjaan latar depan
    segera ada sebelum dapat diselesaikan?

    $ sleep 10000  # a foreground job
    ^C
    
    
    $ sleep 10000 & # a background job
    [1] 21219
    $ wait 21219
    ^C
    $ echo $?
    130
    
  2. Apa yang dimaksud dengan “sinyal yang telah memasang jebakan” maksudnya,

    • sinyal arg yang perangkapnya telah ditentukan melalui trap arg sigspec , atau

    • sinyal yang tidak diabaikan, atau

    • sinyal yang perangkapnya bukan yang default?

    Dalam contoh di bagian 1 saya, saya tidak menyiapkan jebakan untuk SIGINT, jadi sinyalnya memiliki
    penangan defaultnya (yang keluar dari loop eksekusi apa pun). Apakah sebuah
    sinyal memiliki pengendali defaultnya dianggap memiliki jebakan yang
    telah dipasang?

  3. Saya membuat jebakan untuk SIGINT , tetapi ctrl-C akan membuat perintah
    berikut keluar sebelum selesai. Jadi apakah ini bertentangan dengan
    kalimat pertama dalam kutipan saya?

    $ trap "echo You hit control-C!" INT
    $ bash -c 'sleep 10; echo "$?"'
    ^C
    $
    

    Sebelum menyetel jebakan untuk SIGINT , ctrl-C juga akan membuat
    perintah yang sama keluar sebelum menyelesaikan. Jadi apakah ini bertentangan dengan
    kalimat pertama dalam kutipan saya?

    $ bash -c 'sleep 10; echo "$?"'
    ^C
    
  4. Bisakah Anda memberikan beberapa contoh untuk menjelaskan apa arti kedua kalimat dalam
    kutipan tersebut?

Terima kasih.

Jawaban yang Diterima:

Apa yang dimaksud dengan "sinyal yang telah memasang jebakan"?

Itu adalah sinyal yang penangannya telah ditentukan (dengan trap 'handling code' SIG ) di mana kode penanganan tidak kosong karena akan menyebabkan sinyal diabaikan.

Jadi sinyal yang memiliki disposisi default bukanlah sinyal yang telah dipasang jebakan.
Beberapa kutipan di posting Anda juga berlaku untuk sinyal yang memiliki disposisi default, meskipun jelas bukan bagian tentang menjalankan perangkap , karena tidak ada jebakan yang ditentukan untuk mereka.

Manual berbicara tentang pengiriman sinyal ke shell , bukan ke perintah yang Anda jalankan dari shell itu.

1.

Jika Bash menunggu perintah untuk diselesaikan dan menerima sinyal bahwa jebakan telah ditetapkan, jebakan tidak akan dijalankan sampai perintah selesai.

(1)

mengapa dalam contoh pertama saya, apakah ctrl-C membuat pekerjaan latar depan segera keluar sebelum dapat diselesaikan

Jika Anda menjalankan sleep 10 pada prompt shell interaktif , shell akan menempatkan pekerjaan itu di latar depan (melalui ioctl() pada perangkat tty yang memberi tahu disiplin baris terminal grup proses mana yang menjadi latar depan), jadi hanya sleep akan mendapatkan SIGINT pada ^C dan shell interaktif tidak akan , jadi tidak berguna untuk menguji perilaku itu.

  • Shell induk, karena bersifat interaktif, tidak akan menerima SIGINT karena prosesnya tidak berada dalam grup proses latar depan.

  • Setiap perintah bebas menangani sinyal sesuka mereka. sleep tidak melakukan sesuatu yang khusus dengan SIGINT, jadi akan mendapatkan disposisi default (berhenti) kecuali SIGINT diabaikan saat startup.

Terkait:Linux – Meningkatkan Volume Video MKV dari Terminal Linux?

(2) Jika Anda menjalankan sleep 10 dalam cangkang non-interaktif ,

bash -c 'sleep 10; echo "$?"'

Keduanya bash noninteraktif shell dan sleep akan menerima SIGINT saat Anda menekan Ctrl-C.

Jika bash keluar langsung, itu bisa meninggalkan sleep perintah berjalan tanpa pengawasan di latar belakang jika kebetulan mengabaikan atau menangani sinyal SIGINT. Jadi sebagai gantinya,

  • bash seperti kebanyakan shell lainnya, blok penerimaan sinyal (setidaknya beberapa sinyal) saat menunggu perintah.
  • Pengiriman dilanjutkan setelah perintah keluar (di mana jebakan dieksekusi). Itu juga menghindari perintah dalam perangkap untuk dijalankan secara bersamaan dengan perintah lain.

Dalam contoh di atas, sleep akan mati setelah SIGINT, jadi bash tidak perlu menunggu lama untuk menangani SIGINT-nya sendiri (disini mati karena saya tidak menambahkan trap di SIGINT).

(3) saat Anda menekan Ctrl+C saat menjalankan shell noninteraktif:

bash -c 'sh -c "trap "" INT; sleep 3"; echo "$?"'

(tanpa trap pada SIGINT) bash tidak dibunuh oleh SIGINT. bash , seperti beberapa shell lainnya memperlakukan SIGINT dan SIGQUIT secara khusus. Mereka menerapkan keluar menunggu dan kooperatif perilaku yang dijelaskan di https://www.cons.org/cracauer/sigint.html (dan diketahui menyebabkan beberapa gangguan seperti skrip yang memanggil perintah penanganan SIGINT yang tidak dapat diinterupsi dengan ^C )

(4) Untuk menguji dengan benar, Anda harus menjalankan bash non-interaktif bahwa memiliki perangkap SIGINT yang disetel dan memanggil perintah yang tidak langsung mati pada SIGINT seperti:

bash -c 'trap "echo Ouch" INT; sh -c "trap "" INT; sleep 3"'

bash sedang menunggu sh yang memiliki (bersama dengan sleep ) SIGINT diabaikan (karena trap "" INT ), jadi SIGINT tidak akan mematikan sleep atau sh . bash tidak mengabaikan SIGINT, tetapi penanganannya ditunda hingga sh kembali. Anda melihat Ouch sedang ditampilkan, bukan pada Ctrl+C , tapi setelah sleep dan sh telah dihentikan secara normal.

Perhatikan bahwa trap perintah menetapkan perangkap untuk sinyal untuk shell yang sama di mana ia berjalan. Jadi ketika trap perintah dijalankan di luar shell noninteractive dan di shell induk,

$ trap "echo You hit control-C!" INT
$ bash -c 'sleep 10; echo "$?"'
^C
$

bash yang noninteraktif , dan sleep perintah tidak akan mewarisi trap dari cangkang induk. Penangan sinyal hilang saat menjalankan perintah yang berbeda (execve() menghapus seluruh ruang alamat proses termasuk kode pawang). Setelah execve() , sinyal yang memiliki penangan yang ditentukan kembali ke disposisi default, yang diabaikan tetap diabaikan.
Selain itu, di sebagian besar shell, trap s juga direset di sub-kulit.

2.

Saat Bash menunggu perintah asinkron melalui fitur wait bawaan , penerimaan sinyal yang perangkapnya telah ditetapkan akan menyebabkan fitur tunggu segera kembali dengan status keluar lebih besar dari 128, segera setelah perangkap dijalankan.

Saat menggunakan wait secara eksplisit , wait diinterupsi oleh sinyal apa pun yang memiliki jebakan (dan jelas juga sinyal yang membunuh cangkang sama sekali).

Terkait:Bagaimana cara memformat partisi menjadi sistem file dengan cepat?

Itu membuat sulit untuk mendapatkan status keluar dari suatu perintah secara andal ketika ada sinyal yang terjebak :

$ bash -c 'trap "echo Ouch" INT; sh -c "trap "" INT; sleep 10" & wait "$!"; echo "$?"'
^COuch
130

Dalam hal ini, sleep dan sh tidak dibunuh oleh SIGINT (karena mereka mengabaikannya). Masih wait kembali dengan 130 status keluar karena sinyal (SIGINT) diterima saat menunggu sh . Anda harus mengulang wait "$!" sampai sh benar-benar berakhir untuk mendapatkan sh status keluar.


Linux
  1. Mengapa Bash Prompt Disadap Saat Saya Menelusuri Riwayat??

  2. Mengapa Beberapa Instance Mate-terminal Memiliki Pid yang Sama?

  3. Bagaimana Mengkonfigurasi Bashrc Untuk Menutup Semua Sesi Tmux Saat Saya Menutup Terminal?

  1. Mengapa Wget Tidak Mati Setelah Koneksi Ssh Hilang?

  2. Mengapa Kursor Melompat Saat Mengetik?

  3. memanggil fungsi ketika program selesai dengan ctrl c

  1. Apa cara yang benar untuk membuat aplikasi PyQt saya berhenti saat dimatikan dari konsol (Ctrl-C)?

  2. Kapan setsid() berguna, atau mengapa kita perlu mengelompokkan proses di Linux?

  3. mengapa bash while loop tidak keluar saat menyalurkan ke subperintah yang diakhiri?