Comment redirect la sortie d’un script shell complet dans le script lui-même?

Est-il possible de redirect toute la sortie d’un script shell Bourne vers quelque part, mais avec des commandes shell dans le script lui-même?

Redirection de la sortie d’une seule commande est facile, mais je veux quelque chose de plus:

#!/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 à la sortie standard, 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 n’ai pas l’habitude de voir tous les jours dans un courrier électronique, 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 e-mail le résultat de cette partie des tâches quotidiennes.

Mise à jour: La réponse de Joshua est exacte, mais je voulais aussi sauvegarder et restaurer stdout et stderr autour du script entier, ce qui se fait comme ceci:

 # 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 

Répondre à la question comme mise à jour.

 #...part of script without redirection... { #...part of script with redirection... } > file1 2>file2 # ...and others as appropriate... #...residue of script without redirection... 

Les accolades ‘{…}’ fournissent une unité de redirection d’E / S. Les accolades doivent apparaître où une commande peut apparaître – de manière simpliste, au début d’une ligne ou après un point-virgule. ( Oui, cela peut être plus précis; si vous voulez chipoter, faites le moi savoir. )

Vous avez raison de dire que vous pouvez conserver le fichier stdout et stderr d’origine avec les redirections que vous avez montrées, mais il est généralement plus simple pour les personnes qui doivent gérer le script plus tard de comprendre ce qui se passe.

Envoyer stdout dans un fichier

 exec > file 

avec stderr

 exec > file exec 2>&1 

append les deux fichiers stdout et stderr au fichier

 exec >> file exec 2>&1 

Vous pouvez faire de tout le script une fonction comme ceci:

 main_function() { do_things_here } 

alors à la fin du script ont ceci:

 if [ -z $TERM ]; then # if not run via terminal, log everything into a log file main_function 2>&1 >> /var/log/my_uber_script.log else # run via terminal, only output to screen main_function fi 

Alternativement, vous pouvez tout enregistrer dans logfile chaque exécution et toujours le sortir en stdout simplement en:

 # log everything, but also output to stdout main_function 2>&1 | tee -a /var/log/my_uber_script.log 
 [ -t <&0 ] || exec >> test.log 

Pour enregistrer le fichier stdout et stderr d’origine, vous pouvez utiliser:

 exec [fd number]<&1 exec [fd number]<&2 

Par exemple, le code suivant imprimera "walla1" et "walla2" dans le fichier journal ( a.txt ), "walla3" dans stdout, "walla4" dans stderr.

 #!/bin/bash exec 5<&1 exec 6<&2 exec 1> ~/a.txt 2>&1 echo "walla1" echo "walla2" >&2 echo "walla3" >&5 echo "walla4" >&6