sopprime i messaggi stderr in uno script bash


49

Prendi in considerazione il seguente (leggermente stupido) nome dello script 'test1.sh':

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

Quando lo eseguo, ottengo non solo l'output dell'eco, ma il resoconto di Bash della morte del sonno su stderr:

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

In questo caso, vorrei sopprimere la stampa su stderr. So che posso farlo dalla riga di comando, come in:

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

... ma c'è un modo per sopprimere dal all'interno dello script? (So ​​che potrei inserirlo in un secondo script e fare in modo che il wrapper lo reindirizzi, ma deve esserci qualcosa di più facile ...)


hai provato ad aggiungere il reindirizzamento 2> / dev / null dopo la sospensione di pkill?
rahul,

@rahul: sì, l'ho fatto - pkill non sta generando il messaggio, bash lo è.
fearless_fool

Ho usato kill invece di pkill e non ho preso lo stderr. strano ..
rahul,

@rahul: potrebbe essere una cosa incorporata vs non incorporata? L'hai provato anche con pkill?
fearless_fool

si, credo di si. Ottengo lo stesso errore con pkill, ma non con kill. Durante l'utilizzo di kill, ho usato il pid invece del nome proc.
rahul,

Risposte:


73

Hai ragione; pkill non sta generando il messaggio, bash lo è. Lo suggerisci

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

è una possibile soluzione. Come sottolinea UVV, l'azione equivalente all'interno dello script è

exec 2> /dev/null

Questo reindirizza lo standard per lo script /dev/null da questa istruzione fino a quando non viene ripristinato. I modi goffi di cambiarlo indietro includono

exec 2> /dev/tty

che reindirizza stderr al terminale. Questo è probabilmente (ma non necessariamente) dove era originariamente.

O

exec 2>&1

che imposta stderr allo stesso modo di stdout ed è probabile che sia sbagliato.

Un modo più affidabile è

exec 3> & 2
exec 2> / dev / null
(fai cose dove non vuoi vedere lo stderr.) 
exec 2> & 3

che salva lo stderr originale nel descrittore di file 3 e successivamente lo ripristina.

Altri modi per sopprimere solo l'annuncio della morte del processo includono

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

e

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

che cambia lo stderr solo per i comandi raggruppati.


Questa è una risposta così grande e dettagliata. Grazie Signore!
Keenan Lawrence,

Esistono pericoli associati al salvataggio stdine stderrai nuovi descrittori di file, all'invio dei descrittori originali /dev/nulle al loro ripristino?
Alexej Magura,

Bene, suppongo che, se avessi eseguito un programma che (a tua insaputa) ha scritto sul descrittore di file 3 (o 4), tale operazione fallirebbe in circostanze normali. Ma il programma potrebbe essere scritto per ignorare l'errore e continuare senza segnalarlo; allora non lo sapresti mai. Ma se il tuo descrittore di file 1 (o 2) fosse “parcheggiato” sul descrittore di file 3 (o 4), quel programma improvvisamente scriverà sullo stdout o sullo stderr del tuo script. Ma questo è un esempio molto ingegnoso e un pericolo ancora minimo. Avevi in ​​mente qualcosa?
Scott,

1
FWIW, preferisco l'approccio di comando raggruppato di Scott, vale a dire{ sleep 10 & pkill sleep;} 2> /dev/null
fearless_fool il

9

In base a ciò potresti fare qualcosa del tipo:

#!/bin/bash
exec 2>/dev/null
ls -al test
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.