Как подавить завершенное сообщение после убийства в bash?
Как вы можете подавить сообщение Terminated
, которое появляется после того, как вы убили
процесс в bash script?
Я пробовал set +bm
, но это не работает.
Я знаю, что другое решение включает вызов exec 2> /dev/null
, но это
надежны? Как мне вернуть reset, чтобы я мог продолжать видеть stderr?
Ответы
Ответ 1
Короткий ответ заключается в том, что вы не можете. Bash всегда печатает статус заданий переднего плана. Флаг мониторинга применяется только для фоновых заданий и только для интерактивных оболочек, а не для сценариев.
см. notify_of_job_status() в jobs.c.
Как вы говорите, вы можете перенаправить, поэтому стандартная ошибка указывает на /dev/null, но затем вы пропускаете любые другие сообщения об ошибках. Вы можете сделать это временным, выполнив перенаправление в подоболочке, которая запускает script. Это оставляет исходную среду отдельно.
(script 2> /dev/null)
который потеряет все сообщения об ошибках, но только из этого script, а не из чего-либо другого в этой оболочке.
Вы можете сохранить и восстановить стандартную ошибку, перенаправив новый filedescriptor, чтобы указать там:
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
Но я бы не рекомендовал этого - единственный потенциал от первого заключается в том, что он сохраняет вызов под-оболочки, будучи более сложным и, возможно, даже изменяет поведение script, если script изменяет дескрипторы файлов.
EDIT:
Для получения более подходящего ответа на вопрос ответа Mark Edgar
Ответ 2
Чтобы отключить сообщение, вы должны перенаправить stderr
во время создания сообщения. Поскольку команда kill
посылает сигнал и не ждет ответа целевого процесса, перенаправление stderr
команды kill
неужели ты не годишься. Для этой цели был специально создан bash встроенный wait
.
Вот очень простой пример, который убивает самую последнюю команду фона. (Подробнее о $! здесь.
kill $!
wait $! 2>/dev/null
Поскольку оба kill
и wait
принимают несколько pids, вы также можете совершать групповые убийства. Вот пример, который убивает все фоновые процессы (текущего процесса /script, конечно).
kill $(jobs -rp)
wait $(jobs -rp) 2>/dev/null
Меня привел здесь из bash: бесшумно уничтожить фоновый процесс.
Ответ 3
Вдохновленный ответом MarcHs. Я использовал kill -INT
, как он предлагает с некоторым успехом, но я заметил, что он не убивал некоторые процессы. После тестирования некоторых других сигналов я вижу, что SIGPIPE
также будет убит без сообщения.
kill -PIPE
или просто
kill -13
Ответ 4
Решение: используйте 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
Ответ 5
Возможно, отсоедините процесс от текущего процесса оболочки, вызвав disown
?
Ответ 6
Это то, что мы все ищем?
Не требуется:
$ 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' отключает управление заданиями (см. "набор справок" ) для текущей оболочки. Поэтому, если вы вводите свою команду в подоболочку (как это делается здесь в скобках), вы не будете влиять на настройки управления заданиями текущей оболочки. Единственным недостатком является то, что вам нужно вернуть pid вашего фонового процесса в текущую оболочку, если вы хотите проверить, завершилось ли это или оценил код возврата.
Ответ 7
Это также работает для killall (для тех, кто предпочитает это):
killall -s SIGINT (yourprogram)
подавляет сообщение... я запускаю mpg123 в фоновом режиме. Его можно было просто тихо убить, отправив ctrl-c (SIGINT) вместо SIGTERM (по умолчанию).
Ответ 8
Другой способ отключить уведомления о работе - поместить вашу команду в фоновый рисунок в конструкцию 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}"
'
Ответ 9
disown сделал именно то, что мне нужно - exec 3 > & 2 рискован по множеству причин - set + bm, похоже, не работает внутри script, только в командной строке
Ответ 10
Успех с добавлением 'jobs 2>&1 >/dev/null
' к script, не определен, если он поможет кому-либо еще script, но вот пример.
while true; do echo $RANDOM; done | while read line
do
echo Random is $line the last jobid is $(jobs -lp)
jobs 2>&1 >/dev/null
sleep 3
done
Ответ 11
Просто:
{ kill $! } 2>/dev/null
Преимущество? можно использовать любой сигнал
например:
{ kill -9 $PID } 2>/dev/null
Ответ 12
Я обнаружил, что помещение команды kill в функцию, а затем ее фонирование подавляют вывод завершения
function killCmd() {
kill $1
}
killCmd $somePID &