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?


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


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" \
  )

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'
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.