Existe uma maneira de executar apenas um comando depois que outro é feito sem um arquivo temporário? Eu tenho um comando mais em execução e outro comando que formata a saída e a envia para um servidor HTTP usando curl. Se eu apenas executar commandA | commandB
, commandB
iniciará curl
, conectará ao servidor e começará a enviar dados. Como commandA
leva tanto tempo, o servidor HTTP expirará. Eu posso fazer o que eu quero comcommandA > /tmp/file && commandB </tmp/file && rm -f /tmp/file
Por curiosidade, quero saber se existe uma maneira de fazer isso sem o arquivo temporário. Eu tentei, mbuffer -m 20M -q -P 100
mas o processo de enrolamento ainda é iniciado logo no início. O Mbuffer aguarda apenas o término do commandA
envio dos dados. (Os dados em si são apenas algumas centenas de kb no máximo)
commandA && commandB
?commandA
paracommandB
, transmite ?Respostas:
Isso é semelhante a algumas das outras respostas. Se você possui o pacote "moreutils", deve ter o
sponge
comando TentarO
sponge
comando é basicamente um filtro de passagem (comocat
), exceto que ele não começa a gravar a saída até ter lido toda a entrada. Ou seja, ele "absorve" os dados e os libera quando você os aperta (como uma esponja). Então, até certo ponto, isso é "trapaça" - se houver uma quantidade não trivial de dados,sponge
quase certamente usaremos um arquivo temporário. Mas é invisível para você; você não precisa se preocupar com tarefas domésticas, como escolher um nome de arquivo exclusivo e limpar depois.A
{ IFS= read -r x; { printf "%s\n" "$x"; cat; } | commandB; }
lê a primeira linha de saída dosponge
. Lembre-se, isso não aparece atécommandA
terminar. Em seguida, ele disparacommandB
, grava a primeira linha no canal e chamacat
para ler o restante da saída e gravá-lo no canal.fonte
sponge
acontece com o que eu useimbuffer
, mas parece ser mais adequado aqui. usar a leitura é inteligente aqui. Definitivamente vai se lembrar disso para o futuro.mbuffer
antes; pode ser tão bom quantosponge
. Concordo que usarread
é um truque inteligente. Eu não posso levar todo o crédito por isso; ele aparece nas respostas de tempos em tempos no Stack Exchange (U&L, Superusuário, Ask Ubuntu etc.). De fato, a resposta da roaima a essa pergunta é muito semelhante à minha, exceto que ela não usasponge
(ou algo equivalente); portanto, como mencionei em um comentário, não demora em iniciar ocommandB
quanto você precisa (no meu entendimento de seu problema).Os comandos na linha de tubulação são iniciados simultaneamente, você precisa armazenar a
commandA
saída em algum lugar para usar posteriormente. Você pode evitar o arquivo temporário usando a variável:fonte
echo A
substituição no processo?Não conheço nenhum utilitário UNIX padrão que possa resolver esse problema. Uma opção seria usar
awk
para acumularcommandA
saída e liberá-la decommandB
uma só vez, comoLembre-se de que isso pode exigir muita memória, pois
awk
está construindo uma sequência a partir de sua entrada.fonte
\n
ou outraORS
no final.Você pode resolver o requisito com um pequeno script. Essa variante específica evita o arquivo temporário e o possível consumo de memória à custa de processos adicionais.
Se você chamasse o script
waituntil
(e o tornasse executável, coloque-o noPATH
, etc), usaria assimExemplo
fonte
commandB
atécommandA
que a sua primeira linha de saída seja escrita . Provavelmente isso não é bom o suficiente.sponge
. Off para ler sobre isso agora.