Le langage de programmation Crystal n'écrit pas actuellement dans STDERR en cas d'échec de la compilation. J'ai besoin de rediriger STDOUT vers STDERR si le statut de sortie n'est pas 0 et toujours retourner le statut de sortie.Rediriger STDOUT vers STDERR lorsque l'état de sortie n'est pas 0 dans Bash
Répondre
Pris littéralement, votre requête est littéralement impossible: Les redirections sont effectuées avant le démarrage d'une commande, alors que le statut de sortie n'est connu qu'à sa sortie.
Cependant, vous pouvez inconditionnellement rediriger dans un tampon, puis écrire ce tampon soit stdout ou stderr après que l'état de sortie est connu.
Considérons une enveloppe semblable à ce qui suit:
#!/bin/sh
if output=$("[email protected]"); then
printf '%s\n' "$output"
else
retval=$?
printf '%s\n' "$output" >&2
exit "$retval"
fi
... invoquée (si cela est enregistré en tant que stderr-wrapper
):
stderr-wrapper your-program arg1 arg2 ...
C'est tellement génial! Merci beaucoup! Il n'a pas eu d'effets secondaires pour les autres chemins heureux. –
Il ya * une mise en garde ici dans la mesure où ce code va manger des NUL qui pourraient être inclus dans la sortie de votre programme (car les NUL ne peuvent pas être stockées dans les chaînes C, qui bash utilise le stockage en mémoire). Si c'est un problème, vous pouvez écrire dans un fichier. –
Si la sortie attendue est trop importante, un fichier temporaire peut être plus sûr –
méthode de conduite Rond-point, ce qui nécessite tac
et sans danger eval
, mais ni les variables de tampon, ni les fichiers temporaires.
script démonstration demo
, en utilisant echo false ; false
pour simuler un programme qui génère à stdout et renvoie un code d'erreur "".
#!/bin/bash
out=([0]=/dev/stdout [1]=/dev/stderr)
{ { echo $1 ; $1 ; echo $? ; } | tac ; } | \
{ read x ; eval tac \> ${out[$x]} ; exit $x ; }
Preuve, en utilisant annotate-output
:
annotate-output +'' ./demo true ; echo --- ; annotate-output +'' ./demo false
I: Started ./demo true
O: true
I: Finished with exitcode 0
---
I: Started ./demo false
E: false
I: Finished with exitcode 1
Généraliser qui demo
en stderr-wrapper
:
Pour
bash
:#!/bin/bash # Usage: stderr-wrapper program [ args... ] out=([0]=/dev/stdout [1]=/dev/stderr) { { [email protected] ; echo $? ; } | tac ; } | \ { read x ; eval tac \> ${out[$((x>0))]} ; exit $x ; }
Pour POSIX coquilles, (ici il est
dash
):#!/bin/dash # Usage: stderr-wrapper program [ args... ] { { "[email protected]" ; echo $? ; } | tac ; } | \ { read x ; eval tac 1\>\&$(((x>0)+1)) ; exit $x ; }
Comment la version bash
fonctionne:
- Exécutez le programme incriminé, qui sort à stdout .
- Imprimez le code d'erreur juste après, également stdout.
- Inversez le flux entier avec
tac
, le code d'erreur est donc le premier. (Cher si le flux est long.) read
une ligne, le code d'erreur, stocker dans$x
.eval
le membre du groupe$out
qui correspond au périphérique sur lequel la sortie doit aller, puis de revenir en arrière sur la sortie avectac
sur ce périphérique.
Avez-vous essayé 'some_bash_command.sh 2> & 1' – t0mm13b
Les redirections sont exécutées ** avant ** un programme est démarré. Le statut de sortie n'est connu que ** après ** ce programme se termine. Tu ne peux pas remonter le temps. –