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

<p>как вы можете подавить сообщение <code>terminated</code>, которое появляется после завершения процесса в bash-скрипте?</p><p>я пробовал <code>set +bm</code>, но это не работает.</p><p>я знаю, что другое решение включает вызов <code>exec 2> /dev/null</code>, но надежно ли это? как мне сбросить его обратно, чтобы я мог продолжать видеть stderr?</p>

<p>короткий ответ: ты не можешь. bash всегда печатает статус заданий переднего плана. флаг мониторинга применяется только для фоновых заданий и только для интерактивных оболочек, а не сценариев.</p><p>смотрите notify\_of\_job\_status () в jobs.c.</p><p>как вы говорите, вы можете перенаправить так, чтобы стандартная ошибка указывала на/dev/null, но тогда вы пропускаете любые другие сообщения об ошибках. вы можете сделать это временным, выполнив перенаправление в подоболочке, которая запускает скрипт. это оставляет исходную среду в покое.</p><pre><code>(script 2> /dev/null) </code></pre><p>который потеряет все сообщения об ошибках, но только из этого сценария, а не из чего-либо еще, запущенного в этой оболочке.</p><p>вы можете сохранить и восстановить стандартную ошибку, перенаправив новый дескриптор файла, чтобы указать там:</p><pre><code>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 </code></pre><p>но я бы не рекомендовал это - единственный плюс в первом случае - это то, что он сохраняет вызов sub-shell, будучи более сложным и, возможно, даже изменяющим поведение скрипта, если скрипт изменяет дескрипторы файлов.</p><hr><p><strong> edit: </strong></p><p><em> для более подходящего ответа проверьте ответ, заданный <a href="https://stackoverflow.com/users/129332/mark-edgar">марк эдгар</a> </em></p>

<p>чтобы отключить сообщение, вы должны перенаправить <code>stderr</code> <strong> во время создания сообщения </strong>. поскольку команда <a href="http://ss64.com/bash/kill.html"><code>kill</code></a> отправляет сигнал и не ожидает ответа целевого процесса, перенаправление <code>stderr</code> команды <code>kill</code> не поможет. встроенный bash <a href="http://ss64.com/bash/wait.html"><code>wait</code></a> был создан специально для этой цели.</p><p>вот очень простой пример, который убивает самую последнюю фоновую команду. ( <a href="https://stackoverflow.com/a/5163260/117471">подробнее о $! здесь. )kill $! wait $! 2>/dev/null поскольку и kill, и wait принимают несколько pids, вы также можете выполнять пакетные убийства. вот пример, который убивает все фоновые процессы (текущего процесса/сценария, конечно).kill $(jobs -rp) wait $(jobs -rp) 2>/dev/null меня привели сюда из <a href="https://stackoverflow.com/questions/5719030/bash-silently-kill-background-function-process/5722850">bash: молча убить процесс фоновой функции .

вдохновленный <a href="https://stackoverflow.com/a/4849503">ответ марка . я использовал kill -int, как он предполагает, с некоторым успехом, но я заметил, что это не убивает некоторые процессы. после тестирования некоторых других сигналов я вижу, что sigpipe также убьет без сообщения.kill -pipe или простоkill -13 

решение: использовать sigint (работает только в неинтерактивных оболочках)демо-версия:cat > silent.sh <<"eof" sleep 100 & kill -int $! sleep 1 eof sh silent.sh </code></pre><p> <a href="http://thread.gmane.org/gmane.comp.shells.bash.bugs/15798">http://thread.gmane.org/gmane.comp.shells.bash.bugs/15798</a> </p>

<p>может быть, отсоединить процесс от текущего процесса shell, вызвав <code>disown</code>?</p>

<p>это то, что мы все ищем?</p><p>нежелательный:</p><pre><code>$ sleep 3 & [1] 234 <pressing enter a few times....> $ $ [1]+ done sleep 3 $ </code></pre><p>в розыске:</p><pre><code>$ (set +m; sleep 3 &) <again, pressing enter several times....> $ $ $ $ $ </code></pre><p>как видите, сообщения о завершении работы нет. у меня работает и в скриптах bash, и для убитых фоновых процессов.</p><p>'set + m' отключает управление заданиями (см. 'набор справок') для текущей оболочки. поэтому, если вы введете свою команду в подоболочке (как это сделано здесь в скобках), вы не будете влиять на настройки управления заданиями текущей оболочки. единственным недостатком является то, что вам нужно вернуть pid вашего фонового процесса обратно в текущую оболочку, если вы хотите проверить, завершился ли он, или оценить код возврата.</p>

<p>это также работает для killall (для тех, кто предпочитает это):</p><p>killall -s sigint (ваша программа)</p><p>подавляет сообщение .. я запускаю mpg123 в фоновом режиме. его можно было просто тихо убить, отправив ctrl-c (sigint) вместо sigterm (по умолчанию).</p>

<p>другой способ отключить уведомления о заданиях - поместить вашу команду в фоновую конструкцию <code>sh -c 'cmd &'</code>.</p><pre><code>#!/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}" ' </code></pre>

<p>просто:</p><p>{убить $! } 2>/dev/nullпреимущество? можно использовать любой сигналнапример: {kill -9 $ pid} 2>/dev/null</p>

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

<p>я обнаружил, что помещение команды kill в функцию, а затем ее фонирование подавляют вывод завершения</p><pre><code>function killcmd() { kill $1 } killcmd $somepid & </code></pre>

<p>успешно добавил '<code>jobs 2>&1 >/dev/null</code>' в скрипт, не уверен, поможет ли он кому-нибудь еще, но вот пример.</p><pre><code> 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 </code></pre>