Est-il possible de rediriger toute la sortie d'un script shell Bourne vers quelque part, mais avec des commandes shell à l'intérieur du script lui-même?
Rediriger la sortie d'une seule commande est facile, mais je veux quelque chose de plus comme ceci:
#!/bin/sh
if [ ! -t 0 ]; then
# redirect all of my output to a file here
fi
# rest of script...
Signification: si le script est exécuté de manière non interactive (par exemple, cron), enregistrez la sortie de tout dans un fichier. S'il est exécuté de manière interactive à partir d'un shell, laissez la sortie aller à stdout comme d'habitude.
Je veux le faire pour un script normalement exécuté par l'utilitaire périodique FreeBSD. Cela fait partie de la course quotidienne, que je ne tiens normalement pas à voir tous les jours par e-mail, donc je ne l'ai pas envoyé. Cependant, si quelque chose à l'intérieur de ce script particulier échoue, c'est important pour moi et j'aimerais pouvoir capturer et envoyer par courrier électronique la sortie de cette partie des tâches quotidiennes.
Mise à jour: la réponse de Joshua est parfaite, mais je voulais également enregistrer et restaurer stdout et stderr autour de l'ensemble du script, ce qui se fait comme suit:
# save stdout and stderr to file descriptors 3 and 4, then redirect them to "foo"
exec 3>&1 4>&2 >foo 2>&1
# ...
# restore stdout and stderr
exec 1>&3 2>&4
exec 1>&3 2>&4 3>&- 4>&-
Réponses:
Répondre à la question telle que mise à jour.
Les accolades '{...}' fournissent une unité de redirection d'E / S. Les accolades doivent apparaître là où une commande pourrait apparaître - de manière simplifiée, au début d'une ligne ou après un point-virgule. ( Oui, cela peut être rendu plus précis; si vous voulez ergoter, faites le moi savoir. )
Vous avez raison de pouvoir conserver la stdout et la stderr d'origine avec les redirections que vous avez montrées, mais il est généralement plus simple pour les personnes qui doivent maintenir le script plus tard de comprendre ce qui se passe si vous définissez le code redirigé comme indiqué ci-dessus.
Les sections pertinentes du manuel Bash sont Regroupement des commandes et Réacheminement E / S . Les sections pertinentes de la spécification POSIX sont des commandes composées et I / O redirection . Bash a quelques notations supplémentaires, mais est par ailleurs similaire à la spécification du shell POSIX.
la source
>>
. Certaines personnes en ont l'habitude>
. L'ajout est toujours plus sûr et plus recommandé que l'écrasement. Quelqu'un a écrit une application qui utilise la commande de copie standard pour exporter certaines données vers la même destination.En règle générale, nous plaçons l'un d'entre eux en haut ou près du haut du script. Les scripts qui analysent leurs lignes de commande feraient la redirection après l'analyse.
Envoyer stdout dans un fichier
avec stderr
ajouter à la fois stdout et stderr au fichier
Comme Jonathan Leffler l'a mentionné dans son commentaire :
exec
a deux emplois distincts. La première consiste à remplacer le shell (script) en cours d'exécution par un nouveau programme. L'autre modifie les redirections d'E / S dans le shell actuel. Cela se distingue par l'absence d'argumentexec
.la source
exec
a deux tâches distinctes. L'une consiste à remplacer le script actuel par une autre commande, en utilisant le même processus - vous spécifiez l'autre commande comme argumentexec
(et vous pouvez modifier les redirections d'E / S au fur et à mesure). L'autre tâche consiste à modifier les redirections d'E / S dans le script shell actuel sans le remplacer. Cette notation se distingue par le fait de ne pas avoir de commande comme argument pourexec
. La notation dans cette réponse est de la variante "E / S uniquement" - elle modifie uniquement la redirection et ne remplace pas le script en cours d'exécution. (Laset
commande est également polyvalente.)exec > >(tee -a "logs/logdata.log") 2>&1
imprime les journaux sur l'écran ainsi que les écrit dans un fichierVous pouvez faire du script entier une fonction comme celle-ci:
puis à la fin du script:
Alternativement, vous pouvez tout enregistrer dans le fichier journal à chaque exécution et le restituer à stdout en faisant simplement:
la source
Pour enregistrer la stdout et la stderr d'origine, vous pouvez utiliser:
Par exemple, le code suivant imprimera "walla1" et "walla2" dans le fichier journal (
a.txt
), "walla3" vers stdout, "walla4" vers stderr.la source
exec 5>&1
et d'exec 6>&2
utiliser la notation de redirection de sortie plutôt que la notation de redirection d'entrée pour les sorties. Vous vous en sortez parce que lorsque le script est exécuté à partir d'un terminal, l'entrée standard est également accessible en écriture et la sortie standard et l'erreur standard sont lisibles en vertu (ou est-ce le «vice»?) D'une bizarrerie historique: le terminal est ouvert pour en lecture et en écriture et la même description de fichier ouvert est utilisée pour les trois descripteurs de fichier d'E / S standard.la source