¿Hay alguna manera de ejecutar solo un comando después de que otro se haga sin un archivo temporal? Tengo un comando más largo y otro comando que formatea el resultado y lo envía a un servidor HTTP usando curl. Si solo ejecuto commandA | commandB
, commandB
comenzaré curl
, me conectaré al servidor y comenzaré a enviar datos. Debido a que commandA
lleva tanto tiempo, el servidor HTTP se agota. Puedo hacer lo que quiera concommandA > /tmp/file && commandB </tmp/file && rm -f /tmp/file
Por curiosidad, quiero saber si hay una manera de hacerlo sin el archivo temporal. Lo intenté mbuffer -m 20M -q -P 100
pero el proceso de curl aún se inicia desde el principio. Mbuffer espera hasta que termine de commandA
enviar los datos. (Los datos en sí son solo unos pocos cientos de kb como máximo)
commandA && commandB
?commandA
acommandB
, ¿verdad?Respuestas:
Esto es similar a algunas de las otras respuestas. Si tiene el paquete "moreutils", debe tener el
sponge
comando. TratarEl
sponge
comando es básicamente un filtro de paso (comocat
) excepto que no comienza a escribir la salida hasta que haya leído toda la entrada. Es decir, "absorbe" los datos y luego los libera cuando los aprieta (como una esponja). Entonces, hasta cierto punto, esto es "trampa": si hay una cantidad de datos no trivial,sponge
casi con certeza usa un archivo temporal. Pero es invisible para ti; no tiene que preocuparse por cosas de limpieza como elegir un nombre de archivo único y limpiar después.El
{ IFS= read -r x; { printf "%s\n" "$x"; cat; } | commandB; }
lee la primera línea de salida desponge
. Recuerde, esto no aparece hasta quecommandA
haya terminado. Luego se disparacommandB
, escribe la primera línea en la tubería e invocacat
para leer el resto de la salida y escribirla en la tubería.fuente
sponge
lo que solía hacermbuffer
, pero parece ser más adecuado aquí. El uso de lectura es inteligente aquí. Definitivamente lo recordaré para el futuro.mbuffer
; en realidad podría ser tan bueno comosponge
. Estoy de acuerdo en que usarread
es un truco inteligente. No puedo tomar todo el crédito por ello; aparece de vez en cuando en las respuestas de Stack Exchange (U&L, Super User, Ask Ubuntu, etc.). De hecho, la respuesta de Roaima a esta pregunta es muy similar a la mía, excepto que no usasponge
(o algo equivalente), por lo que, como mencioné en un comentario, no demora el iniciocommandB
tanto como lo necesite (en mi entendimiento de tu problema).Los comandos en la tubería se inician simultáneamente, debe almacenar la
commandA
salida en algún lugar para usarla más tarde. Puede evitar el archivo temporal utilizando la variable:fuente
echo A
sustitución en el proceso?No conozco ninguna utilidad UNIX estándar que pueda solucionar este problema. Una opción sería usar
awk
para acumular lacommandA
salida y enjuagarla decommandB
una vez, asíTenga en cuenta que esto podría requerir mucha memoria, ya que
awk
está creando una cadena a partir de su entrada.fuente
\n
u otroORS
al final.Puede resolver el requisito con un pequeño script. Esta variante en particular evita el archivo temporal y el potencial consumo de memoria a expensas de procesos adicionales.
Si tuviera que llamar al script
waituntil
(y hacerlo ejecutable, ponerlo en elPATH
, etc.), lo usaría asíEjemplo
fuente
commandB
hasta quecommandA
haya escrito su primera línea de salida . Eso probablemente no sea lo suficientemente bueno.sponge
. Fuera para leer sobre eso ahora.