Pourriez-vous élaborer la loi différemment dans le cadre de votre question?
devnull
Vous avez un contrôle limité sur la distance prog2a progressé lorsque les prog1sorties, en raison de la mise en mémoire tampon interne utilisé pour mettre en œuvre la conduite et comment prog1et prog2sont prévues.
chepner
Regardez également [Dans quel ordre s'exécutent les commandes canalisées?] (Unix.stackexchange.com/q/37508)
DK Bose
Réponses:
4
La réponse générale est non. Il est possible prog2de quitter avant prog1même de commencer (cela ne peut évidemment pas se produire s'il prog2lit réellement une entrée, ce que vous attendez qu'il fasse si vous l'utilisez dans un pipeline). Il est certainement possible prog2de sortir avant prog1; cela se produit par exemple quand prog2un programme de recherche prog1se termine dès qu'il trouve une correspondance, auquel cas il se peut qu'il n'ait pas encore fini de produire toutes les données.
Il n'y a aucun moyen direct prog2de récupérer l'état de sortie de prog1ou même de savoir qu'il prog1est sorti. Tout ce que l' prog2on peut savoir, c'est qu'il prog1a fermé son extrémité du tuyau, ce qu'il peut faire sans mourir.
Si vous souhaitez obtenir l'état de sortie de prog1from prog2, il existe deux méthodes courantes: vous pouvez l'écrire dans un fichier ou l'envoyer via le canal. L'envoi de l'état de sortie comme dernière ligne des données canalisées est une possibilité. Vous devez vous assurer de ne pas traiter la dernière ligne jusqu'à ce que vous sachiez que c'est la dernière ligne, c'est-à-dire jusqu'à ce que vous ayez essayé de lire la ligne suivante.
{ prog1; echo $?;}|…
Voici un exemple où le côté droit est un filtre de texte qui colore chaque ligne contenant le mot «erreur» en rouge. Si le côté gauche échoue, le côté droit sort avec le même état.
{ prog1; echo $?;}| awk '
NR != 1 {
if (line ~ /[Ee][Rr][Rr][Oo][Rr]/) print "\033[31m" line "\033[0m";
else print line;
}
{line = $0}
END {exit($0)}
'
J'essayais { command; echo ${PIPESTATUS[@]}; } | sort | ...pour que le statut de sortie vienne en premier dans le flux. C'est très intéressant!
@ illuminÉ Cela ne fonctionnerait que si ${PIPESTATUS[@]}est trié avant toute autre chose dans la sortie de command. Si commandimprime un tas de nombres, ou s'il peut imprimer du texte arbitraire, vous avez des problèmes: vous ne pourrez pas distinguer sa sortie de la ligne d'état.
Gilles 'SO- arrête d'être méchant'
Merci, en effet, il ne réussit à trier un état de réussite que si la commande ne contient pas 0 dans sa sortie lol. Tgif / s.
2
Bien que vous puissiez le faire dans certains cas particuliers (voir les autres réponses), vous ne le pouvez pas dans tous les cas. Certains programmes de filtrage continueront tout simplement, tandis que d'autres conserveront toutes les sorties, les libéreront en une seule fois, puis quitteront.
Pour un exemple de programme "continuez tout simplement", grepsera serveur, comme le ferait tail -f /var/log/some_log_file. L'utilisation sortdans un pipeline provoque un "décrochage", de même que la sortcollecte de l'entrée jusqu'à la fermeture du tuyau devant lui. L'utilisation xargsajoute une complication supplémentaire: les programmes sont-ils démarrés par xargs(cela pourrait démarrer de nombreuses instances) une partie du pipeline ou non?
-1 parce que vous avez voté pour rationaliser une réponse incorrecte.
ctrl-alt-delor
@richard Huh? La réponse de Bruce est correcte (bien que le deuxième paragraphe soit un peu déroutant).
Gilles 'SO- arrête d'être méchant'
1
La réponse: pas directement.
@terdon a illustré que le code de sortie de la commande précédente dans le canal doit être envoyé en tant que paramètre explicite à la commande suivante.
N'oubliez pas que le canal est simplement un mappage du STDOUT de la commande précédente au STDIN de la commande suivante; les codes de sortie ne sont pas sortis vers STDOUT (ou STDERR).
-1 parce que vous avez voté pour avoir cité une réponse incorrecte, sans en dire beaucoup plus.
ctrl-alt-delor
@richard assez juste ... j'aurais dû vérifier deux fois ... c'est ce qui s'est passé si je me force à répondre à une question quand je suis très fatigué ...
pepoluan
1
Tous les processus, en cours, sont démarrés avant toute sortie. Par conséquent, il prog2pourrait être nécessaire d'obtenir ces informations après le démarrage, il devrait également suspendre le traitement jusqu'à la fin prog1, ce qui pourrait bloquer le tuyau. Il semble y avoir des problèmes fondamentaux à faire ce que vous demandez, pas des limitations du système d'exploitation.
Vous devrez probablement considérer un fichier temporaire ou mettre le résultat dans une variable.
Exemple pour une petite quantité de données, en utilisant une variable.
tmp=$(prog1)if test "z$PIPESTATUS"=="z0"then…else…fi
Il y a une lacune dans votre raisonnement. prog2est démarré avant la prog1fin en général, mais il pourrait y avoir un moyen de recevoir l'état de sortie prog1pendant qu'il est en cours d'exécution.
prog2
a progressé lorsque lesprog1
sorties, en raison de la mise en mémoire tampon interne utilisé pour mettre en œuvre la conduite et commentprog1
etprog2
sont prévues.Réponses:
La réponse générale est non. Il est possible
prog2
de quitter avantprog1
même de commencer (cela ne peut évidemment pas se produire s'ilprog2
lit réellement une entrée, ce que vous attendez qu'il fasse si vous l'utilisez dans un pipeline). Il est certainement possibleprog2
de sortir avantprog1
; cela se produit par exemple quandprog2
un programme de rechercheprog1
se termine dès qu'il trouve une correspondance, auquel cas il se peut qu'il n'ait pas encore fini de produire toutes les données.Il n'y a aucun moyen direct
prog2
de récupérer l'état de sortie deprog1
ou même de savoir qu'ilprog1
est sorti. Tout ce que l'prog2
on peut savoir, c'est qu'ilprog1
a fermé son extrémité du tuyau, ce qu'il peut faire sans mourir.Si vous souhaitez obtenir l'état de sortie de
prog1
fromprog2
, il existe deux méthodes courantes: vous pouvez l'écrire dans un fichier ou l'envoyer via le canal. L'envoi de l'état de sortie comme dernière ligne des données canalisées est une possibilité. Vous devez vous assurer de ne pas traiter la dernière ligne jusqu'à ce que vous sachiez que c'est la dernière ligne, c'est-à-dire jusqu'à ce que vous ayez essayé de lire la ligne suivante.Voici un exemple où le côté droit est un filtre de texte qui colore chaque ligne contenant le mot «erreur» en rouge. Si le côté gauche échoue, le côté droit sort avec le même état.
la source
{ command; echo ${PIPESTATUS[@]}; } | sort | ...
pour que le statut de sortie vienne en premier dans le flux. C'est très intéressant!${PIPESTATUS[@]}
est trié avant toute autre chose dans la sortie decommand
. Sicommand
imprime un tas de nombres, ou s'il peut imprimer du texte arbitraire, vous avez des problèmes: vous ne pourrez pas distinguer sa sortie de la ligne d'état.Bien que vous puissiez le faire dans certains cas particuliers (voir les autres réponses), vous ne le pouvez pas dans tous les cas. Certains programmes de filtrage continueront tout simplement, tandis que d'autres conserveront toutes les sorties, les libéreront en une seule fois, puis quitteront.
Pour un exemple de programme "continuez tout simplement",
grep
sera serveur, comme le feraittail -f /var/log/some_log_file
. L'utilisationsort
dans un pipeline provoque un "décrochage", de même que lasort
collecte de l'entrée jusqu'à la fermeture du tuyau devant lui. L'utilisationxargs
ajoute une complication supplémentaire: les programmes sont-ils démarrés parxargs
(cela pourrait démarrer de nombreuses instances) une partie du pipeline ou non?la source
La réponse: pas directement.
@terdon a illustré que le code de sortie de la commande précédente dans le canal doit être envoyé en tant que paramètre explicite à la commande suivante.
N'oubliez pas que le canal est simplement un mappage du STDOUT de la commande précédente au STDIN de la commande suivante; les codes de sortie ne sont pas sortis vers STDOUT (ou STDERR).
la source
Tous les processus, en cours, sont démarrés avant toute sortie. Par conséquent, il
prog2
pourrait être nécessaire d'obtenir ces informations après le démarrage, il devrait également suspendre le traitement jusqu'à la finprog1
, ce qui pourrait bloquer le tuyau. Il semble y avoir des problèmes fondamentaux à faire ce que vous demandez, pas des limitations du système d'exploitation.Vous devrez probablement considérer un fichier temporaire ou mettre le résultat dans une variable.
Exemple pour une petite quantité de données, en utilisant une variable.
la source
prog2
est démarré avant laprog1
fin en général, mais il pourrait y avoir un moyen de recevoir l'état de sortieprog1
pendant qu'il est en cours d'exécution.Pour terminer la réponse de Gilles ,
est une approche.
prog2
pourrait soit/tmp/prog1.status
, ou/tmp/prog1.status
périodiquement lors de la lecture de l'entrée standard.la source