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

StackOverflow https://stackoverflow.com/questions/81520

  •  09-06-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

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

смотрите функцию notify_of_job_status() в jobs.c.

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

(script 2> /dev/null)

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

Вы можете сохранить и восстановить стандартную ошибку, перенаправив новый 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

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


Редактировать:

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

Другие советы

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

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

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

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

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

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

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

kill -PIPE

или просто

kill -13

Решение:используйте 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

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

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

Нежеланный:

$ 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 вашего фонового процесса обратно в текущую оболочку, если вы хотите проверить, был ли он завершен, или оценить код возврата.

Другой способ отключить уведомления о заданиях - поместить вашу команду в качестве фона в 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}"
'

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

killall -s SIGINT (yourprogram) 

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

disown поступил совершенно правильно для меня - exec 3> & 2 рискован по многим причинам - set + bm, похоже, не работал внутри скрипта, только в командной строке

Добился успеха с добавлением 'jobs 2>&1 >/dev/null что касается сценария, не уверен, поможет ли это чьему-либо другому сценарию, но вот пример.

    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

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

function killCmd() {
    kill $1
}

killCmd $somePID &

Простой:

{ kill $! } 2>/dev/null

Преимущество?может использовать любой сигнал

бывший:

{ kill -9 $PID } 2>/dev/null
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top