GNU/Linux >> Znalost Linux >  >> Linux

Přes filtr veďte pouze STDERR

TL;DR:

$ cmd 2> >(stderr-filter >&2)

Příklad:

% cat /non-existant 2> >(tr o X >&2)
cat: /nXn-existant: NX such file Xr directXry
%

To bude fungovat v bash i zsh. Bash je v dnešní době do značné míry všudypřítomný, pokud však opravdu potřebujete (opravdu drsné) řešení pro POSIX sh , pak se podívejte sem.

Vysvětlení

Zdaleka nejjednodušší způsob, jak toho dosáhnout, je přesměrovat STDERR prostřednictvím substituce procesu:

Substituce procesu umožňuje odkazovat na vstup nebo výstup procesu pomocí názvu souboru. Má podobu

>(list)

Seznam procesů běží asynchronně a jeho vstup nebo výstup se zobrazí jako název souboru.

Takže to, co získáte substitucí procesu, je název souboru.

Stejně jako vy:

$ cmd 2> filename

můžete udělat

$ cmd 2> >(filter >&2)

>&2 přesměrování filter 's STDOUT zpět na původní STDERR.


TL;DR:(bash a zsh)

$ cmd 2> >(stderr-filter >&2)

Příklad:

% cat /non-existant 2> >(tr o X >&2)
cat: /nXn-existant: NX such file Xr directXry
%

Mnoho odpovědí v síti StackExchange má tvar:

cat /non-existant 3>&1 1>&2 2>&3 3>&- | sed 's/e/E/g'

To má vestavěný předpoklad:že deskriptor souboru 3 se nepoužívá pro něco jiného.

Místo toho použijte pojmenovaný deskriptor souboru a {ba,z}sh přidělí další dostupný deskriptor souboru>=10:

cat /non-existant {tmp}>&1 1>&2 2>&$tmp {tmp}>&- | sed 's/e/E/g'

Všimněte si, že POSIX sh nepodporuje deskriptory pojmenovaných souborů .

Dalším problémem s výše uvedeným je, že příkaz nelze převést na další příkazy bez opětovného přehození STDOUT a STDERR zpět na jejich původní hodnoty.

Chcete-li povolit další potrubí v POSIX sh , (a stále za předpokladu, že FD 3 nepoužívá) se to komplikuje:

(cmd 2>&1 >&3 3>&- | stderr-filter >&2 3>&-) 3>&1

Takže vzhledem k předpokladu a drsné syntaxi toho budete pravděpodobně lépe používat jednodušší bash /zsh syntaxe zobrazená v TL;DR výše a vysvětlená zde.

praktická ukázka, grepping pouze stderr:

$ ls -l . noexistABC noexistXYZ
ls: cannot access 'noexistABC': No such file or directory
ls: cannot access 'noexistXYZ': No such file or directory
.:
total 4
-rw-rw-r-- 1 frank frank    0 Aug 19 12:26 bar.txt
-rw-rw-r-- 1 frank frank    0 Aug 19 12:26 foo.txt
drwxrwxr-x 2 frank frank 4096 Aug 19 12:26 someFolder


$ ( ls -l . noexistABC noexistXYZ 2>&1 >&3 3>&- | grep ABC >&2 3>&-) 3>&1
.:
ls: cannot access 'noexistABC': No such file or directory
total 4
-rw-rw-r-- 1 frank frank    0 Aug 19 12:26 bar.txt
-rw-rw-r-- 1 frank frank    0 Aug 19 12:26 foo.txt
drwxrwxr-x 2 frank frank 4096 Aug 19 12:26 someFolder

Zde je příklad, modelovaný podle toho, jak zaměnit deskriptory souborů v bash . Výstup a.out je následující, bez předpony 'STDXXX:'.

STDERR: stderr output
STDOUT: more regular

./a.out 3>&1 1>&2 2>&3 3>&- | sed 's/e/E/g'
more regular
stdErr output

Cituji z výše uvedeného odkazu:

  1. Nejprve uložte stdout jako &3 (&1 je duplikováno do 3)
  2. Další odešlete stdout na stderr (&2 je duplikováno do 1)
  3. Odeslat stderr na &3 (stdout) (&3 je duplikováno do 2)
  4. zavřít &3 (&- je duplikováno do 3)

Zdá se, že naivní použití substituce procesů umožňuje filtrování stderr odděleně od stdout :

:; ( echo out ; echo err >&2 ) 2> >( sed s/^/e:/ >&2 )
out
e:err

Všimněte si, že stderr vyjde na stderr a stdout na stdout , což můžeme vidět tak, že to celé zabalíme do jiného subshell a přesměrujeme na soubory o a e

( ( echo out ; echo err >&2 ) 2> >( sed s/^/e:/ >&2 ) ) 1>o 2>e

Linux
  1. Nechat Tail -f vyjet na prasklé potrubí?

  2. Jak přesměrovat pouze Stderr?

  3. Najít pouze cíl Symlinku?

  1. Jak převést příkazy do libovolného terminálu?

  2. Jak filtrovat protokol Dmesg, abyste viděli pouze chyby?

  3. Zobrazit na obrazovce pouze Stderr, ale zapsat do souboru Stdout i Stderr?

  1. Shell:přesměrujte stdout na /dev/null a stderr na stdout

  2. Směrujte pouze konkrétní provoz přes VPN

  3. Napájet veškerý provoz přes OpenVPN pouze pro konkrétní síťový jmenný prostor