Як обмежити розмір файлу журналу за допомогою >>


24

Як я можу обмежити розмір записаного файлу журналу >>на 200 МБ?

$ run_program >> myprogram.log

1
Ви хочете, щоб програма була вбита після 200 Мб? Або ви хочете останні 200 Мб зі всім старшим у відро для розрядів?
Аарон Д. Мараско

Ні, процес не може зупинитися, поки вручну не буде вбито
Девід

вирішив піти на логротат, дякую всім за цінні вкладення
Девід

Відповіді:


9

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

Ви також можете використовувати logrotate(8)для обертання своїх журналів, у ньому є sizeпараметр, який ви можете використовувати для своїх цілей:

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


1
+1 Журнали з повторною інформацією часто можуть стискатися в порядку величини.
користувач невідомий

Чи логротують усічені файли, або просто копіюють чи переміщують їх? Тому що це буде працювати лише в тому випадку, якщо файл, пов'язаний з fd, усічений. Якщо він mv'd, файл буде продовжувати рости, якщо він буде unlink'd, він буде просто відкритим і продовжуватиме розростатися до тих пір, поки процес не завершиться ... IIRC логретує копії, від’єднує і створює новий файл, тому часто доводиться надсилати SIGHUP до dæmons, коли їхні журнали повертаються.
Майкл Трауш

Зверніть увагу , що навіть якщо вона буде скорочуватися, є проблема , якщо файл не був відкритий в режимі додавання (лог - файли повинні бути завжди відкриті в режимі додавання, але в моєму досвіді, часто немає)
Random832

Logrotate може обертатися, коли файл досягає певного розміру, щодня, щотижня тощо. Він також може стискатися, і ви можете використовувати postscriptопцію, щоб конфігурація logrotate надсилала потім SIGHUPпрограмі.
маячка

12

Якщо вашій програмі не потрібно записувати жодні ІНШІ файли, які перевищували б це обмеження, ви можете повідомити ядро ​​про цей ліміт, використовуючи ulimit. Перш ніж запустити команду, запустіть це, щоб встановити ліміт розміру файлу 200 Мб для всіх запущених процесів у вашому поточному сеансі оболонки:

ulimit -f $((200*1024))

Це захистить вашу систему, але програма може записати файл. Як пропонує Eyazici , подумайте про налаштування logrotateдля обрізки файлів журналів після досягнення ними певного розміру або віку. Ви можете відкинути старі дані або архівувати їх протягом певного часу в серії стислих файлів.


це обмежує розмір будь-якого файлу, написаного програмою
Кім

Правда. Якщо в програмі була законна потреба писати інші великі файли, вам знадобиться інше рішення.
Калеб

6

Ви можете створити нове зображення файлової системи, змонтувати його за допомогою циклічного пристрою та розмістити файл журналу у цій файловій системі:

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замість файлу, якщо у вас достатньо пам'яті.


Творча ідея ... яка залишає його перед програмою щодо того, що робити, коли його закінчиться.
Аарон Д. Мараско

6

Вирізати вихід можна за допомогою head:

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

Дуже креативний. Лише зауважте, що це діятиме лише для обмеження запису НОВИХ даних у файл, воно не враховуватиме, наскільки великий або малий файл уже був.
Калеб

2
Зауважте, що, швидше за все, це вб'є програму (з SIGPIPE), коли вона досягне межі розміру, а не відкидає дані.
Випадково832

1
Я думав подібне з деякою ddмагією, але так @ Random832 вірно, ви отримаєте SIGPIPEяк head/ dd/ скидання whatever.
Аарон Д. Мараско

Що з ігноруванням цього з trap '' SIGPIPE?
tuxce

Або труба замість цього { head -c "$size" >> log; cat > /dev/null; }.
Стефан Шазелас

5

У пакеті 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

Повне керівництво ви можете прочитати за цим посиланням .


Посилання відсутня.
Олександр Гончій

1

Я впевнений, що оригінальний плакат знайшов рішення. Ось ще один для інших, хто може прочитати цю тему ...

Curtail обмежує розмір виходу програми і зберігає останні 200MB виводу за допомогою наступної команди:

$ run_program | curtail -s 200M myprogram.log

Список літератури

ПРИМІТКА: Я підтримую репортаж вище. Просто ділитися рішенням ...


Мені подобається ідея згортання. Я не такий знайомий з C, тож є можливість надати для нього двійковий файл? або хоча б докладні інструкції, як його встановити?
Феліпе

0

Оскільки це текст, я би написав сценарій вашою улюбленою мовою і додав би його до цього. Нехай він обробляє введення / виведення файлу (або зберігає його в пам’яті, а потім скидає на нього SIGHUPабо подібне). Для цього замість 200 МБ я б придумав "розумну" кількість рядків, які слід відслідковувати.


Збереження 200 МБ даних журналу з іншої причини, крім того, щоб мати можливість усікати, це не дуже вдале використання системних ресурсів. Також не робиться підрахунок рядків для великого файлу журналу. Я б рекомендував використовувати такі інструменти, як syslogі logrotate.
Калеб

0

Наступний сценарій повинен зробити цю роботу.

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, хоча, здавалося б, зайвим, без цього не вийде.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.