it-swarm-ru.tech

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

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

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

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

50
user14437

Короткий ответ: ты не можешь. 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

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


EDIT:

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

16
wnoise

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

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

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

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

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

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

118
Mark Edgar

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

kill -PIPE

или просто

kill -13
15
Steven Penny

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

8
MarcH

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

4
Matthias Kestenholz

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

Нежелательный:

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

1
Ralph

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

killall -s SIGINT (ваша программа)

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

1
Coder of Salvation

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

Просто:

{убить $! } 2>/dev/null

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

например: {kill -9 $ PID} 2>/dev/null

0
user2429558

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

0
clemep

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

function killCmd() {
    kill $1
}

killCmd $somePID &
0
Al Joslin

Успешно добавил '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
0
J-o-h-n-