Script Bash – almacena stderr en una variable

Estoy escribiendo una secuencia de comandos para hacer una copia de seguridad de una base de datos. Tengo la siguiente línea:

mysqldump --user=$dbuser --password=$dbpswd \ --host=$host $mysqldb | gzip > $filename 

Quiero asignar el stderr a una variable, de modo que me envíe un correo electrónico para informarme de lo que sucedió si algo sale mal. He encontrado soluciones para redirigir stderr a stdout, pero no puedo hacer eso ya que el stdout ya se está enviando (a través de gzip) a un archivo. ¿Cómo puedo almacenar Stderr por separado en un $ resultado variable?

Intente redirigir stderr a stdout y use $() para capturar eso. En otras palabras:

 VAR=$((your-command-including-redirect) 2>&1) 

Como su comando redirige a stdout a alguna parte, no debería interferir con stderr. Puede haber una manera más limpia de escribirlo, pero eso debería funcionar.

Editar:

Esto realmente funciona Lo he probado

 #!/bin/bash BLAH=$(( ( echo out >&1 echo err >&2 ) 1>log ) 2>&1) echo "BLAH=$BLAH" 

imprimirá BLAH=err y el archivo de log contiene.

Para cualquier comando genérico en Bash, puedes hacer algo como esto:

 { error=$(command 2>&1 1>&$out); } {out}>&1 

La salida normal aparece normalmente, cualquier cosa para stderr se captura en $ error (cúmplalo como “$ error” cuando lo use para preservar las nuevas líneas). Para capturar stdout en un archivo, simplemente agregue una redirección al final, por ejemplo:

 { error=$(ls /etc/passwd /etc/bad 2>&1 1>&$out); } {out}>&1 >output 

Rompiéndolo, leyendo desde afuera, en él:

  • crea una descripción de archivo $ out para todo el bloque, duplicando stdout
  • captura el stdout de todo el comando en $ error (pero mira a continuación)
  • el comando mismo redirige stderr a stdout (que se captura arriba) luego stdout a la stdout original desde fuera del bloque, por lo que solo stderr se captura

Puede guardar la referencia de stdout antes de que se redirija a otro número de archivo (por ejemplo, 3) y luego redirigir stderr a eso:

 result=$(mysqldump --user=$dbuser --password=$dbpswd \ --host=$host $mysqldb 3>&1 2>&3 | gzip > $filename) 

Entonces 3>&1 redirigirán el archivo número 3 a stdout (observe esto antes de que stdout sea redirigido con el conducto). Luego 2>&3 redireccionan stderr al archivo número 3, que ahora es el mismo que stdout. Finalmente, stdout se redirige al alimentarlo a un conducto, pero esto no afecta a los números de archivo 2 y 3 (observe que redireccionar el stdout de gzip no está relacionado con las salidas del comando mysqldump).

Editar: mysqldump el comando para redirigir stderr desde el comando mysqldump y no gzip , fui demasiado rápido en mi primera respuesta.

dd escribe stdout y stderr:

 $ dd if=/dev/zero count=50 > /dev/null 50+0 records in 50+0 records out 

las dos streams son independientes y redirigibles por separado:

 $ dd if=/dev/zero count=50 2> countfile | wc -c 25600 $ cat countfile 50+0 records in 50+0 records out $ mail -s "countfile for you" thornate < countfile 

si realmente necesitabas una variable:

 $ variable=`cat countfile`