Подтвердить что ты не робот

Как подавить завершенное сообщение после убийства в bash?

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

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

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

4b9b3361

Ответ 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 &