Убить процесс и заставить его вернуть 0 в Linux?

16

В среде Linux, как я могу отправить сигнал уничтожения процессу, убедившись, что код выхода, возвращаемый этим процессом, равен 0? Должен ли я сделать для этого какую-нибудь причудливую магию GDB, или есть какой-нибудь причудливый сигнал убийства, о котором я не знаю?

Прецедент:

cat; echo $?

killall cat

Попытка различных сигналов уничтожения дает только разные обратные сигналы, такие как 129, 137 и 143. Моя цель - убить процесс, который запускается сценарием, но заставить сценарий думать, что он был успешным.

sega01
источник

Ответы:

20

Вы можете присоединиться к процессу, используя GDB и идентификатор процесса, а затем выполнить callкоманду exit(0)в качестве аргумента.

callпозволяет вызывать функции внутри запущенной программы. Вызов exit(0)выходов с кодом возврата 0.

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

Program exited normally.

Как однострочный инструмент:

gdb --batch --eval-command 'call exit(0)' --pid <process id>
LeStarke
источник
Это не будет работать , если программа не использует (г) Libc, например, программа , записанная в сборе: No symbol table is loaded. Use the "file" command. Хотя это маловероятно.
Кристиан Чиупиту
Работал над рубиновым сценарием :-D
Михаил
1
@CristianCiupitu Есть способ обойти эту проблему. При входе в следующий системный вызов просто измените соответствующие регистры, чтобы целевая программа вызывала _exitсистемный вызов в 0качестве аргумента. Это будет работать с любым процессом, который не просто зацикливает и записывает циклы процессора. Если процесс не застрял в бесконечном цикле, вы все равно можете использовать тот же подход, если вы можете найти необходимые инструкции где-нибудь в его исполняемом файле и указать указатель инструкции там.
Касперд
@Mikhail, он работал над "сценарием ruby", потому что GDB был связан с процессом интерпретатора ruby, бинарный файл которого был связан с glibc.
Даниэль
@kasperd, да, хотя я и так, но более точные инструкции были бы хорошими.
Кристиан Чиупиту
8

Нет. Когда оболочка перехватывает, SIGCHLDона безоговорочно устанавливает возвращаемое значение ненулевым значением, так что это потребует модификации либо скрипта, либо оболочки.

Игнасио Васкес-Абрамс
источник
3

Я не уверен, но это завершится с 0, если какой-либо из перечисленных сигналов будет получен. Вы можете выполнять другие действия, включая вызов функции и т. Д.

#!/bin/bash 
trap 'exit 0' SIGINT SIGQUIT SIGTERM
TBI Infotech
источник
3

Этот однострочник работал для меня:

/bin/bash -c '/usr/bin/killall -q process_name; exit 0'
Лэндон Томас
источник
Я не думаю, что вы поняли вопрос. Нет способа, чтобы эта команда достигла того, о чем просили. Это то , что я получил от использования вашей команды: $ cat; echo $? Terminated 143.
Касперд
2
@Landon Thomas, ваша строка кода, показанная здесь, на самом деле возвращает 0. Однако уничтоженное имя процесса НЕ возвращает 0, чего и хотел ОП.
Даниил
2

Немного хакерский путь, но ..

Вы можете создать оболочку для вашего процесса, переопределяя SIGCHLD Handler. Например:

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

После этого вы можете заставить свой скрипт запускать эту оболочку вместо процесса, поместив его ранее в $ PATH и переименовав в то же имя.

DukeLion
источник