Назад | Перейти на главную страницу

Почему команда sed останавливает запись в мой файл журнала?

Я запускаю на сервере Gnu / Linux приложение myApp:

./myApp &>myApp.log &

Конечно, файл журнала скоро станет огромным.

Я бы хотел использовать sed уменьшить его (я знаю logrotate но мое приложение все еще черновик).

Но если я воспользуюсь такой командой

sed -i "1,200d" myApp.lo

файл действительно усечен, но после этого приложение больше не записывает в файл данные.

Зачем?

Когда файл открывается, система назначает ему дескриптор файла. Пока файл открыт, доступ к нему осуществляется через этот FD.

Когда вы запускаете команду sed, она обрезает файл, копируя его в новый файл. Вы можете видеть это, потому что номер inode изменяется

ls -i log
131122 log
sed -i "1,200d" log
ls -i log
131090 log

Что происходит, так это то, что файл записывается, вы усекаете его, копируя содержимое в другой файл, однако исходный файл остается открытым в myApp и все еще записывается в myApp, он просто помечается как готовый к удалению, когда myApp завершает работу. Вы можете увидеть это с помощью lsof.

lsof | grep myapp.log
myapp    11334  iain    1w  REG  253,2   54 131122 /home/iain/myapp.log
sed -i "1,200d" myapp.log
lsof | grep myapp.log
myapp    11334  iain    1w  REG  253,2  416 131122 /home/iain/myapp.log (deleted)

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

Если вы не можете изменить свое приложение для обработки сигналов, вы можете использовать файл fifo. я написал объяснение, как это сделать здесь некоторое время назад.

Ваш sed команда создаст новый файл и запишет обработанный вывод в этот файл. Затем он переименует новый файл, чтобы заменить старый файл.

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

Вам следует начать подготовку к использованию logrotate. Он не решит всех проблем, но может решить одну проблему - хранить несколько файлов журналов. То, что процесс продолжает запись в файл в течение некоторого времени после его поворота, не является препятствием.

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

Когда вы запускаете ./myApp &>myApp.log вывод команды перенаправляется в новый файл с именем myApp.log.

Когда вы запускаете свой sed -i "1,200d" myApp.log command создается новый файл с именем myApp.log.

Проблема здесь в том, что исходная команда все еще записывает в файл, который был создан изначально, но который был отключен и больше не имеет имени в файловой системе. Однако этот файл все еще остается, поскольку он все еще открыт.

Результатом этого является то, что вы не только больше не видите вывод после запуска команды sed, если вашей целью было освободить место, чего не происходит до тех пор, пока исходный файл не будет закрыт.