Bash script-stocker stderr dans une variable [dupliquer]
cette question a déjà une réponse ici:
j'écris un script pour sauvegarder une base de données. J'ai la ligne suivante:
mysqldump --user=$dbuser --password=$dbpswd
--host=$host $mysqldb | gzip > $filename
je veux assigner le stderr à un variable, de sorte qu'il va envoyer un email à moi-même me faire savoir ce qui s'est passé si quelque chose va mal. J'ai trouvé des solutions pour rediriger stderr vers stdout, mais je ne peux pas le faire car stdout est déjà envoyé (via gzip) vers un fichier. Comment puis-je stocker séparément stderr dans une variable $result ?
4 réponses
essayez de rediriger stderr vers stdout et utilisez $()
pour capturer cela. En d'autres termes:
VAR=$((your-command-including-redirect) 2>&1)
puisque votre commande redirige stdout quelque part, elle ne devrait pas interférer avec stderr. Il pourrait y avoir une manière plus propre de l'écrire, mais cela devrait fonctionner.
Edit:
ça marche vraiment. Je l'ai testé:
#!/bin/bash
BLAH=$((
(
echo out >&1
echo err >&2
) 1>log
) 2>&1)
echo "BLAH=$BLAH"
imprime BLAH=err
et le le fichier log
contient out
.
pour toute commande générique en Bash, vous pouvez faire quelque chose comme ceci:
{ error=$(command 2>&1 1>&$out); } {out}>&1
sortie régulière apparaît normalement, tout à stderr est capturé dans $error (citez-le comme "$error" en l'utilisant pour préserver newlines). Pour capturer stdout dans un fichier, il suffit d'ajouter une redirection à la fin, par exemple:
{ error=$(ls /etc/passwd /etc/bad 2>&1 1>&$out); } {out}>&1 >output
en décomposant, à la lecture de l'extérieur, c':
- crée une description de fichier $out pour l'ensemble du bloc, dupliquer stdout
- capture le stdout de toute la commande en $ error (mais voir ci-dessous)
- la commande elle-même redirige stderr vers stdout (qui est capturé ci-dessus) puis stdout vers le stdout original depuis l'extérieur du bloc, donc seul le stderr est capturé
vous pouvez enregistrer la référence stdout avant qu'elle ne soit redirigée dans un autre numéro de fichier (par exemple 3) et ensuite rediriger stderr à cela:
result=$(mysqldump --user=$dbuser --password=$dbpswd \
--host=$host $mysqldb 3>&1 2>&3 | gzip > $filename)
donc 3>&1
redirigera le fichier Numéro 3 vers stdout (notez que c'est avant que stdout soit redirigé avec le tuyau). Puis 2>&3
redirige stderr vers le fichier numéro 3, qui est maintenant le même que stdout. Enfin stdout est redirigé en étant introduit dans un tuyau, mais cela n'affecte pas les numéros de fichiers 2 et 3 (avis que la redirection de stdout à partir de gzip n'est pas liée aux sorties de la commande mysqldump).
Edit: mise à jour de la commande pour rediriger stderr de la commande mysqldump
et non gzip
, j'ai été trop rapide dans ma première réponse.
dd
écrit à la fois stdout et stderr:
$ dd if=/dev/zero count=50 > /dev/null
50+0 records in
50+0 records out
les deux flux sont indépendants et peuvent être redirigés séparément:
$ 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 vous avez vraiment besoin d'une variable:
$ variable=`cat countfile`