Как ограничить размер файла журнала, используя >>

Как я могу ограничить размер файла журнала, написанного с помощью >> до 200 МБ?

 $ run_program >> myprogram.log 

Если ваше приложение (то есть run_program ) не поддерживает ограничение размера файла журнала, вы можете периодически проверять размер файла в цикле с помощью внешнего приложения или скрипта.

Вы также можете использовать logrotate(8) для поворота ваших журналов, у него есть параметр size который вы можете использовать для своей цели:

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

Если вашей программе не нужно писать какие-либо ДРУГИЕ файлы, которые были бы больше этого предела, вы можете сообщить ядру этого предела, используя ulimit . Перед запуском вашей команды запустите это, чтобы установить ограничение размера файла 200 МБ для всего запуска процесса в текущем сеансе оболочки:

 ulimit -f $((200*1024)) 

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

Вы можете усекать вывод с помощью head :

 size=$((200*1024*1024-$(stat -c %s myprogram.log))) run_program | head -c ${size} >> myprogram.log 

Вы можете создать образ новой файловой системы, смонтировать его с помощью устройства loop и поместить файл журнала в эту файловую систему:

 dd if=/dev/zero of=./200mb.img bs=1024 count=200000 # create new empty 200MB file mkfs.ext2 200mb.img # or ext3, or whatever fits your needs mkdir logs sudo mount -t ext2 -o loop 200mb.img logs # only root can do '-o loop' by default run_program >>logs/myprogram.log 

Вы также можете использовать tmpfs вместо файла, если у вас достаточно памяти.

В пакете apache2-utils присутствует утилита, называемая rotatelogs , она может быть полезна для вас.

Сводка:

rotatelogs [-l] [-L linkname ] [-p program ] [-f] [-t] [-v] [-e] [-c] [-n number-of-files ] logfile rotationtime | filesize (B | K | M | G) [ смещение ]

Пример:

 your_program | rotatelogs -n 5 /var/log/logfile 1M 

Полное руководство вы можете прочитать по этой ссылке .

Поскольку это текст, я бы написал сценарий на вашем любимом языке и применил его к этому. Попросите его обработать файл ввода / вывода (или сохранить все в памяти, а затем сбросить его на SIGHUP или аналогичный). Для этого, вместо 200 МБ, я бы подумал о «разумном» количестве строк для отслеживания.

Следующий сценарий должен выполнить эту работу.

 LOG_SIZE=500000 NUM_SEGM=2 while getopts "s:n:" opt; do case "$opt" in s) LOG_SIZE=$OPTARG ;; n) NUM_SEGM=$OPTARG ;; esac done shift $((OPTIND-1)) if [ $# == 0 -o -z "$1" ]; then echo "missing output file argument" exit 1 fi OUT_FILE=$1 shift NUM=1 while :; do dd bs=10 count=$(($LOG_SIZE/10)) >> $OUT_FILE 2>/dev/null SZ=`stat -c%s $OUT_FILE` if [ $SZ -eq 0 ]; then rm $OUT_FILE break fi echo -e "\nLog portion finished" >> $OUT_FILE mv $OUT_FILE $OUT_FILE.n$NUM NUM=$(($NUM + 1)) [ $NUM -gt $NUM_SEGM ] && NUM=1 done 

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

Обратите внимание на небольшую gotcha, если вы используете ее с демоном, который вилки на фоне. Использование трубы предотвратит переход демона к фону. В этом случае существует синтаксис (вероятный баш-специфический), чтобы избежать проблемы:

 my_daemon | ( logger.sh /var/log/my_log.log <&0 & ) 

Обратите внимание на <&0 , но, похоже, избыточно, это не сработает без этого.