Как подавить прекращение сообщения после убийства в bash? - PullRequest
50 голосов
/ 17 сентября 2008

Как вы можете подавить сообщение Terminated, которое появляется после того, как вы убили процесс в скрипте bash?

Я пытался set +bm, но это не работает.

Я знаю, что другое решение предполагает вызов exec 2> /dev/null, но надежны? Как мне вернуть его обратно, чтобы я мог продолжать видеть stderr?

Ответы [ 12 ]

118 голосов
/ 20 апреля 2011

Чтобы отключить сообщение, вы должны перенаправить stderr во время создания сообщения . Поскольку команда kill отправляет сигнал и не ожидает ответа целевого процесса, перенаправление stderr команды kill не принесет вам пользы. Встроенный bash wait был создан специально для этой цели.

Вот очень простой пример, который убивает самую последнюю фоновую команду. ( Узнайте больше о $! Здесь. )

kill $!
wait $! 2>/dev/null

Поскольку и kill, и wait принимают несколько пидов, вы также можете делать групповые убийства. Вот пример, который убивает все фоновые процессы (конечно, текущего процесса / сценария).

kill $(jobs -rp)
wait $(jobs -rp) 2>/dev/null

Меня привели сюда из bash: молча убить процесс фоновой функции .

16 голосов
/ 17 сентября 2008

Короткий ответ: ты не можешь. Bash всегда печатает статус заданий переднего плана. Флаг мониторинга применяется только для фоновых заданий и только для интерактивных оболочек, а не сценариев.

см. Notify_of_job_status () в jobs.c.

Как вы говорите, вы можете перенаправить так, чтобы стандартная ошибка указывала на / dev / null, но тогда вы пропускаете любые другие сообщения об ошибках. Вы можете сделать это временным, выполнив перенаправление в подоболочке, которая запускает скрипт. Это оставляет исходную среду в одиночестве.

(script 2> /dev/null)

, что приведет к потере всех сообщений об ошибках, но только из этого скрипта, а не из чего-либо еще, запущенного в этой оболочке.

Вы можете сохранить и восстановить стандартную ошибку, перенаправив новый дескриптор файла, указав туда:

exec 3>&2          # 3 is now a copy of 2
exec 2> /dev/null  # 2 now points to /dev/null
script             # run script with redirected stderr
exec 2>&3          # restore stderr to saved
exec 3>&-          # close saved version

Но я бы не рекомендовал это - единственный плюс в первом - это то, что он сохраняет вызов под-оболочки, хотя и более сложный и, возможно, даже изменяет поведение скрипта, если скрипт изменяет дескрипторы файлов .


EDIT:

Для более подходящего ответа проверьте ответ, заданный Марк Эдгар

15 голосов
/ 04 января 2013

Вдохновленный ответом MarcH . Я использовал kill -INT, как он предполагает, с некоторым успехом, но я заметил, что это не убивает некоторые процессы. После тестирования некоторых других сигналов я вижу, что SIGPIPE также убьет без сообщения.

kill -PIPE

или просто

kill -13
8 голосов
/ 31 января 2011

Решение: используйте SIGINT (работает только в неинтерактивных оболочках)

Демо-версия:

cat > silent.sh <<"EOF"
sleep 100 &
kill -INT $!
sleep 1
EOF

sh silent.sh

http://thread.gmane.org/gmane.comp.shells.bash.bugs/15798

4 голосов
/ 17 сентября 2008

Может быть, отсоединить процесс от текущего процесса оболочки, вызвав disown?

1 голос
/ 08 марта 2013

Другой способ отключить уведомления о заданиях - поместить вашу команду в основу sh -c 'cmd &'.

#!/bin/bash
# ...
pid="`sh -c 'sleep 30 & echo ${!}' | head -1`"
kill "$pid"
# ...

# or put several cmds in sh -c '...' construct
sh -c '
sleep 30 &
pid="${!}"
sleep 5 
kill "${pid}"
'
1 голос
/ 05 ноября 2012

Это также работает для killall (для тех, кто предпочитает это):

killall -s SIGINT (yourprogram) 

подавляет сообщение ... Я запускаю mpg123 в фоновом режиме. Его можно было просто тихо убить, отправив Ctrl-C (SIGINT) вместо SIGTERM (по умолчанию).

1 голос
/ 30 августа 2012

Это то, что мы все ищем?

Не хотел:

$ sleep 3 &
[1] 234
<pressing enter a few times....>
$
$
[1]+  Done                    sleep 3
$

Требуются:

$ (set +m; sleep 3 &)
<again, pressing enter several times....>
$
$
$
$
$

Как видите, сообщения о завершении работы нет. У меня работает и в скриптах bash, и для убитых фоновых процессов.

'set + m' отключает управление заданиями (см. 'Help set') для текущей оболочки. Поэтому, если вы введете свою команду в подоболочке (как здесь сделано в скобках), вы не будете влиять на настройки управления заданиями текущей оболочки. Единственным недостатком является то, что вам нужно вернуть pid вашего фонового процесса обратно в текущую оболочку, если вы хотите проверить, завершился ли он, или оценить код возврата.

0 голосов
/ 11 февраля 2018

Я обнаружил, что помещение команды kill в функцию, а затем ее фонирование подавляют вывод завершения

function killCmd() {
    kill $1
}

killCmd $somePID &
0 голосов
/ 23 июня 2013

Simple:

{ kill $! } 2>/dev/null

Advantage? можно использовать любой сигнал

например:

{ kill -9 $PID } 2>/dev/null
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...