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 à une variable, afin qu'il m'envoie un e-mail m'informant de ce qui s'est passé en cas de problème. J'ai trouvé des solutions pour rediriger stderr vers stdout, mais je ne peux pas le faire car la stdout est déjà envoyée (via gzip) dans un fichier. Comment puis-je stocker séparément stderr dans un résultat $ variable?
Essayez de rediriger stderr vers stdout et d'utiliser $()
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 façon plus propre de l'écrire, mais cela devrait fonctionner.
Modifier:
Cela fonctionne vraiment. Je l'ai testé:
#!/bin/bash
BLAH=$((
(
echo out >&1
echo err >&2
) 1>log
) 2>&1)
echo "BLAH=$BLAH"
imprimera BLAH=err
et le fichier log
contient out
.
Pour toute commande générique dans Bash, vous pouvez faire quelque chose comme ceci:
{ error=$(command 2>&1 1>&$out); } {out}>&1
La sortie régulière apparaît normalement, tout ce qui est envoyé à stderr est capturé dans $ error (citez-le comme "$ error" lorsque vous l'utilisez pour conserver les retours à la ligne). Pour capturer stdout dans un fichier, ajoutez simplement une redirection à la fin, par exemple:
{ error=$(ls /etc/passwd /etc/bad 2>&1 1>&$out); } {out}>&1 >output
Le décomposer, lire de l'extérieur vers l'intérieur, cela:
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), puis rediriger stderr vers celui-ci:
result=$(mysqldump --user=$dbuser --password=$dbpswd \
--Host=$Host $mysqldb 3>&1 2>&3 | gzip > $filename)
Alors 3>&1
redirigera le fichier numéro 3 vers stdout (notez que c'est avant que stdout soit redirigé avec le tube). Ensuite 2>&3
redirige stderr vers le fichier numéro 3, qui est maintenant le même que stdout. Enfin stdout est redirigé en étant alimenté dans un tube, mais cela n'affecte pas les numéros de fichiers 2 et 3 (notez que la redirection de stdout depuis gzip n'est pas liée aux sorties de la commande mysqldump).
Edit: Mise à jour de la commande pour rediriger stderr à partir 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 réorientables 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 aviez vraiment besoin d'une variable:
$ variable=`cat countfile`