Pipe stderr und stdout zu verschiedenen Befehlen (nicht nur zu Dateien)

11

Ich mache ein Backup-Skript für ldap. Ich möchte, dass die Fehler in eine Datei in / var / log und die Ausgabe in eine andere Datei im Sicherungsordner verschoben werden. Derzeit leite ich zu einer temporären Datei um und sende die temporäre Datei dann an das Protokoll. Ich mache das aber lieber als 1 Liner ...

/usr/bin/ldapsearch -x -LLL -b "dc=contoso,dc=com" "(objectclass=*)" -h ldap.server -v 2>>/tmp/ldaptmp.err |
  gzip -c > /mnt/backups/ldap/`date +\%Y\%m\%d`.ldif.gz || 
  logger -t ldapbackup -p local6.err error exit $?

cat /tmp/ldaptmp.err | grep -v "ldap_initialize( ldap://ldap.server )" | 
  grep -v "filter: (objectclass=\*)" |
  grep -v "requesting: All userApplication attributes" >$ERR_LOG
rm -f /tmp/ldaptmp.err

Irgendwelche Ideen, wie man stderr und stdout in verschiedene Pipes umleitet, um diesen Befehl in einer Zeile zusammenzufassen? Oder gibt es einen besseren Weg?

Robert
quelle
1
Schauen Sie sich diese Demonstration an: stackoverflow.com/a/16283739/1765658 oder dieses andere Bedeutungsbeispiel: unix.stackexchange.com/a/84012/27653
F. Hauri

Antworten:

10

Wie aus dieser Antwort bei Unix SE hervorgeht:

MyWeirdCommand.sh

#!/bin/bash
echo "1 2   3"
echo "4 5   6" >&2

testRedirection.sh:

#!/bin/bash
(./MyWeirdCommand.sh | cut -f1 >stdout.log) 3>&1 1>&2 2>&3 | cut -f3 >stderr.log

Laufende Erträge:

  • stderr.log 6

  • stdout.log 1

Hirschjäger
quelle
24

In Bash können Sie die Prozessersetzung verwenden, um die zusätzlichen Dateideskriptoren für Sie zu verwalten. Möglicherweise sieht dies etwas ordentlicher aus als die Dateideskriptor-Austauschmethode.

command > >(process_stdout) 2> >(process_stderr)

Ihr Befehl könnte ungefähr so ​​aussehen:

/usr/bin/ldapsearch -x -LLL -b "dc=contoso,dc=com" "(objectclass=*)" -h ldap.server -v \
  > >( \
    gzip -c > /mnt/backups/ldap/$(date '+%Y%m%d').ldif.gz || 
    logger -t ldapbackup -p local6.err error exit $?
  ) \
  2> >( \
    grep -Ev "ldap_initialize( ldap://ldap.server )|filter: (objectclass=\*)|requesting: All userApplication attributes" > "$err_log" \
  )
Bis auf weiteres angehalten.
quelle
1
Dies ist die richtige Antwort.
Michael Martinez
Möglicherweise möchten Sie die Ausgabe zurück zu stderr umleiten, wenn Sie die Kette beibehalten möchten, anstatt sie in eine Datei umzuleiten: sh f >> (sed -e "s / ^ / stdout: /") 2 >> ( sed -e "s / ^ / stderr: /"> & 2)
James Moore
Wie lautet der technische Name für die >(process)Notation?
Jchook
1
@jchook Ich benutze den Begriff im ersten Satz: "Prozesssubstitution".
Bis auf weiteres angehalten.
1

So drucke ich stdout und stderr, um Dateien mit Zeitstempeln zu trennen (Weiterleitung an ts aus dem Debian moreutils-Paket):

(./my_little_script.pl | ts %F\ %T > out.log) 2>&1 | ts > err.log

PS Wenn Sie keine ts haben, erstellen Sie Ihren eigenen Alias:

alias ts='while IFS= read -r line; do printf "%s %s\n" "$(date +%F\ %T)" "$line"; done'
interner Serverfehler
quelle