Rediriger stdout seul, comme lors d'un pipe stdin [Résolu/Fermé]

Signaler
-
Messages postés
29732
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
15 avril 2021
-
Bonjour,

Voici mon problème :

j'ai une commande au milieu de multiples pipe dont je voudrais traiter la sortie STDERR différemment. Je m'explique:

..... commande1 | commande2 .....

STDOUT de "commande1" va donc vers "commande2"
et STDERR de "commande1" va s'afficher sur mon terminal local

Ce que je voudrais faire, c'est rediriger ce STDERR vers un programme qui va le modifier, puis renvoyer cette modification pour qu'elle s'affiche sur mon terminal


Exemple:
cmd1 2> >(grep txt) | cmd2

Sauf que dans cet exemple, la sortie du "grep txt" n'est plus redirigée vers mon terminal. Je n'arrive pas à trouver de solution.


Sauriez-vous m'aider?
Merci:)

3 réponses

Messages postés
18240
Date d'inscription
lundi 15 janvier 2007
Statut
Contributeur
Dernière intervention
30 novembre 2020
5 254
hello
$ (echo aaa ; echo bbb>&2 ; echo ccc) 2> >(sed 's/^/stderr: /' >&2) | sed 's/^/stdout: /'
stdout: aaa
stdout: ccc
stderr: bbb
$ 
2
Merci

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

CCM 65492 internautes nous ont dit merci ce mois-ci

J'avais mis le >&2 à l'extérieur de la parenthèse
cmd1 2> >(grep txt)>&2 | cmd2

En le mettant dedans ça marche mieux effectivement !
Merci! :-)
Messages postés
29732
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
15 avril 2021
7 072
En fait tu peux rediriger le flux stderr sur le flux stdout et ainsi le récupérer dans ton pipe (2>&1).

Tu peux rediriger le flux qui était envoyé initialement dans stdout vers /dev/null (1>/dev/null) pour qu'il ne perturbe pas le flux d'erreur. Attention à l'ordre dans lequel tu passes les redirections car dans le mauvais ordre, tu vas rediriger les deux flux vers /dev/null. La syntaxe correcte est indiquée ci-dessous :

(mando@silk) (/etc) $ find .
find: .
./shadow-
./kernel-img.conf
./esound
./esound/esd.conf
./.pwd.lock
./acpi
./acpi/events
./acpi/events/RadioPowerTest
./udev
"./lvm/cache": Permission non accordée
...

(mando@silk) (/etc) $ find . 2>&1 1>/dev/null 
find: "./lvm/cache": Permission non accordée 
find: "./vpnc": Permission non accordée 
find: "./ppp/peers": Permission non accordée 
find: "./ssl/private": Permission non accordée 
find: "./chatscripts": Permission non accordée 

(mando@silk) (/etc) $ find . 2>&1 1>/dev/null | grep vpnc 
find: "./vpnc": Permission non accordée


Comme tu le vois ici, le flux d'erreur traverse bien le pipe puisque grep rattrape bien uniquement la ligne contenant vpnc dans cet exemple.

Bonne chance
Salut,

Merci, mais le problème c'est que dans cet exemple le flux 1 original (STDOUT) est perdu.
Or il est très important et doit être transmis à "cmd2"

cmd1 2> >(grep txt) | cmd2
->Le STDOUT est transmis à cmd2 par le pipe
->Le STDERR, pour cmd1 doit être traité à part, comme si on l'envoyait dans un 2ème pipe
Messages postés
29732
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
15 avril 2021
7 072
Autre solution tu rediriges le flux de stderr dans un fichier temporaire et ensuite tu cat + pipe ce fichier pour commande 2.

commande 2>/tmp/toto | commande_stdout && cat /tmp/toto | commande_stderr


Bonne chance
Merci également,
La solution de dubdek correspond mieux à mon problème.

Car en passant par un fichier temporaire comme tu le suggères, la totalité du flux STDERR serait d'abord enregistrée sur le disque avant d'être traitée. Or je cherchais à traiter ce flux au fur et à mesure, comme lors d'un pipe, et ne pas le conserver sur disque.

Et en cas de traitement concurrent, si le même fichier temporaire est utilisé, cela posera de gros soucis
Messages postés
29732
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
15 avril 2021
7 072
Au moment ou tu cat /tmp/toto, rien n'empêcherait de mettre un grep pour ne conserver que les lignes qui t'intéresse.

Mais la solution de dubcek est effectivement meilleure, car elle évite de passer par un fichier temporaire (ce qui évite pas mal de soucis, comme vérifier que le fichier temporaire n'existe pas déjà , le supprimer à la fin etc.). J'avoue que je ne pensais pas qu'on pouvait rediriger un flux avec > dans une commande, pour moi c'était forcément dans un fichier... donc j'ai appris quelque chose.