Тут задали мне юристы задачку. Они сканируют какие-то документы в JPG (родная софтина от сканера по-другому не умеет), а на выходе очень хотят получить PDF. Да не абы какой, а многостраничный. Чтобы N отсканированных страниц поместились бы в итоге в одном файле.
Естественно, покупать для этих целей полновесный Adobe-овский акробатический пакет жаба задушит. Есть прекрасные альтернативы типа того же самого ImageMagick, да вот только незадача: работают они из командной строки. Юристы навряд ли разберутся, хоть они у нас достаточно продвинутые и в делах компьютерных в том числе.
Стал чесать репу. Думаю: коль скоро у меня всё равно есть линуксовая файлопомойка, почему бы не заставить её заодно и картинки конвертировать? Сказано — сделано. На самбовой расшарке организовал отдельную папочку. Установил ImageMagick. На папочку натравил простенький шелл-скриптик такого вот содержания.
#!/bin/bash
DIR="/usr/share/samba/pdf"
umask 011
FILE="$DIR/"`/bin/date +%y%m%d%H%M`".pdf"
/usr/bin/find $DIR -iregex ".+\.jpe?g" -print0 | sort -z | \
xargs -r -0 /bin/bash -c \
'sudo -u nobody /usr/bin/convert "$0" "$@"'" $FILE "'&& rm "$0" "$@"'
Здесь find ищет внутри папки все файлы с расширениями "jpg" и "jpeg", найденное сортируется в алфавитном порядке при помощи sort, затем xargs-ом скармливается ImageMagick-у ("convert"). Результат складывается в файл, который именуется банально как текущая дата и время плюс расширение ".pdf".
Дальше возникает вопрос, по какому событию запускать этот скриптик. По крону? Можно, но как-то некрасиво. Вспоминаем, что в пингвиньем ядре существует достаточно эффективный механизм inotify. Надо только подобрать какую-нибудь утилитку, чтобы его попользовать. Первое что пришло в голову — lsyncd.
Вообще-то последний изначально задумывался как инструмент для синхронизации. Но с другой стороны, какая нам разница, коли он умеет "вешать" на папку notification-ы и запускать произвольный бинарник (или скрипт) по факту возникновения изменений в этой папке.
Начиная со 2-й версии конфиг для lsyncd пишется на Lua. Но в стабильном дебиане по умолчанию идет 1-ая версия, а гоняться за "свежаком" мне было, как обычно, лень. Поэтому я не стал выё выпендриваться и написал свои конфигушки на старом добром XML. Получилось что-то типа того.
<lsyncd version="1">
<settings>
<scarce/>
<logfile filename="/var/log/lsyncd/lsyncd.log"/>
<binary filename="/usr/local/bin/pdf"/>
<pidfile filename="/var/run/lsyncd/lsyncd.pid"/>
<delay value="30"/>
</settings>
<directory>
<source path="
/usr/share/samba/pdf
"/>
<target path="/dev/null"/>
</directory>
</lsyncd>
Обязательно задать какой-нибудь "source path" (папка, за которой следим) и "target path" (нужен для нормальной работы lsyncd). Остальные параметры не обязательны. Ключ "delay" говорит о том, сколько секунд надо подождать прежде чем начинать что-то делать. Действительно, мы заранее не знаем сколько файлов захочет положить в расшаренную папку пользователь. Но на гигабитной-то сети тридцати секунд должно по идее хватить с большим запасом на то, чтобы туда успело скопироваться всё что нужно. В "binary" указал путь до "конвертирующего" скрипта (см. выше).
Всё. Запускаем демон lsyncd и наслаждаемся эффектом. С точки зрения пользователя это выглядит следующим образом. Он копирует в заранее заданную расшаренную папку пачку JPG-файлов, ждет чуть меньше минуты, после чего забирает оттуда же готовый PDF. Просто и привычно.
Да, согласен, это колхозное решение. Более расово правильно было бы организовать какой-нибудь модный Web-интерфейс с AJAX-ом. Зато оно работает и может быть изготовлено "на коленке" менее чем за полдня любым знакомым с *nix системным администратором, даже не имеющим навыков программирования.
Ретранслировано из Я.ру