Canalice stderr y stdout a diferentes comandos (no solo a archivos)

11

Estoy haciendo un script de respaldo para ldap. Quiero que los errores vayan a un archivo en / var / log y que la salida vaya a otro archivo en la carpeta de copia de seguridad. Actualmente estoy redirigiendo a un archivo temporal y luego envío el archivo temporal al registro. Sin embargo, prefiero hacer esto como 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

¿Alguna idea sobre cómo redirigir stderr y stdout a diferentes tuberías para condensar este comando en 1 línea? ¿O hay un mejor camino?

Robert
fuente
1
Eche un vistazo a esta demostración: stackoverflow.com/a/16283739/1765658 o esta otra muestra de significado: unix.stackexchange.com/a/84012/27653
F. Hauri

Respuestas:

10

Como lo indica esta respuesta en 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

Rendimientos corrientes:

  • stderr.log 6

  • stdout.log 1

Cazador de ciervos
fuente
24

En Bash, puede usar la sustitución de procesos para administrar los descriptores de archivo adicionales por usted. Puede encontrar esto un poco más ordenado que el método de intercambio de descriptor de archivo.

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

Su comando podría verse más o menos así:

/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" \
  )
Pausado hasta nuevo aviso.
fuente
1
Esta es la respuesta correcta.
Michael Martinez
Es posible que desee redirigir la salida de nuevo a stderr si desea mantener la cadena en lugar de redirigir a un archivo, algo como esto: sh f>> (sed -e "s / ^ / stdout: /") 2>> ( sed -e "s / ^ / stderr: /"> & 2)
James Moore el
¿Cuál es el nombre técnico de la >(process)notación?
jchook
1
@jchook Utilizo el término en la primera oración: "sustitución de proceso".
Pausado hasta nuevo aviso.
1

Así es como imprimo stdout y stderr para separar archivos con marcas de tiempo (canalización a ts desde el paquete Debian moreutils):

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

PD: si no tienes ts, crea tu propio alias:

alias ts='while IFS= read -r line; do printf "%s %s\n" "$(date +%F\ %T)" "$line"; done'
error de servidor interno
fuente