Странные упражнения с xargs-ом

Oct 07, 2019 21:52


Вот какие интересные упражнения получаются. Выполним простенький скриптик. Чтобы вы не лазили почем зря по man-ам, сразу напишу ключи запуска xargs-а слева направо: выполнять в два потока, принимать со стандартного входа максимум по 3 аргумента за проход, запустить команду "/bin/sleep" с полученными со стандартного входа (stdin) аргументами. То есть, грубо говоря, выполнить "/bin/sleep 5 5 5" в два потока.
while true ; do echo "5" ; done | xargs -P 2 -n 3 /bin/sleep | cat > some.file
При помощи заклинания "ps axf" в соседней консоли смотрим что получилось (да, я "сижу" под "гномом"):
1996 ? Rsl 0:21 \_ /usr/lib/gnome-terminal/gnome-terminal-server
2001 pts/0 Ss 0:01 | \_ bash
26913 pts/0 S+ 0:00 | | \_ bash
26914 pts/0 S+ 0:00 | | \_ xargs -P 2 -n 3 /bin/sleep
26916 pts/0 S+ 0:00 | | | \_ /bin/sleep 5 5 5
26917 pts/0 S+ 0:00 | | | \_ /bin/sleep 5 5 5
26915 pts/0 S+ 0:00 | | \_ cat

Внатуре видим два процесса "sleep". Но! Обратите внимание, что на стандартный ввод cat-а (процесс 26915) подаётся вывод не sleep-ов (26916 и 26917), а xargs-а (26914). Допустим, меня такой расклад по каким-то причинам не устраивает. Я хочу писать в "some.file" вывод именно что sleep-ов (я знаю, что они ничего не выдают, но это синтетическое упражнение). Тогда я заменяю конструкцию на вот такую.
while true ; do echo "5" ; done |\
xargs -P 2 -n 3 -I'{}' /bin/bash -c "/bin/sleep {} | cat > some.file"
И получаю в списке процессов вот такую картину:
1996 ? Rsl 0:24 \_ /usr/lib/gnome-terminal/gnome-terminal-server
2001 pts/0 Ss 0:01 | \_ bash
26954 pts/0 S+ 0:00 | | \_ bash
26955 pts/0 S+ 0:00 | | \_ xargs -P 2 -n 3 -I{} /bin/bash -c /bin/sleep {} | cat > some.file
26956 pts/0 S+ 0:00 | | \_ /bin/bash -c /bin/sleep 5 | cat > some.file
26960 pts/0 S+ 0:00 | | | \_ /bin/sleep 5
26961 pts/0 S+ 0:00 | | | \_ cat
26957 pts/0 S+ 0:00 | | \_ /bin/bash -c /bin/sleep 5 | cat > some.file
26958 pts/0 S+ 0:00 | | \_ /bin/sleep 5
26959 pts/0 S+ 0:00 | | \_ cat

Сравните с предыдущим примером и почувствуйте разницу. Вот тут уже всё как мне надо: в два потока запустился sleep, каждый из них "гадит" в свой собственный отдельный cat, который, в свою очередь, складывает всё это безобразие в "some.file". Вроде бы то что надо.

Но постойте! В первом примере у sleep было три ключа запуска, а во втором оказался всего один! Как же так?!

Очень просто. Параметр "-I" у xargs-а автоматически отменяет скармливание дочернему бинарнику пачки аргументов. В таком режиме он работает по принципу "один выстрел - один труп один запуск - один аргумент".

Вопрос-загадка для самых въедливых и просто сочувствующих. Допустим, мы подаем на вход xargs-у что-то осмысленное и вместо sleep-а используем какой-нибудь, например, текстовый процессор. Или что-нибудь ещё полезное. В чём будет заключаться принципиальная разница в результате (в содержимом файла "some.file") между первым и вторым вариантом?

И вопрос, который прямо сейчас волнует лично меня и не даёт мне спать. Можно ли как-то и на ёлку влезть и руки не поцарапать совместить оба варианта так, чтобы и несколько аргументов, и водопровод (pipe) у каждого из подпроцессов был бы свой собственный?

Объясню почему меня это так интересует. Пусть для определенности на входе у xargs-а будет список gz-файлов, в качестве выполняемой команды zcat, а потом всё это надо отправить на стандартный ввод условному mysql-ю. То бишь.
xargs -0 -a some_gz.list -L 1 -P 4 -n 20 zcat | mysql someDB
Но да, так работать не будет. Почему - это уже третий вопрос для самых въедливых. А мне надо чтоб работало.

linux, bash

Previous post Next post
Up