У меня есть куча изображений PNG в каталоге. У меня есть приложение pngout, которое я запускаю для сжатия этих изображений. Это приложение вызывается скриптом, который я сделал. Проблема в том, что этот скрипт делает по одному, что-то вроде этого:
FILES=(./*.png)
for f in "${FILES[@]}"
do
echo "Processing $f file..."
# take action on each file. $f store current file name
./pngout -s0 $f R${f/\.\//}
done
Обработка только одного файла за раз, занимает много времени. После запуска этого приложения я вижу, что загрузка процессора составляет всего 10%. Итак, я обнаружил, что могу разделить эти файлы на 4 пакета, поместить каждый пакет в каталог и запустить 4 из четырех окон терминала, четырех процессов, поэтому у меня есть четыре экземпляра моего сценария, одновременно обрабатывающие эти изображения и работа занимает 1/4 времени.
Вторая проблема заключается в том, что я потерял время, разделяя изображения и пакеты и копируя скрипт в четыре директории, открывая 4 окна терминала, бла-бла ...
Как это сделать с одним сценарием, без необходимости что-либо делить?
Я имею в виду две вещи: во-первых, как мне из сценария bash запустить процесс в фоновом режиме? (просто добавьте & в конец?) Второе: как я могу прекратить отправку задач в фоновом режиме после отправки четвертых задач и поставить сценарий для ожидания завершения задач? Я имею в виду, просто отправка новой задачи в фоновом режиме, когда одна задача заканчивается, и всегда остается 4 параллельных задачи? если я не сделаю этого, цикл запустит миллионы задач в фоновый режим, и процессор засорится.
источник
Ответы:
Если у вас есть копия,
xargs
которая поддерживает параллельное выполнение с-P
, вы можете просто сделатьЧто касается других идей, в Wooledge Bash wiki есть раздел в статье «Управление процессами», в котором описывается именно то, что вы хотите.
источник
pngout
команды, которую OP хотел выполнить. Ключевой параметр-P 4
, который говорит Xargs использовать до 4 одновременных команд.printf
здесь функцию, а не просто обычнуюls .. | grep .. *.png
? Также меня интересовалиxargs
параметры, которые вы использовали (-0
а-I{}
). Благодарность!ls
не могут использоваться для удобного и безопасного анализа имен файлов . Единственными безопасными символами, используемыми для разделения имен файлов, являются\0
и/
, поскольку любой другой символ, в том числе\n
, может быть частью самого имени файла. Вprintf
использует\0
для имен файлов разграничить, и-0
информируетxargs
об этом.-I{}
Говоритxargs
заменить{}
с аргументом.В дополнение к уже предложенным решениям вы можете создать make-файл, который описывает, как сделать сжатый файл из несжатого, и использовать его
make -j 4
для параллельного запуска 4 заданий. Проблема в том, что вам нужно будет по-разному называть сжатые и несжатые файлы или хранить их в разных каталогах, иначе будет невозможно написать разумное правило make.источник
Если у вас установлен GNU Parallel http://www.gnu.org/software/parallel/, вы можете сделать это:
Вы можете установить GNU Parallel просто:
Посмотрите вступительные видео для GNU Parallel, чтобы узнать больше: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
источник
Чтобы ответить на два ваших вопроса:
wait
команду, вы можете попросить оболочку дождаться завершения всех процессов в фоновом режиме, прежде чем продолжить.Вот скрипт, модифицированный так, чтобы
j
он использовался для отслеживания количества фоновых процессов. ПриNB_CONCURRENT_PROCESSES
достижении сценарий сбрасываетсяj
до 0 и ожидает завершения всех фоновых процессов, прежде чем возобновить его выполнение.источник
$f
и т. Д. (3) Используйте[
для POSIX-совместимых скриптов, но для чистого bash[[
всегда предпочтительнее. В этом случае((
больше подходит для арифметики.