Matikan proses dan paksa untuk mengembalikan 0 di Linux?

16

Di lingkungan Linux, bagaimana saya bisa mengirim sinyal kill ke suatu proses, sambil memastikan bahwa kode keluar kembali dari proses itu adalah 0? Apakah saya harus melakukan sihir GDB mewah untuk ini, atau ada sinyal membunuh mewah yang tidak saya sadari?

Kasus cobaan:

cat; echo $?

killall cat

Mencoba berbagai sinyal kill hanya menawarkan sinyal return yang berbeda, seperti 129, 137, dan 143. Tujuan saya adalah untuk mematikan proses yang dijalankan skrip, tetapi membuat skrip berpikir itu berhasil.

sega01
sumber

Jawaban:

20

Anda bisa melampirkan ke proses menggunakan GDB dan ID proses dan kemudian mengeluarkan callperintah dengan exit(0)sebagai argumen.

callmemungkinkan Anda memanggil fungsi dalam program yang sedang berjalan. Memanggil exit(0)keluar dengan kode balik 0.

gdb -p <process name>
....
.... Gdb output clipped
(gdb) call exit(0)

Program exited normally.

Sebagai alat satu baris:

gdb --batch --eval-command 'call exit(0)' --pid <process id>
LeStarke
sumber
Ini tidak akan bekerja jika program ini tidak menggunakan (g) libc, misalnya program yang ditulis dalam perakitan: No symbol table is loaded. Use the "file" command. Meskipun ini sangat tidak mungkin.
Cristian Ciupitu
Bekerja pada naskah ruby ​​:-D
Mikhail
1
@CristianCiupitu Ada cara untuk mengatasi masalah itu. Saat masuk ke panggilan sistem berikutnya cukup modifikasi register yang relevan untuk menyebabkan program target memanggil panggilan _exitsistem dengan 0argumen. Itu akan bekerja pada proses apa pun yang tidak hanya mengulang dan membakar siklus CPU. Jika proses tersebut tidak terjebak dalam infinite loop, Anda masih dapat menggunakan pendekatan yang sama jika Anda dapat menemukan instruksi yang diperlukan di suatu tempat di executable dan arahkan pointer instruksi ke sana.
kasperd
@Mikhail itu bekerja pada "skrip ruby" karena GDB terhubung ke proses interpreter ruby ​​yang binernya dikaitkan dengan glibc.
Daniel
@kasperd, ya, saya kira begitu, tapi instruksi yang lebih tepat akan menyenangkan.
Cristian Ciupitu
8

Tidak. Ketika shell menangkapnya SIGCHLDtanpa syarat menetapkan nilai kembali tepat ke nilai non-nol, jadi ini akan memerlukan modifikasi skrip atau shell.

Ignacio Vazquez-Abrams
sumber
3

Saya tidak yakin tetapi ini akan keluar dengan 0 jika ada sinyal yang terdaftar diterima. Anda dapat melakukan tindakan lain termasuk memanggil fungsi, dll.

#!/bin/bash 
trap 'exit 0' SIGINT SIGQUIT SIGTERM
TBI Infotech
sumber
3

Satu kalimat ini bekerja untuk saya:

/bin/bash -c '/usr/bin/killall -q process_name; exit 0'
Landon Thomas
sumber
Saya pikir Anda tidak mengerti pertanyaan itu. Tidak mungkin, perintah itu akan mencapai apa yang diminta. Ini adalah apa yang saya dapatkan dari menggunakan perintah Anda: $ cat; echo $? Terminated 143.
kasperd
2
@ Land Thomas baris kode Anda yang ditampilkan di sini sebenarnya mengembalikan 0. Namun process_name yang terbunuh TIDAK mengembalikan 0, yang merupakan apa yang diinginkan OP.
Daniel
2

Cara agak hacky, tapi ..

Anda dapat membuat pembungkus untuk proses Anda, menimpa SIGCHLD Handler. Sebagai contoh:

#!/bin/bash
set -o monitor
trap 'exit(0)' CHLD
/some/dir/yourcommand

Setelah itu Anda dapat membuat skrip Anda menjalankan pembungkus ini alih-alih proses Anda dengan meletakkannya lebih awal dalam $ PATH dan mengganti nama dengan nama yang sama.

DukeLion
sumber