Comment redirect l'erreur vers un file?

J'ai ce script simple qui redirige la sortie et l' append à un file.

 filename="/home/ronnie/tmp/hello" date=$(date) echo "$date" >> $filename 

Maintenant, supposons que je change la date=$(date) à date= $(date) qui générera une erreur.

Mon script modifié:

 filename="/home/ronnie/tmp/hello" date= $(date) echo "$date" >> $filename 2>> $filename #Also sortinged echo "$date" >> $filename 2>&1 

Je pensais que le script ci-dessus va redirect l'erreur test.sh: line 5: Fri: command not found dans le file hello mais elle entre juste une nouvelle ligne dans le file et l'erreur est imprimée sur mon stdout .

Ma version bash:

 ronnier@ronnie:~/tmp$ bash --version GNU bash, version 4.2.24(1)-release (i686-pc-linux-gnu) 

Alors, où vais-je mal?

La ligne qui cause l'erreur est date =$(date) , cette erreur est envoyée à stderr. À ce stade, vous ne redirigez stderr nulle part. La ligne suivante envoie stderr à $ filename, mais ce n'est pas cette ligne qui provoque l'erreur.

Une des façons d'get l'effet que vous voulez, vous exécuterez votre script et dirigerez stderr vers un autre endroit en même time, alors,

 ./myscript 2>> errors.txt 

à ce stade, errors.txt contiendra votre erreur.

Le problème est donc que la ligne générant l'erreur est une erreur dans le script lui-même, pas une erreur provoquée par une command externe que le script appelle qui a sa sortie redirigée. c'est-à-dire que c'est la sortie de script de niveau supérieur que vous devez redirect.

Le shell émet un message d'erreur lorsqu'il atteint la ligne 5. Le stream d'erreur du shell n'est pas redirigé à ce point.

Si vous écrivez la date= $(date) 2>/dev/null , le message "command not found" provient du shell et non de la command dont le stream d'erreur est redirigé. Par conséquent, vous verrez toujours le message d'erreur.

Pour éviter de voir le message d'erreur, placez toute la command à l'intérieur d'un groupe et redirigez le stream d'erreur du groupe entier:

 { date= $(date); } 2>/dev/null 

Avec les accolades, la command est toujours exécutée dans le shell parent, donc elle peut changer son environnement et son autre état (et non pas ici). Vous pouvez également placer la command dans un corps de fonction ou dans un sous-shell (commands entre parenthèses, exécutées dans un process shell séparé).

Vous pouvez redirect les descripteurs de files du shell de manière permanente (ou au less jusqu'à la prochaine modification) en utilisant une redirection sur l'exécutable embedded sans nom de command.

 exec 2>/dev/null # From this point on, all error messages are lost date= $(date) … exec 2>/some/log/file # From this point on, all error messages go to the specified file