Perangkap 'Ctrl + c' untuk skrip bash tetapi tidak untuk proses terbuka di skrip ini

11

Saya mencoba memiliki program interaktif dalam skrip bash:

my_program

Dan saya berharap dapat menutupnya dengan 'Ctrl + c'. Tetapi ketika saya melakukannya skrip saya juga ditutup.

Saya tahu tentang.

trap '' 2
my_program
trap 2

Tetapi dalam kasus ini, saya tidak bisa menutup my_programdengan Ctrl + c.

Apakah Anda tahu cara mengizinkan Ctrl + c pada suatu program, tetapi tidak menutup skrip yang menjalankannya?

Sunting: tambahkan contoh

#!/bin/bash
my_program
my_program2

Jika saya menggunakan Ctrl + c untuk menutup my_program, my_program2tidak pernah dieksekusi karena seluruh skrip keluar.

bob dylan
sumber

Jawaban:

13

Anda harus menggunakan trap true 2atau trap : 2bukannya trap '' 2. Itulah yang "jebakan bantuan" dalam bash shell mengatakan tentang itu:

Jika ARG adalah string nol, setiap SIGNAL_SPEC diabaikan oleh shell dan oleh perintah yang diminta .

Contoh:

$ cat /tmp/test
#! /bin/sh
trap : INT
cat
echo first cat killed
cat
echo second cat killed
echo done
$ /tmp/test
   <press control-C>
^Cfirst cat killed
   <press control-C>
^Csecond cat killed
done
mosvy
sumber
2
Bagaimana dengan membunuh taildan bukannya membunuh kucing lain kali?
kubanczyk
12

Anda dapat mengatur ulang jebakan ke defaultnya dengan memberikan perintah jebakan -sebagai argumen aksinya. Jika Anda melakukan ini dalam subkulit , itu tidak akan mempengaruhi jebakan di shell induk. Dalam skrip Anda, Anda bisa melakukan ini untuk setiap perintah yang harus Anda interupsi dengan Ctrl-C:

#!/bin/bash
# make the shell (and its children) ignore SIGINT
trap '' INT
.
.
.
# but this child won't ignore SIGINT
(trap - INT; my_program)
# the rest of the script is still ignoring SIGINT
.
.
.
Tandai Plotnick
sumber
1
Sementara jawaban yang diterima mungkin lebih baik dan lebih kanonik untuk shell, ini adalah jawaban yang bagus karena memperkenalkan prinsip umum (bukan shell-spesifik) untuk bagaimana melakukan semacam ini sinyal masking / abaikan dengan aman.
R .. GitHub BERHENTI MEMBANTU ICE
Saya kira Anda bisa exec my_programdalam subkulit, menjadi sedikit lebih efisien.
Toby Speight
@ R .. itu sama sekali tidak spesifik shell - jika Anda mengatur sinyal ke SIG_IGN (itulah yang dilakukan perangkap dengan string kosong), keadaan itu akan diwarisi melalui exec (), kecuali untuk SIGCHLD. Itu perilaku mandat POSIX. Lihat juga jawaban untuk stackoverflow.com/questions/32708086/…
mosvy
@mosvy: Saya tidak melihat bagian mana dari komentar saya yang tidak Anda setujui. Seluruh poin saya adalah bahwa "tutup / abaikan sebelum garpu, buka tutup / hapus tanda pada anak sebelum exec" adalah prinsip umum yang berguna untuk mengetahui di luar konteks pemrograman shell yang adil.
R .. GitHub BERHENTI MEMBANTU ICE
1
Ini jawaban yang sangat berguna. Sebagai pengguna Linux yang berpengalaman, saya dapat mengatakan saya belum pernah mendengar ini sebelumnya. Ini memiliki cukup banyak kegunaan ... Anda mendapat upvote dan bookmark saya.
Dev
-1


Ketika Anda menggunakan Crtl+ C, Anda menghentikan program (" bunuh " itu).
Apa yang mungkin Anda cari adalah untuk menunda program Anda (" jeda " itu). Untuk ini, Anda dapat menggunakan Crtl+ Z.
Setelah program Anda dijeda, Anda dapat melihatnya menggunakan jobs. Sebagai contoh:
[1]+ Stopped ./foobar
Di sini saya hanya memiliki satu pekerjaan, pekerjaan # 1, tetapi mungkin ada lebih dari satu - setiap pekerjaan memiliki nomor sendiri.
Anda dapat mengontrol proses yang ditangguhkan menggunakan sejumlah perintah, misalnya bg, fgdan kill.
bg %1akan restart pekerjaan # 1 di b ack g putaran
fg %1akan me-restart pekerjaan # 1 di f bijihg round
kill %1akan mematikan pekerjaan # 1
Perhatikan bahwa Anda dapat menggunakan bgdan fgtanpa argumen jika Anda hanya memiliki satu pekerjaan aktif.

pi0tr
sumber
Terima kasih tetapi tidak, saya ingin melakukan Ctrl + c.
bob dylan