web-dev-qa-db-fra.com

echo qui sort en stderr

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). 

883
BCS

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.

1128
Marco Aurelio

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; }
377
James Roth

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!

212
Brandon Rhodes

Une autre option

echo foo >>/dev/stderr
43
Steven Penny

Non, c'est la façon habituelle de le faire. Cela ne devrait pas causer d'erreurs.

29
Matthew Flaschen

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
12
erselbst

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."

10
Grzegorz Luczywo

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
9
return42

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:

  • plus belle syntaxe possible (mots significatifs au lieu de symboles laids)
  • plus difficile de faire une erreur (surtout si vous réutilisez le script)
  • ce n'est pas un outil Bash standard, mais il peut s'agir d'une bibliothèque Shell standard pour vous ou votre entreprise/organisation

Autres raisons:

  • clarté - indique l'intention aux autres responsables
  • rapidité - les fonctions sont plus rapides que les scripts Shell
  • réutilisabilité - une fonction peut appeler une autre fonction
  • configurabilité - pas besoin de modifier le script original
  • le débogage - il est plus facile de trouver la ligne responsable d'une erreur (surtout si vous êtes submergé par une tonne de sorties de redirection/filtrage)
  • robustesse - si une fonction est manquante et que vous ne pouvez pas modifier le script, vous pouvez utiliser un outil externe portant le même nom (par exemple, log_error peut être associé à l'enregistreur sur Linux).
  • changer d'implémentation - vous pouvez passer à des outils externes en supprimant l'attribut "x" de la bibliothèque
  • sortie agnostique - vous ne devez plus vous soucier si cela va à STDERR ou ailleurs
  • personnalisation - vous pouvez configurer le comportement avec des variables d'environnement
7
Cezary Baginski

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.

6
Sebastian

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.

5
Douglas Mayle

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é.

2
n0rd

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).

0
GuyPaddock