Zabić proces i zmusić go do zwrócenia 0 w systemie Linux?


16

Jak w środowisku Linux mogę wysłać sygnał zabicia do procesu, upewniając się, że kod wyjścia zwrócony z tego procesu wynosi 0? Czy musiałbym wykonać w tym celu jakąś fantazyjną magię GDB, czy może jest jakiś fantazyjny sygnał zabicia, którego nie jestem świadomy?

Przypadek testowy:

cat; echo $?

killall cat

Próbowanie różnych sygnałów zabicia oferuje tylko różne sygnały powrotu, takie jak 129, 137 i 143. Moim celem jest zabicie procesu uruchamianego przez skrypt, ale sprawienie, by skrypt uznał, że się powiódł.

Odpowiedzi:


20

Możesz dołączyć do procesu za pomocą GDB i identyfikatora procesu, a następnie wydać callpolecenie exit(0)jako argument.

callpozwala na wywoływanie funkcji w ramach uruchomionego programu. Wywołanie exit(0)kończy pracę z kodem powrotu 0.

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

Program exited normally.

Jako narzędzie jednowierszowe:

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

To nie będzie działać, jeśli program nie korzysta (g) libc, na przykład program napisany w montażu: No symbol table is loaded. Use the "file" command. Chociaż jest to bardzo mało prawdopodobne.
Cristian Ciupitu

Pracowałem nad skryptem rubinowym :-D
Michaił

1
@CristianCiupitu Istnieje sposób na obejście tego problemu. Po wejściu do następnego wywołania systemowego wystarczy zmodyfikować odpowiednie rejestry, aby program docelowy wywołał wywołanie _exitsystemowe 0jako argument. Będzie to działać na każdym procesie, który nie jest po prostu zapętleniem i spaleniem cykli procesora. Jeśli proces nie utknie w nieskończonej pętli, nadal możesz zastosować to samo podejście, jeśli możesz znaleźć niezbędne instrukcje gdzieś w jego pliku wykonywalnym i wskazać tam wskaźnik instrukcji.
kasperd

@ Michaił działał na „skrypcie ruby”, ponieważ GDB był połączony z procesem interpretera ruby, którego plik binarny był powiązany z glibc.
Daniel

@kasperd, tak, tak myślałem, ale bardziej dokładne instrukcje byłyby fajne.
Cristian Ciupitu,

8

Nie. Gdy powłoka zostanie złapana SIGCHLD, bezwarunkowo ustawia wartość zwracaną odpowiednio na wartość niezerową, więc wymagałoby to modyfikacji skryptu lub powłoki.


3

Nie jestem pewien, ale to zakończy się z 0, jeśli którykolwiek z wymienionych sygnałów zostanie odebrany. Możesz wykonywać inne czynności, w tym wywoływać funkcję itp.

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

3

Ten liner działał dla mnie:

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

Nie sądzę, że zrozumiałeś pytanie. Nie ma mowy, aby to polecenie osiągnęło to, o co proszono. To co mam z użyciem polecenia: $ cat; echo $? Terminated 143.
kasperd

2
@Landon Thomas, twoja linia kodu pokazana tutaj faktycznie zwraca 0. Jednak nazwa_procesu, która została zabita, NIE zwraca 0, czego chciał OP.
Daniel

2

Trochę hacky sposób, ale ...

Możesz utworzyć opakowanie dla swojego procesu, zastępując moduł obsługi SIGCHLD. Na przykład:

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

Następnie możesz ustawić skrypt uruchamiający to opakowanie zamiast procesu, umieszczając go wcześniej w $ PATH i zmieniając jego nazwę na tę samą nazwę.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.