Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 30/05/2017, à 18:51

Postmortem

[bash] Redirections sorties standard et d'erreur vers fichiers/écran

Salut,

Voilà bien longtemps que je ne suis pas venu faire un tour par ici !!
En général, je venais plutôt pour essayer de filer un coup de main mais là, je m'arrache les cheveux depuis un moment sur un problème.

Mon but est de rediriger les sorties standard et d'erreur d'un script vers un fichier log ET vers l'écran...
Ça c'est pas compliqué...
Mais je voudrais en plus que le script garde 2 sorties distinctes et que ça soit synchro. Et c'est avoir ces 2 conditions en même temps qui ne fonctionne pas !

Petit exemple :

$ cat test.sh 
#!/bin/bash

# Redirections et sauvegardes sorties originales
exec 3>&1 4>&2 > >(tee /tmp/test/mon_log) 2>&1

echo "Message 1 sur sortie STANDARD"
echo "Message 1 sur sortie ERREUR" >&2

echo "Message 2 sur sortie STANDARD"
echo "Message 2 sur sortie ERREUR" >&2

# Restauration sorties originales
exec >&3- 2>&4-

Ce qui donne à l'exécution :

$ ./test.sh 
$ Message 1 sur sortie STANDARD
Message 1 sur sortie ERREUR
Message 2 sur sortie STANDARD
Message 2 sur sortie ERREUR

$ cat mon_log
Message 1 sur sortie STANDARD
Message 1 sur sortie ERREUR
Message 2 sur sortie STANDARD
Message 2 sur sortie ERREUR
$ 

Ça a l'air bien, n'est ce pas ?? Si ce n'est le prompt qui se raffiche avant l'affichage de tous mes messages... Mais :

$ ./test.sh >fic_sortie 2>fic_erreur
$ ls -ltr
total 12
-rwxrwxr-x 1 XXX XXX 314 mai   30 18:13 test.sh
-rw-rw-r-- 1 XXX XXX   0 mai   30 18:20 fic_erreur    # <=== C'est vide !!
-rw-rw-r-- 1 XXX XXX 116 mai   30 18:20 mon_log
-rw-rw-r-- 1 XXX XXX 116 mai   30 18:20 fic_sortie
$

Rien ne va dans fic_erreur, la sortie standard et la sortie d'erreur sont "fusionnées", tout est donc allé dans fic_sortie.

Alors après des dizaines d'essais, je suis arrivé à ça ; j'ai bien mes 2 sorties séparées mais j'ai des problèmes dans l'ordre d'affichage des messages dans "mon_log" ou si je laisse l'affichage à l'écran :

$ cat test2.sh 
#!/bin/bash

fic_log=/tmp/test/mon_log
>"$fic_log" # On vide le log

exec 3>&1 4>&2

coproc gestion_sorties {
    while read -r
    do
        case $REPLY in
            1\;*) fd=3;;
            2\;*) fd=4;;
        esac
        printf '%s\n' "${REPLY#?;}" >> "$fic_log"
        printf '%s\n' "${REPLY#?;}" >&$fd
    done
}

exec > >( while read -r; do echo "1;$REPLY"; done >&${gestion_sorties[1]} ) 2> >( while read -r; do echo "2;$REPLY"; done >&${gestion_sorties[1]} )

echo "Message 1 sur sortie STANDARD"
echo "Message 1 sur sortie ERREUR" >&2

echo "Message 2 sur sortie STANDARD"
echo "Message 2 sur sortie ERREUR" >&2

exec >&3- 2>&4- {gestion_sorties[1]}>&- {gestion_sorties[0]}<&-
wait $gestion_sorties_PID
$ 
$ ./test2.sh >fic_sortie 2>fic_erreur
$ ls -ltr
total 20
-rwxrwxr-x 1 XXX XXX 314 mai   30 18:13 test.sh
-rwxrwxr-x 1 XXX XXX 718 mai   30 18:34 test2.sh
-rw-rw-r-- 1 XXX XXX 116 mai   30 18:37 mon_log
-rw-rw-r-- 1 XXX XXX  60 mai   30 18:37 fic_sortie
-rw-rw-r-- 1 XXX XXX  56 mai   30 18:37 fic_erreur
$ more mon_log fic_sortie fic_erreur
::::::::::::::
mon_log
::::::::::::::
Message 1 sur sortie STANDARD
Message 2 sur sortie STANDARD   # <=== Les messages dans mon_log ne sont pas dans le bon ordre   
Message 1 sur sortie ERREUR
Message 2 sur sortie ERREUR
::::::::::::::
fic_sortie
::::::::::::::
Message 1 sur sortie STANDARD
Message 2 sur sortie STANDARD
::::::::::::::
fic_erreur
::::::::::::::
Message 1 sur sortie ERREUR
Message 2 sur sortie ERREUR
$ 

Bon, en vrai, c'est pas dramatique, c'est plus du chipotage que je fais.... Mais ça m'énerve !!!

Merci d'avance pour votre aide !

Édit :
Mon test2.sh est tordu, on peut arriver au même résultat bien plus simplement, mais toujours avec le problème de synchro :

#!/bin/bash
exec 3>&1 4>&2 > >(tee -a mon_log) 2> >(tee -a mon_log >&2)

echo "Message 1 sur sortie STANDARD"
echo "Message 1 sur sortie ERREUR" >&2

echo "Message 2 sur sortie STANDARD"
echo "Message 2 sur sortie ERREUR" >&2

exec >&3- 2>&4-

Dernière modification par Postmortem (Le 31/05/2017, à 09:17)


Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »

Hors ligne

#2 Le 31/05/2017, à 08:56

pingouinux

Re : [bash] Redirections sorties standard et d'erreur vers fichiers/écran

Bonjour Postmortem,
Effectivement, ça fait un bail…

$ ./test.sh >fic_sortie 2>fic_erreur

Rien ne va dans fic_erreur, la sortie standard et la sortie d'erreur sont "fusionnées", tout est donc allé dans fic_sortie.

Ça me paraît logique, puisque tu rediriges stderr sur stdout dans test.sh

exec 3>&1 4>&2 > >(tee /tmp/test/mon_log) 2>&1

Pour la suite, je n'ai pas encore tout compris…

Hors ligne

#3 Le 31/05/2017, à 09:28

Postmortem

Re : [bash] Redirections sorties standard et d'erreur vers fichiers/écran

Salut pingouinux,
Je savais que ça te plairait comme souci ! tongue

pingouinux a écrit :

Ça me paraît logique, puisque tu rediriges stderr sur stdout dans test.sh

exec 3>&1 4>&2 > >(tee /tmp/test/mon_log) 2>&1

Oui oui, c'est logique, c'était car je m'attendais à ce qu'on me propose cette solution, donc j'ai pris les devants pour expliquer pourquoi ce n'est pas ce que j'attendais.

J'ai mis à jour mon 1er message avec une solution bien plus simple (j'en suis arrivé à "coproc" après des dizaines d'essais, me suis perdu !) pour garder 2 flux en sortie mais j'ai toujours le souci de synchro.

Je crois qu'on ne peut pas y arriver en bash d'après tout ce que j'ai lu hier soir.


Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »

Hors ligne

#4 Le 31/05/2017, à 10:01

pingouinux

Re : [bash] Redirections sorties standard et d'erreur vers fichiers/écran

Peut-être ceci :

#!/bin/bash
exec 3>&1 4>&2 > >(tee -a mon_log >&1) 2> >(tee -a mon_log >&2)

stdbuf -o0 echo "Message 1 sur sortie STANDARD"
stdbuf -e0 echo "Message 1 sur sortie ERREUR" >&2

stdbuf -o0 echo "Message 2 sur sortie STANDARD"
stdbuf -e0 echo "Message 2 sur sortie ERREUR" >&2

exec >&3- 2>&4-

Hors ligne

#5 Le 31/05/2017, à 10:58

Postmortem

Re : [bash] Redirections sorties standard et d'erreur vers fichiers/écran

Merci, ça fonctionne nickel si on a que des « echo » dans le script.
Mais bien sûr, je n'ai pas que ça dedans ; il fait beaucoup de chose ce script, dont un appels ssh pour exécuter un script sur un serveur.
J'ai fait un test avec un simple awk qui écrit sur STDOUT et STDERR et là, ça ne fonctionne plus :

$ cat test.sh 
#!/bin/bash

exec 3>&1 4>&2 > >(tee -a mon_log >&1) 2> >(tee -a mon_log >&2)

stdbuf -o0 -e0 awk 'BEGIN { for (i=1; i<=5; i++) { printf "Message %d sur sortie STANDARD\n", i; printf "Message %d sur sortie ERREUR\n", i > "/dev/stderr" } }'

exec >&3- 2>&4-
$ 

$ ./test.sh 
Message 1 sur sortie STANDARD
Message 2 sur sortie STANDARD
Message 1 sur sortie ERREUR
Message 2 sur sortie ERREUR
Message 3 sur sortie ERREUR
Message 4 sur sortie ERREUR
Message 5 sur sortie ERREUR
Message 3 sur sortie STANDARD
Message 4 sur sortie STANDARD
Message 5 sur sortie STANDARD
$ 

Mais je garde dans un coin ce « stdbuf », merci !

Edit :
Je pense que c'est mort à partir du moment où la sortie standard et la sortie d'erreur font appel à 2 « substitutions de processus » étant donné que la « substitution de processus » est asynchrone.

Dernière modification par Postmortem (Le 31/05/2017, à 11:02)


Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »

Hors ligne