Возникла у меня как-то задача обработать файл с логами. В принципе, задача банальная, я для этого использую Perl и в Linux и в Windows. Но дело в том, что всё это происходит на Mac, файл находится в архиве и он большой. Распакованным, он занимает около 20 ГБ.
Какое будет обычное решение?
Если бы файл был небольшой, то его можно просто достать из архива и подать на вход скрипта. Но это не так, и место на диске тратить жалко. Для этого есть стандартное решение распаковывать файл в STDOUT и сразу забирать его обработчиком из STDIN (через безымянный pipe, символ "|"). Сказано, сделано. У стандартного в Mac'е распаковщика есть параметры для этого.
unzip -p data.zip log.txt | process.pl > result.txt
Где, process.pl обработчик логов.
После тестирования на небольших файлах всё было отлажено и я перешел к рабочему файлу. Но тут меня ждал сюрприз. Файл обрабатывался моментально, но результат был пустой. Оказалось, что файлы больше 4 ГБ не распаковываются. Ха-ха, и это в 64-разрядной операционке. После гугления оказалось, что да, есть такая проблема. Поговаривают даже, что файл запаковать можно, а распаковать нет. Некоторые программы, которые предлагались, по описанию было хорошие, например, The Unarchiver (http://wakaba.c3.cx/s/apps/unarchiver.html), но имели только графический интерфейс, ну да, конечно, это же Mac. К счастью нашлась еще одна утилита, unar (http://code.google.com/p/theunarchiver/downloads/list) от того же автора, которая умеет работать с командной строкой. Всё классно, но… она умеет распаковывать только в файл, да то только с оригинальным именем. И что же делать? Я уж было решил искать что-то ещё, но вовремя вспомнил про именованные каналы (named pipe), которые позволяет сделать псевдо-файл на диске, который выступает как конвеер, куда одна программа пишет, другая читает и обе считают, что работают с настоящим файлом. То есть план действия получался такой:
1. Создаем именованный канал с именем совпадающим с запакованным файлом:
mkfifo log.txt
2. Запускаем обработчик, который будет читать данные их него. Запустим его с символом &, чтобы он работал в фоновом режиме, иначе он будет ждать данные и не освободит терминал, пока не закончит полную обработку:
./process.pl <log.txt >results.txt &
3. Теперь можно запустить распаковку:
./unar -D -f data.zip log.txt
Параметр -D не создавать директорию.
-f игнорировать, если файл с таким именем уже существует.
4. После окончания работы удалить именованный канал:
unlink log.txt
Всё отлично, всё работает. Естественно, что все описанное выше можно использовать и в обычном Linux'е.
Автор: varerysan