Как я могу ограничить размер файла журнала, записанного с >>200 МБ?
$ run_program >> myprogram.log
Как я могу ограничить размер файла журнала, записанного с >>200 МБ?
$ run_program >> myprogram.log
Ответы:
Если ваше приложение (т.е. run_program) не поддерживает ограничение размера файла журнала, вы можете периодически проверять размер файла в цикле с помощью внешнего приложения или сценария.
Вы также можете использовать, logrotate(8)чтобы вращать ваши журналы, у него есть sizeпараметр, который вы можете использовать для своих целей:
При этом файл журнала поворачивается при достижении указанного размера. Размер может быть указан в байтах (по умолчанию), килобайтах (sizek) или мегабайтах (sizem).
postscriptопцию для отправки конфигурации logrotate SIGHUPв программу.
Если вашей программе не нужно записывать какие-либо ДРУГИЕ файлы, которые были бы больше этого предела, вы можете сообщить ядру об этом пределе, используя ulimit. Перед тем, как выполнить команду, запустите ее, чтобы установить ограничение размера файла 200 МБ для всех процессов, запущенных в текущем сеансе оболочки:
ulimit -f $((200*1024))
Это защитит вашу систему, но это может вызвать проблемы с программой, записывающей файл. Как рекомендует eyazici , подумайте о том , чтобы настроить удалениеlogrotate файлов журнала, когда они достигнут определенного размера или возраста. Вы можете удалить старые данные или заархивировать их на некоторое время в виде ряда сжатых файлов.
Вы можете создать новый образ файловой системы, смонтировать его с помощью устройства 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вместо файла, если у вас достаточно памяти.
Вы можете усечь вывод с помощью head:
size=$((200*1024*1024-$(stat -c %s myprogram.log)))
run_program | head -c ${size} >> myprogram.log
SIGPIPE), как только она достигнет предела размера, а не отбросит данные.
ddмагией, но да @ Random832 прав, вы получите SIGPIPEas head/ dd/ whateverотбрасываете его.
trap '' SIGPIPE?
{ head -c "$size" >> log; cat > /dev/null; }.
В пакете apache2-utilsприсутствует утилита под названием rotatelogs, она может быть вам полезна.
Сводка:
rotatelogs [-l] [-L linkname ] [-p программа ] [-f] [-t] [-v] [-e] [-c] [-n количество файлов ] время ротации файла журнала | размер файла (B | K | M | G) [ смещение ]
Пример:
your_program | rotatelogs -n 5 /var/log/logfile 1M
Полное руководство вы можете прочитать по этой ссылке .
Я уверен, что оригинальный плакат нашел решение. Вот еще один для других, которые могут читать эту тему ...
Curtail ограничивает размер вывода программы и сохраняет последние 200 МБ вывода с помощью следующей команды:
$ run_program | curtail -s 200M myprogram.log
ПРИМЕЧАНИЕ: я поддерживаю вышеупомянутое РЕПО. Просто делюсь решением ...
Поскольку это текст, я бы написал сценарий на вашем любимом языке и направил его на это. Сделайте так, чтобы он обрабатывал файловый ввод / вывод (или сохранял все это в памяти, а затем сбрасывал его SIGHUPили тому подобное). Для этого вместо 200 МБ я бы подумал о «разумном» количестве строк для отслеживания.
syslogи logrotate.
Следующий скрипт должен сделать эту работу.
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
У него есть несколько очевидных коротких путей, но в целом он делает то, что вы просили. Это разделит журнал на куски ограниченного размера, и количество кусков также ограничено. Все можно указать с помощью аргументов командной строки. Файл журнала также указывается через командную строку.
Обратите внимание на небольшую ошибку, если вы используете ее с демоном, который разветвляется на задний план. Использование канала предотвратит переход демона в фоновый режим. В этом случае есть (вероятно, специфичный для bash) синтаксис, чтобы избежать проблемы:
my_daemon | ( logger.sh /var/log/my_log.log <&0 & )
Обратите внимание, что <&0, несмотря на внешнюю избыточность, без этого не получится.