Giết một tiến trình và buộc nó trả về 0 trong Linux?


16

Trong môi trường Linux, làm cách nào tôi có thể gửi tín hiệu tiêu diệt đến một quy trình, trong khi đảm bảo rằng mã thoát được trả về từ quy trình đó là 0? Tôi sẽ phải thực hiện một số phép thuật GDB ưa thích cho việc này, hoặc có một tín hiệu tiêu diệt lạ mắt mà tôi không biết?

Trường hợp thử nghiệm:

cat; echo $?

killall cat

Thử nhiều tín hiệu tiêu diệt khác nhau chỉ cung cấp các tín hiệu trả về khác nhau, chẳng hạn như 129, 137 và 143. Mục tiêu của tôi là giết một quá trình chạy tập lệnh, nhưng làm cho tập lệnh nghĩ rằng nó đã thành công.

Câu trả lời:


20

Bạn có thể đính kèm vào quy trình bằng GDB và ID tiến trình và sau đó đưa ra calllệnh với exit(0)tư cách là một đối số.

callcho phép bạn gọi các chức năng trong chương trình đang chạy. Gọi exit(0)thoát với mã trả về 0.

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

Program exited normally.

Là một công cụ một dòng:

gdb --batch --eval-command 'call exit(0)' --pid <process id>

Điều này sẽ không hoạt động nếu chương trình không sử dụng (g) libc, ví dụ như một chương trình được viết bằng cách lắp ráp : No symbol table is loaded. Use the "file" command. Mặc dù điều này rất khó xảy ra.
Cristian Ciupitu

Làm việc trên một kịch bản ruby ​​:-D
Mikhail

1
@CristianCiupitu Có một cách xoay quanh vấn đề đó. Khi vào cuộc gọi hệ thống tiếp theo, chỉ cần sửa đổi các thanh ghi có liên quan để khiến chương trình đích gọi cuộc gọi _exithệ thống với 0tư cách là đối số. Điều đó sẽ hoạt động trên bất kỳ quy trình nào không chỉ đơn giản là lặp và đốt các chu kỳ CPU. Nếu quá trình xảy ra không bị kẹt trong một vòng lặp vô hạn, bạn vẫn có thể sử dụng cùng một cách tiếp cận nếu bạn có thể tìm thấy các hướng dẫn cần thiết ở đâu đó trong tệp thực thi của nó và trỏ con trỏ lệnh vào đó.
kasperd 3/03/2015

@Mikhail nó hoạt động trên "một tập lệnh ruby" vì GDB được kết nối với quy trình phiên dịch ruby ​​có nhị phân được liên kết với glibc.
Daniel

@kasperd, yeah, tôi mặc dù vậy, nhưng hướng dẫn chính xác hơn sẽ tốt đẹp.
Cristian Ciupitu

8

Không. Khi trình bao bắt SIGCHLDnó, nó đặt giá trị trả về một cách thích hợp thành giá trị khác không, do đó, điều này sẽ yêu cầu sửa đổi tập lệnh hoặc trình bao.


3

Tôi không chắc chắn nhưng điều này sẽ thoát với 0 nếu bất kỳ tín hiệu được liệt kê nào được nhận. Bạn có thể thực hiện các hành động khác bao gồm gọi một chức năng, v.v.

#!/bin/bash 
trap 'exit 0' SIGINT SIGQUIT SIGTERM

3

Điều này một làm việc cho tôi:

/bin/bash -c '/usr/bin/killall -q process_name; exit 0'

Tôi không nghĩ bạn đã hiểu câu hỏi. Không có cách nào, lệnh đó sẽ đạt được những gì được yêu cầu. Đây là những gì tôi nhận được từ việc sử dụng lệnh của bạn : $ cat; echo $? Terminated 143.
kasperd 3/03/2015

2
@Landon Thomas dòng mã của bạn được hiển thị ở đây thực tế trả về 0. Tuy nhiên, process_name đã bị giết KHÔNG trả về 0, đó là điều mà OP muốn.
Daniel

2

Một chút cách hacky, nhưng ..

Bạn có thể tạo một trình bao bọc cho quy trình của mình, ghi đè Trình xử lý SIGCHLD. Ví dụ:

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

Sau đó, bạn có thể làm cho tập lệnh của mình chạy trình bao bọc này thay vì tiến trình của bạn bằng cách đặt nó trước đó bằng $ PATH và đổi tên thành cùng tên.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.