Existe-t-il un outil Bash standard qui agit comme un écho mais génère des sorties sur stderr plutôt que sur stdout?
Je sais que je peux faire echo foo 1>&2
mais c’est un peu moche et, je suppose, sujet à des erreurs (par exemple, plus susceptible d’être mal édité lorsque les choses changent).
Cette question est ancienne, mais vous pouvez le faire, ce qui facilite la lecture:
>&2 echo "error"
L'opérateur >&2
signifie littéralement rediriger l'adresse du descripteur de fichier 1 (stdout
) vers l'adresse du descripteur de fichier 2 (stderr
) pour cette commande.1. Selon le degré de compréhension souhaité, lisez ceci: http://wiki.bash-hackers.org/howto/redirection_tutorial
Pour éviter les interactions avec d’autres redirections, utilisez subshell
(>&2 echo "error")
1>&2
copie le descripteur de fichier n ° 2 dans le descripteur de fichier n ° 1. Par conséquent, une fois cette redirection effectuée, les deux descripteurs de fichier feront référence au même fichier: le descripteur de fichier n ° 2 se rapportait à originellement.
Vous pouvez définir une fonction:
echoerr() { echo "$@" 1>&2; }
echoerr hello world
Cela serait plus rapide qu'un script et n'aurait aucune dépendance.
La suggestion spécifique de bash de Camilo Martin utilise une "chaîne ici" et affiche tout ce que vous lui transmettez, y compris les arguments (-n) que l'écho avalera normalement:
echoerr() { cat <<< "$@" 1>&2; }
La solution de Glenn Jackman évite également le problème de déglutition des arguments:
echoerr() { printf "%s\n" "$*" >&2; }
Puisque 1
est la sortie standard, vous n'avez pas à la nommer explicitement devant une redirection de sortie telle que >
, mais vous pouvez simplement taper:
echo Ce message est envoyé à stderr> & 2
Puisque vous semblez craindre qu'il soit difficile pour 1>&2
de taper de manière fiable, l'élimination du 1
redondant pourrait être un léger encouragement!
Une autre option
echo foo >>/dev/stderr
Non, c'est la façon habituelle de le faire. Cela ne devrait pas causer d'erreurs.
Il s'agit d'une simple fonction STDERR, qui redirige l'entrée du tuyau vers STDERR.
#!/bin/bash
# *************************************************************
# This function redirect the pipe input to STDERR.
#
# @param stream
# @return string
#
function STDERR () {
cat - 1>&2
}
# remove the directory /bubu
if rm /bubu 2>/dev/null; then
echo "Bubu is gone."
else
echo "Has anyone seen Bubu?" | STDERR
fi
# run the bubu.sh and redirect you output
Tux@earth:~$ ./bubu.sh >/tmp/bubu.log 2>/tmp/bubu.err
Si cela ne vous dérange pas de consigner le message également dans syslog, la méthode not_so_ugly est:
logger -s $msg
L'option -s signifie: "Envoie le message à l'erreur standard et au journal système."
N'utilisez pas cat
car certains sont mentionnés ici. cat
est un programme tandis que echo
et printf
sont des commandes intégrées bash (Shell). Lancer un programme ou un autre script (également mentionné ci-dessus) signifie créer un nouveau processus avec tous ses coûts. En utilisant les fonctions intégrées, les fonctions d'écriture sont relativement peu coûteuses, car il n'est pas nécessaire de créer (exécuter) un processus (-environnement).
L'opérateur demande "existe-t-il un outil standard permettant de générer ( pipe ) vers stderr", la réponse schort est: NON ... pourquoi? ... rediredcting pipes est un concept essentiel dans des systèmes comme unix (Linux ...) et bash (sh), construit sur ces concepts.
Je suis d'accord avec l'ouvreur que rediriger avec des notations comme celle-ci: &2>1
n'est pas très agréable pour les programmeurs modernes, mais c'est bash. Bash n’était pas destiné à écrire des programmes volumineux et robustes, mais à aider les administrateurs à travailler avec moins de touches ;-)
Et au moins, vous pouvez placer la redirection n'importe où dans la ligne:
$ echo This message >&2 goes to stderr
This message goes to stderr
Remarque: je réponds à la question - pas à la question trompeuse/vague "d'écho qui sort vers stderr" (déjà répondu par OP).
Utilisez une fonction pour afficher le intention et trouver l’implémentation souhaitée. Par exemple.
#!/bin/bash
[ -x error_handling ] && . error_handling
filename="foobar.txt"
config_error $filename "invalid value!"
output_xml_error "No such account"
debug_output "Skipping cache"
log_error "Timeout downloading archive"
notify_admin "Out of disk space!"
fatal "failed to open logger!"
Et error_handling
étant:
ADMIN_EMAIL=root@localhost
config_error() { filename="$1"; shift; echo "Config error in $filename: $*" 2>&1; }
output_xml_error() { echo "<error>$*</error>" 2>&1; }
debug_output() { [ "$DEBUG"=="1" ] && echo "DEBUG: $*"; }
log_error() { logger -s "$*"; }
fatal() { which logger >/dev/null && logger -s "FATAL: $*" || echo "FATAL: $*"; exit 100; }
notify_admin() { echo "$*" | mail -s "Error from script" "$ADMIN_EMAIL"; }
Raisons qui gèrent les problèmes dans l'OP:
Autres raisons:
Cela a déjà été répondu et avec beaucoup de votes. Juste pour info:
echo "my errz" > /proc/self/fd/2
affichera effectivement stderr
. Explication: /proc/self
est un lien vers le processus en cours et /proc/self/fd
contient les descripteurs de fichier ouverts du processus. 0
, 1
et 2
correspondent respectivement à stdin
, stdout
et stderr
.
Je l'ai trouvé plus lisible. Cela peut aussi fonctionner dans la plupart des distributions Linux:
echo "my errz" > /dev/stderr
Le rendant beaucoup plus lisible.
read
est une commande intégrée au shell qui s’imprime sur stderr et peut être utilisée comme écho sans effectuer de redirection:
read -t 0.1 -p "This will be sent to stderr"
Le -t 0.1
est un délai qui désactive la fonctionnalité principale de read et stocke une ligne de stdin dans une variable.
Faire un script
#!/bin/sh
echo $* 1>&2
ce serait votre outil.
Ou créez une fonction si vous ne voulez pas avoir un script dans un fichier séparé.
Une autre option que je suis récemment tombé sur est la suivante:
{
echo "First error line"
echo "Second error line"
echo "Third error line"
} >&2
Ceci utilise uniquement les éléments intégrés de Bash tout en réduisant le risque d'erreur sur les lignes multilignes (vous n'avez pas à vous rappeler d'ajouter &>2
à chaque ligne).