Есть ли способ выполнить команду только после выполнения другой без временного файла? У меня есть одна более длинная команда и другая команда, которая форматирует вывод и отправляет его на HTTP-сервер с помощью curl. Если я просто выполню commandA | commandB
, commandB
запустится curl
, подключусь к серверу и начну отправку данных. Потому что commandA
занимает так много времени, HTTP-сервер будет тайм-аут. Я могу делать то, что я хочу сcommandA > /tmp/file && commandB </tmp/file && rm -f /tmp/file
Из любопытства я хочу знать, есть ли способ сделать это без временного файла. Я пытался, mbuffer -m 20M -q -P 100
но процесс скручивания все еще начинается в самом начале. Mbuffer ждет, пока commandA
не закончится фактическая отправка данных. (Данные сами по себе не более нескольких сотен килобайт)
commandA && commandB
?commandA
вcommandB
, не так ли?Ответы:
Это похоже на пару других ответов. Если у вас есть пакет «moreutils», у вас должна быть
sponge
команда. ПытатьсяКоманда
sponge
в основном является сквозным фильтром (напримерcat
), за исключением того, что она не начинает записывать вывод, пока не прочитает весь ввод. То есть он «впитывает» данные, а затем освобождает их, когда вы сжимаете их (как губка). Так что, в определенной степени, это «обман» - если есть нетривиальный объем данных,sponge
почти наверняка используется временный файл. Но это невидимо для вас; Вам не нужно беспокоиться о таких вещах, как выбор уникального имени файла и его очистка.{ IFS= read -r x; { printf "%s\n" "$x"; cat; } | commandB; }
Считывает первую линию выхода изsponge
. Помните, это не появится, покаcommandA
не закончится. Затем он запускаетсяcommandB
, записывает первую строку в канал и вызываетcat
чтение остальной части вывода и запись его в канал.источник
sponge
же самое, что я использовалmbuffer
для, но, кажется, лучше подходит здесь. Использование чтения - это умно. Определенно запомним это на будущее.mbuffer
раньше; на самом деле это может быть так же хорошо, какsponge
. Я согласен, что использованиеread
это умный трюк. Я не могу взять полный кредит на это; время от времени он появляется в ответах в Stack Exchange (U & L, Super User, Ask Ubuntu и т. д.). На самом деле ответ roaima на этот вопрос очень похож на мой, за исключением того, что он не используетsponge
(или что-то эквивалентное), поэтому, как я упоминал в комментарии, он не задерживает запускcommandB
столько, сколько вам нужно (в моем понимании твоя проблема).Команды в конвейере запускаются одновременно, вам нужно хранить
commandA
выходные данные где-то, чтобы использовать позже. Вы можете избежать временного файла, используя переменную:источник
echo A
в процессе замены?Я не знаю ни одной стандартной утилиты UNIX, которая могла бы решить эту проблему. Одним из вариантов будет использование
awk
для накопленияcommandA
выходного сигнала и сброса егоcommandB
в один выстрел, например, такПомните, что это может занять много памяти, так
awk
как строит строку из своего ввода.источник
\n
или другойORS
в конце.Вы можете решить требование с помощью небольшого сценария. Этот конкретный вариант позволяет избежать временного файла и потенциального сбоя памяти за счет дополнительных процессов.
Если бы вы вызывали скрипт
waituntil
(и делали его исполняемым, помещали его в иPATH
т. Д.), Вы бы использовали его следующим образомпример
источник
commandB
доcommandA
тех пор, пока не будет написана первая строка вывода . Это, вероятно, не достаточно хорошо.sponge
. Прочь, чтобы прочитать об этом сейчас.