Rediriger stdout seul, comme lors d'un pipe stdin

Résolu/Fermé
gnugo - 3 oct. 2012 à 09:40
mamiemando Messages postés 33407 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 29 novembre 2024 - 3 oct. 2012 à 23:59
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

dubcek Messages postés 18755 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 14 novembre 2024 5 621
3 oct. 2012 à 10:00
hello
$ (echo aaa ; echo bbb>&2 ; echo ccc) 2> >(sed 's/^/stderr: /' >&2) | sed 's/^/stdout: /'
stdout: aaa
stdout: ccc
stderr: bbb
$ 
2
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! :-)
0
mamiemando Messages postés 33407 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 29 novembre 2024 7 806
Modifié par mamiemando le 3/10/2012 à 09:54
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
0
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
0
mamiemando Messages postés 33407 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 29 novembre 2024 7 806
3 oct. 2012 à 10:08
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
0
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
0
mamiemando Messages postés 33407 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 29 novembre 2024 7 806
3 oct. 2012 à 23:59
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.
0