придушити більш строгі повідомлення в баш-скрипті


48

Розглянемо таку (злегка нерозумно) назву сценарію 'test1.sh':

#/bin/bash
#
sleep 10 &
echo sleep pid = $!
pkill sleep

Коли я запускаю його, я отримую не тільки вихід відлуння, але й повідомлення Баша про смерть сну на stderr:

$ ./test1.sh
sleep pid = 3551
./test1.sh: line 5:  3551 Terminated              sleep 10

У цьому випадку я хотів би придушити роздруківку до більш жорсткої. Я знаю, що можу це зробити в командному рядку, як у:

$ ./test1.sh 2> /dev/null

... але чи є спосіб придушити це всередині сценарію? (Я знаю, що я міг би перетворити його у другий сценарій і мати його, щоб обгортка перенаправляла його, але повинно бути щось простіше ...)


ви намагалися додати переспрямування 2> / dev / null після сну pkill?
— rahul

@rahul: так, я зробив - pkill не генерує повідомлення, баш.
— безстрашний_фол

Я використовував kill замість pkill і не отримую більш жорсткий. дивно ..
— rahul

@rahul: чи може це бути вбудованим проти небудованого в речі? Ви пробували і з pkill?
— безстрашний_фул

так, я вірю, що це так. Я отримую ту ж помилку з pkill, але не з kill. Під час використання kill я використав pid замість імені proc.
— rahul

Відповіді:


72

Ти правий; pkill не генерує повідомлення, bash є. Ви пропонуєте це

$ ./test1.sh 2> /dev/null

є можливим рішенням. Як зазначає UVV, еквівалентна дія всередині сценарію є

exec 2> /dev/null

Це перенаправляє stderr для сценарію /dev/null з цього твердження, поки він не буде змінений назад. Незграбні способи зміни його назад включають

exec 2> /dev/tty

який перенаправляє stderr до терміналу. Це, мабуть, (але не обов'язково) там, де воно було спочатку.

Або

exec 2>&1

що встановлює stderr таким же, як і stdout, і, ймовірно, помиляється.

Більш надійний спосіб

exec 3> & 2
exec 2> / dev / null
(робити речі там, де ви не хочете бачити stderr.) 
exec 2> & 3

який зберігає оригінальний stderr у дескрипторі файлів 3, а пізніше відновлює його.

Інші способи придушити лише оголошення смерті процесу включають

(sleep 10 & pkill sleep) 2> /dev/null

і

{ sleep 10 & pkill sleep;} 2> /dev/null

які змінюють stderr лише для згрупованих команд.


Це така чудова, детальна відповідь. Дякую вам сер!
— Кінан Лоуренс

Чи існують якісь небезпеки, пов’язані із збереженням stdinта stderrновими дескрипторами файлів, надсиланням оригінальних дескрипторів, /dev/nullа потім їх відновленням?
— Олексій Магура

Ну, я припускаю, що якщо ви запустили програму, яка (невідомо вам) написала файл дескриптора 3 (або 4), ця операція не відбудеться за звичайних обставин. Але програма може бути написана для того, щоб ігнорувати збій та продовжувати, не повідомляючи про це; тоді ти ніколи не дізнаєшся. Але якщо ваш дескриптор файлу 1 (або 2) був "припаркований" у дескрипторі файлів 3 (або 4), то ця програма раптом запише в stdout або stderr вашого сценарію. Але це дуже надуманий приклад і все ще мінімальна небезпека. Ви щось мали на увазі?
— Скотт

1
FWIW, я віддаю перевагу групованому командному підходу Скотта, тобто{ sleep 10 & pkill sleep;} 2> /dev/null
— безстрашний_фол

9

Згідно з цим ви можете зробити щось на кшталт наступного:

#!/bin/bash
exec 2>/dev/null
ls -al test
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.