Je veux rediriger à la fois stdout et stderr d'un processus vers un seul fichier. Comment puis-je faire cela dans Bash ?
Cette syntaxe est dépréciée selon les règles de l'UE. Bash Hackers Wiki . C'est ça ?
Je veux rediriger à la fois stdout et stderr d'un processus vers un seul fichier. Comment puis-je faire cela dans Bash ?
Jetez un coup d'œil aquí . Devrait être :
yourcommand &>filename
(qui redirige les deux stdout
y stderr
au nom de fichier).
Según wiki.bash-hackers.org/scripting/obsolete Il semble qu'il soit obsolète dans le sens où il ne fait pas partie de POSIX, mais la page de manuel de bash ne mentionne pas qu'il sera supprimé de bash dans un futur proche. La page de manuel indique une préférence pour '&>' par rapport à '>&', qui est par ailleurs équivalent.
Je suppose que nous ne devrions pas utiliser &> car il n'est pas dans POSIX, et les shells courants tels que "dash" ne le supportent pas.
Sous AIX (ksh), votre solution fonctionne. La réponse acceptée do_something &>filename
ne le fait pas. +1.
Vous pouvez rediriger stderr a stdout y el stdout dans un fichier :
some_command >file.log 2>&1
Ver http://tldp.org/LDP/abs/html/io-redirection.html
Ce format est préféré au format le plus populaire &> qui ne fonctionne que dans bash. Dans le shell Bourne, il pourrait être interprété comme l'exécution de la commande en arrière-plan. De plus, le format est plus lisible 2 (est STDERR) redirigé vers 1 (STDOUT).
EDIT : changement de l'ordre comme indiqué dans les commentaires
Si vous voulez ajouter à un fichier, vous devez le faire de cette façon : echo "foo" 2>&1 1>> bar.txt AFAIK il n'y a aucun moyen d'ajouter en utilisant &>.
# Close STDOUT file descriptor
exec 1<&-
# Close STDERR FD
exec 2<&-
# Open STDOUT as $LOG_FILE file for read and write.
exec 1<>$LOG_FILE
# Redirect STDERR to STDOUT
exec 2>&1
echo "This line will appear in $LOG_FILE, not 'on screen'"
Maintenant, un simple écho écrira dans $LOG_FILE. Utile pour la démonisation.
À l'auteur du message original,
Cela dépend de ce que vous voulez réaliser. Si vous avez juste besoin de rediriger les entrées/sorties d'une commande que vous appelez depuis votre script, les réponses sont déjà données. La mienne consiste à rediriger sur le script actuel qui affecte toutes les commandes/built-ins (y compris les forks) après l'extrait de code mentionné.
Une autre solution intéressante consiste à rediriger à la fois vers std-err/out ET vers le logger ou le fichier de log en même temps, ce qui implique de diviser "un flux" en deux. Cette fonctionnalité est fournie par la commande 'tee' qui peut écrire/appliquer sur plusieurs descripteurs de fichiers (fichiers, sockets, pipes, etc.) en une seule fois : tee FILE1 FILE2 ... >(cmd1) >(cmd2) ...
exec 3>&1 4>&2 1> >(tee >(logger -i -t 'my_script_tag') >&3) 2> >(tee >(logger -i -t 'my_script_tag') >&4)
trap 'cleanup' INT QUIT TERM EXIT
get_pids_of_ppid() {
local ppid="$1"
RETVAL=''
local pids=`ps x -o pid,ppid | awk "\\$2 == \\"$ppid\\" { print \\$1 }"`
RETVAL="$pids"
}
# Needed to kill processes running in background
cleanup() {
local current_pid element
local pids=( "$$" )
running_pids=("${pids[@]}")
while :; do
current_pid="${running_pids[0]}"
[ -z "$current_pid" ] && break
running_pids=("${running_pids[@]:1}")
get_pids_of_ppid $current_pid
local new_pids="$RETVAL"
[ -z "$new_pids" ] && continue
for element in $new_pids; do
running_pids+=("$element")
pids=("$element" "${pids[@]}")
done
done
kill ${pids[@]} 2>/dev/null
}
Donc, depuis le début. Supposons que nous ayons un terminal connecté à /dev/stdout(FD #1) et /dev/stderr(FD #2). En pratique, il peut s'agir d'un tuyau, d'un socket ou autre.
Le résultat de l'exécution d'un script ayant la ligne ci-dessus et en plus celle-ci :
echo "Will end up in STDOUT(terminal) and /var/log/messages"
...est le suivant :
$ ./my_script
Will end up in STDOUT(terminal) and /var/log/messages
$ tail -n1 /var/log/messages
Sep 23 15:54:03 wks056 my_script_tag[11644]: Will end up in STDOUT(terminal) and /var/log/messages
Si vous voulez voir une image plus claire, ajoutez ces 2 lignes au script :
ls -l /proc/self/fd/
ps xf
Une seule exception. dans le premier exemple, vous avez écrit : exec 1<>$LOG_FILE . il en résulte que le fichier journal original est toujours écrasé. pour un vrai journal, la meilleure façon est : exec 1>>$LOG_FILE il en résulte que le journal est toujours ajouté.
C'est vrai, mais cela dépend des intentions. Mon approche consiste à toujours créer un fichier journal unique et horodaté. L'autre approche consiste à ajouter des fichiers. Les deux méthodes sont "logrotables". Je préfère les fichiers séparés qui nécessitent moins d'analyse, mais comme je l'ai dit, tout ce qui fait flotter votre bateau :)
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
2 votes
J'aimerais dire que cette question est étonnamment utile. Beaucoup de gens ne savent pas comment faire, car ils n'ont pas à le faire fréquemment, et ce n'est pas le comportement le mieux documenté de Bash.
3 votes
Parfois, il est utile de voir la sortie (comme d'habitude) ET de la rediriger vers un fichier. Voir la réponse de Marko ci-dessous. (Je le dis ici car il est facile de se contenter de la première réponse acceptée si cela suffit à résoudre un problème, mais les autres réponses fournissent souvent des informations utiles).