(←) предыдущая запись ; следующая запись (→)
Откуда у меня вообще взялось странное желание писать
echo cmd | bash
У нас часто возникает задача обработать много файлов одним и тем же способом. Писать многопоточный питоновский код довольно нетривиально и обычно незачем. Самый простой и надёжный способ загрузить все ядра сервера — написать однопоточную утилиту и запустить несколько процессов одновременно. Для этого есть удобная утилита GNU parallel [Tange 2011].
Ей на вход можно передать набор команд, а она их сама запустит в нужном числе процессов. Этакая очередь задач на минималках. Вдобавок ко всему, parallel ещё и распечатает результат так, будто все процессы были запущены последовательно (а не как в этих жутких примерах про race condition, где вывод параллельно запущенных программ перемешивается).
Сейчас мой любимый подход для распараллеливания вычислений выглядит так:
for FILENAME in $(find ./in/folder -xtype f); do
echo ./process_data $FILENAME --ton-of-tricky-configs
done | parallel
Если надо запустить в один поток, меняете parallel
на bash
. Если хотите удостовериться, что правильно сформировали команды, просто убираете команду запуска. Или заменяете parallel
на cat
/ head
. Очень удобно!
p.s. В более сложных кейсах, где генератор команд на баше писать неудобно, можно написать скрипт генерации команд на вашем любимом языке:
ruby -e 'Dir.glob("folder/*.txt").each{|fn| bn = File.basename(fn, ".txt"); cmd = "mv #{fn} another_folder/#{bn.upcase}"; puts cmd }' | parallel
References:
O. Tange (2011): GNU Parallel - The Command-Line Power Tool,
;login: The USENIX Magazine, February 2011:42-47.
Должен же я хоть раз в жизни процитировать тул, который так настойчиво об этом просит