Вопрос:

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

bash unix shell

41466 просмотра

12 ответа

1325 Репутация автора

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

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

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

Автор: user14437 Источник Размещён: 17.09.2008 09:40

Ответы (12)


4 плюса

2470 Репутация автора

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

Автор: Matthias Kestenholz Размещён: 17.09.2008 09:44

16 плюса

8775 Репутация автора

Решение

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

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


РЕДАКТИРОВАТЬ:

Для более уместного ответа проверьте ответ, данный Марком Эдгаром

Автор: wnoise Размещён: 17.09.2008 10:07

0 плюса

9 Репутация автора

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

Автор: clemep Размещён: 28.01.2011 09:04

8 плюса

12175 Репутация автора

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

Автор: MarcH Размещён: 31.01.2011 09:55

118 плюса

3619 Репутация автора

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

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

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

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

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

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

Автор: Mark Edgar Размещён: 19.04.2011 09:22

1 плюс

19 Репутация автора

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

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

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

Автор: Ralph Размещён: 30.08.2012 01:35

1 плюс

151 Репутация автора

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

killall -s SIGINT (yourprogram) 

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

Автор: Coder of Salvation Размещён: 04.11.2012 09:43

15 плюса

1 Репутация автора

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

kill -PIPE

или просто

kill -13
Автор: Steven Penny Размещён: 04.01.2013 06:35

1 плюс

11 Репутация автора

Другой способ отключить уведомления о заданиях - поместить вашу команду в основу 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}"
'
Автор: phily Размещён: 08.03.2013 05:49

0 плюса

39 Репутация автора

Успешно добавил ' 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
Автор: J-o-h-n- Размещён: 07.05.2013 04:34

0 плюса

0 Репутация автора

Просто:

{ kill $! } 2>/dev/null

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

например:

{ kill -9 $PID } 2>/dev/null
Автор: user2429558 Размещён: 23.06.2013 05:31

0 плюса

513 Репутация автора

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

function killCmd() {
    kill $1
}

killCmd $somePID &
Автор: Al Joslin Размещён: 10.02.2018 10:15
32x32