ImageMagick / GraphicsMagick: Как объединить / составить несколько (3+) изображений без временных файлов за один шаг?

Несоответствие протокола готовности. Вы сказали systemd, что ваша программа разветвляет дочерний процесс, а затем выходит из родительского процесса, чтобы сигнализировать о том, что он готов. Но на самом деле ваша программа этого не делает. Поскольку не указано, что он будет готов в течение 90 секунд (тайм-аут запуска по умолчанию), systemd решил, что ваша служба не работает. Неудачные службы убивают все. Из-за при сбое ваша отказавшая служба затем перезапускается, и цикл повторяется.

Используйте протокол готовности, который правильно описывает, что на самом деле делает ваша программа. Этого вы нам не сказали.

Дополнительная литература

1
05.12.2016, 14:54
2 ответа

Это не ответ на поставленный вопрос, а лишь отступление, показывающее, что предпосылка исходного вопроса, что "временный файл ... должен быть удален вручную", совершенно неверна.

(Я опубликовал этот "ответ" в том случае, если заметить, что эта предпосылка ложна, позволит ОП и другим людям не стесняться использовать временные файлы. Во многих случаях использование временных файлов делает скрипты более надежными и более простыми в сопровождении.)

Если скрипту Bash необходимо использовать один или несколько временных файлов, я всегда использую следующий подход:

#!/bin/bash
work="$(mktemp -d)" || exit 1
trap "cd / ; rm -rf '$work'" EXIT

Здесь используется помощник mktemp для создания временного рабочего каталога (в /tmp/). Если mktemp недоступен или каталог не может быть создан, сценарий прерывается.

Чтобы автоматически удалить рабочий каталог и все файлы, которые он может содержать, мы устанавливаем ловушку EXIT. Эта ловушка срабатывает - то есть bash выполняет указанную команду - всякий раз, когда shell завершает работу; будь то обычный выход или из-за ошибки.

Команда EXIT trap переходит в корневой каталог (просто чтобы убедиться, что текущий рабочий каталог не находится во временном каталоге), а затем удаляет все поддерево. Обратите внимание, что поскольку команда заключена в двойные кавычки, $work оценивается при установке ловушки; это означает, что даже если вы измените значение переменной work позже в сценарии, ловушка все равно удалит исходный временный каталог.

Хотя ловушка изменяет текущий рабочий каталог, это не будет иметь никакого эффекта за пределами ловушки - ни в сценарии в другом месте, ни для других процессов - потому что текущий рабочий каталог специфичен для каждого процесса, а текущий процесс bash завершится сразу после выполнения команды ловушки.

Поэтому любые временные файлы, созданные под $work, например "$work/1", "$work/result" и так далее, автоматически удаляются, как и сам временный каталог $work, после завершения работы скрипта.

1
27.01.2020, 23:25

Из первоначального запроса я понимаю, что вам нужно объединить 3 изображения (1 из файла и 2 сгенерированных) в один снимок, учитывая, что вы можете одновременно работать только с 2.

Я также понимаю, что вам не нужно хранить временные данные на диске. Самым быстрым решением было бы использовать tmpfs, как было предложено в предыдущем ответе @ nominal-animal.

Но если пойти дальше, можно избежать создания временных файлов и в основном выполнять всю обработку за один раз. Решение, которое я нашел, заключается в использовании "именованных каналов", это специальные файлы, которые не хранят данные на диске и даже приостанавливают любую передачу по каналам, пока принимающая часть также не будет готова. Я не буду использовать полную Команды, которые вы указали (только команда, ввод и вывод), не стесняйтесь вводить необходимые аргументы.

# First it's necessary to have the pipes created, one time operation and they can be reused over and over.
mknod /tmp/pipe1 p
mknod /tmp/pipe2 p
mknod /tmp/pipe3 p

# generate the 2 images and send each to a pipe 
gm convert ... miff:- > pipe1 &
gm convert ... miff:- > pipe2 &
# merge the source image to the 1st generated image
gm composite ... source.tif pipe1 miff:- > pipe3 &
# finally merge the result to the 2nd generated image
gm composite ... pipe3 pipe2 out.tif

Похоже, что операция выполняется в 4 этапа, но на самом деле все будет выполнено за один раз без записи на диск.

Вот как это работает и почему команды написаны так, как они есть:

  • команда для генерации 1-го изображения начнет работать по запросу, но вывод должен идти в именованный канал. Поскольку в этот момент из канала ничего не читается, вывод остановится в ожидании приема. Процесс не будет завершаться или отображать какую-либо ошибку, поэтому для продолжения он помещается в фоновый режим.
  • 2-е изображение то же самое, только другая труба.
  • объединение исходного изображения и данных из 1-го конвейера приведет к тому, что он будет читать из конвейера 1 и освободить 1-ю команду генерации, но поскольку его вывод идет в другой конвейер, ему придется дождаться последнего шага.
  • объединение данных из конвейера 3 и конвейера 2 завершит операцию, сгенерирует желаемый выходной файл и освободит предыдущие 2 команды.

Вы можете рассматривать каналы как временные файлы, которые не являются файлами, просто не забудьте поместить некоторые вещи в фоновый режим, иначе сценарий будет ждать вашего CTRL + C. Каждую команду нужно ставить в фоновый режим отдельно! Нет проблем, если вы поместите их в сценарий, подобный этому, после того, как сгенерированы выходные данные, до которых завершились предыдущие команды.

Приятной особенностью является то, что вы можете запускать любые 3 команды сначала в фоновом режиме, а последнюю - в обычном режиме, поскольку все 4 зависят от данных из каналов. Также его легко расширить на несколько команд, просто добавив больше каналов.

Есть одно ограничение, которое я вижу, вы не можете использовать одни и те же каналы параллельно, если вам нужно, вы должны использовать разные наборы каналов для каждого экземпляра, работающего параллельно, иначе будут сюрпризы :) {{1 }} Последовательная обработка не имеет такой проблемы.

С точки зрения производительности, я не знаю, быстрее ли это, чем создание временных файлов в "tmpfs", поэтому вам нужно будет выяснить это путем тестирования в реальном сценарии. Чтобы это сработало, вы должны иметь достаточно памяти для размещения всех 4 процессов с их данными в памяти. (это во многом зависит от размера изображений, которые вы обрабатываете / генерируете).

2
27.01.2020, 23:25

Теги

Похожие вопросы