Dirigez stderr et stdout vers différentes commandes (pas seulement vers des fichiers)

11

Je fais un script de sauvegarde pour LDAP. Je veux que les erreurs aillent dans un fichier dans / var / log et la sortie dans un autre fichier dans le dossier de sauvegarde. Actuellement, je redirige vers un fichier temporaire, puis j'envoie le fichier temporaire au journal. Je préfère cependant le faire en 1 doublure ...

/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

Des idées sur la façon de rediriger stderr et stdout vers différents tuyaux pour condenser cette commande en 1 ligne? Ou existe-t-il une meilleure façon?

Robert
la source
1
Jetez un œil à cette démonstration: stackoverflow.com/a/16283739/1765658 ou cet autre exemple de signification: unix.stackexchange.com/a/84012/27653
F. Hauri

Réponses:

10

Comme indiqué par cette réponse à Unix SE:

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

Rendements courants:

  • stderr.log 6

  • stdout.log 1

Chasseur de cerf
la source
24

Dans Bash, vous pouvez utiliser la substitution de processus pour gérer les descripteurs de fichiers supplémentaires pour vous. Vous pouvez trouver cela un peu plus net que la méthode d'échange de descripteurs de fichiers.

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

Votre commande pourrait ressembler à ceci:

/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" \
  )
En pause jusqu'à nouvel ordre.
la source
1
Ceci est la bonne réponse.
Michael Martinez
Vous voudrez peut-être rediriger la sortie vers stderr si vous souhaitez conserver la chaîne au lieu de rediriger vers un fichier, quelque chose comme ceci: sh f>> (sed -e "s / ^ / stdout: /") 2>> ( sed -e "s / ^ / stderr: /"> & 2)
James Moore
Quel est le nom technique de la >(process)notation?
jchook
1
@jchook J'utilise le terme dans la première phrase: "substitution de processus".
pause jusqu'à nouvel ordre.
1

Voici comment j'imprime stdout et stderr pour séparer les fichiers avec des horodatages (piping to ts depuis le paquet Debian moreutils):

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

PS si vous n'avez pas ts, faites votre propre alias:

alias ts='while IFS= read -r line; do printf "%s %s\n" "$(date +%F\ %T)" "$line"; done'
Erreur Interne du Serveur
la source