Existe-t-il un moyen d'exécuter une commande uniquement après qu'une autre soit effectuée sans fichier temporaire? J'ai une commande plus longue et une autre commande qui formate la sortie et l'envoie à un serveur HTTP en utilisant curl. Si je viens d'exécuter commandA | commandB
, commandB
démarre curl
, se connecte au serveur et commence à envoyer des données. Parce que cela commandA
prend tellement de temps, le serveur HTTP expirera. Je peux faire ce que je veux aveccommandA > /tmp/file && commandB </tmp/file && rm -f /tmp/file
Par curiosité, je veux savoir s'il existe un moyen de le faire sans le fichier temporaire. J'ai essayé mbuffer -m 20M -q -P 100
mais le processus de curl est toujours démarré dès le début. Mbuffer attend jusqu'à ce que commandA
la transmission des données soit terminée. (Les données elles-mêmes ne font que quelques centaines de ko au maximum)
commandA && commandB
?commandA
àcommandB
, n'est-ce pas?Réponses:
Ceci est similaire à quelques autres réponses. Si vous avez le paquet «moreutils», vous devriez avoir la
sponge
commande. EssayerLa
sponge
commande est fondamentalement un filtre pass-through (commecat
) sauf qu'elle ne commence à écrire la sortie qu'après avoir lu l'intégralité de l'entrée. C'est-à-dire qu'il «absorbe» les données, puis les libère lorsque vous les serrez (comme une éponge). Donc, dans une certaine mesure, c'est de la «tricherie» - s'il y a une quantité non négligeable de données,sponge
utilise presque certainement un fichier temporaire. Mais c'est invisible pour vous; vous n'avez pas à vous soucier des tâches ménagères comme le choix d'un nom de fichier unique et le nettoyage par la suite.Le
{ IFS= read -r x; { printf "%s\n" "$x"; cat; } | commandB; }
lit la première ligne de sortie desponge
. N'oubliez pas que cela n'apparaît que lorsque vouscommandA
avez terminé. Ensuite, il se déclenchecommandB
, écrit la première ligne dans le tuyau et appellecat
pour lire le reste de la sortie et l'écrire dans le tuyau.la source
sponge
va de même pour cette chose que j'ai utiliséembuffer
, mais qui semble mieux adaptée ici. utiliser la lecture est intelligent ici. Je m'en souviendrai certainement pour l'avenir.mbuffer
auparavant; cela pourrait en fait être aussi bon quesponge
. Je suis d'accord que l'utilisationread
est une astuce astucieuse. Je ne peux pas m'en attribuer le mérite; il apparaît de temps en temps dans les réponses de Stack Exchange (U&L, Super User, Ask Ubuntu, etc.). En fait, la réponse de roaima à cette question est très similaire à la mienne, sauf qu'elle n'utilise passponge
(ou quelque chose d'équivalent), donc, comme je l'ai mentionné dans un commentaire, cela ne retarde pas le démarragecommandB
autant que vous en avez besoin (dans ma compréhension de ton problème).Les commandes dans le pipeline sont démarrées simultanément, vous devez stocker la
commandA
sortie quelque part pour l'utiliser plus tard. Vous pouvez éviter le fichier temporaire en utilisant la variable:la source
echo A
substitution dans le processus?Je ne connais aucun utilitaire UNIX standard pouvant résoudre ce problème. Une option serait d'utiliser
awk
pour accumuler lacommandA
sortie et la rincercommandB
à un coup, comme siAttention, cela pourrait être gourmand en mémoire car il
awk
s'agit de construire une chaîne à partir de son entrée.la source
\n
ou d'un autreORS
à la fin.Vous pouvez résoudre l'exigence avec un petit script. Cette variante particulière évite le fichier temporaire et le porc de mémoire potentiel au détriment de processus supplémentaires.
Si vous deviez appeler le script
waituntil
(et le rendre exécutable, le mettre dans lePATH
, etc.), vous l'utiliseriez comme ceciExemple
la source
commandB
jusqu'à ce qu'ilcommandA
ait écrit sa première ligne de sortie . Ce n'est probablement pas assez bon.sponge
. Off pour lire sur celui-ci maintenant.