2015-05-13 2 views
1

Я пытаюсь создать конвейер unix команд, которые позволят мне записывать только текстовые строки вывода n в текстовый файл.Файл журнала буфера буфера на unix

Текстовый файл не должен превышать n строки длиной. (это может быть меньше при первом заполнении файла)

Он будет работать на устройстве с ограниченной памятью/ресурсами, поэтому сохранение размера файла является приоритетом.

Я пробовал такие вещи, как это (п = 500):

program_spitting_out_text > output.txt 
cat output.txt | tail -500 > recent_output.txt 
rm output.txt 

или

program_spitting_out_text | tee output.txt | tail -500 > recent_output.txt 

Очевидно ни работы для моих целей ...

Кто-нибудь есть хороший способ сделать это в однострочном лайнере? Или мне нужно написать скрипт/утилиту?

Примечание: Я не хочу иметь ничего общего с dmesg и должен использовать стандартные команды BSD unix. «Program_spitting_out_text» выводит около 60 строк в секунду каждую секунду.

Заранее благодарен!

+1

Открывает ли файл 'program_spitting_out_text' файл или открывается или закрывается для вывода строки журнала? – paxdiablo

+0

Что еще более важно - если вы хотите журнал, зачем вам нужно только несколько переходных линий. Предположим, вы получили условие ошибки. Планируете ли вы читать вещи в реальном времени? Именно это и займет этот проект. Вам нужно подумать о переносе данных из другого места. В противном случае не беспокойтесь о журнале. –

+0

В чем проблема с вашим вторым вариантом? (исключая, конечно, часть 'tee') – Diego

ответ

2

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

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


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

Просто контролировать файл до тех пор, пока не достигнет определенного размера, затем обвалять файл снова, что-то вроде:

while true; do 
    sleep 5 
    lines=$(wc -l <file.log) 
    if [[ $lines -ge 5000 ]]; then 
     rm -f file2.log 
     mv file.log file2.log 
     touch file.log 
    fi 
done 

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

Это означает, что вы всегда будете иметь (примерно) от пяти до десяти тысяч строк в наборе файлов журнала, и вы можете найти их с командами, которые сочетают в себе два:

grep ERROR file2.log file.log 

Другая возможность если вы можете периодически перезапускать программу, не затрагивая ее функцию. Например, программа, которая ищет наличие файла один раз в секунду и сообщает об этом, возможно, может быть перезапущена без проблем. Один расчет PI до ста миллиардов значащих цифр, вероятно, будет не может быть перезапущен без воздействия.

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

Для примера рассмотрим следующую программу prog.sh (Перезапускаемые), который просто непрерывно выводит текущую дату и время:

#!/usr/bin/bash 
while true; do 
    date 
done 

Затем, следующий сценарий будет отвечать за запуск и остановка другой сценарий, как это необходимо, проверяя лог-файл каждые пять секунд, чтобы увидеть, если он превысил свои пределы:

#!/usr/bin/bash 

exe=./prog.sh 
log1=prog.log 
maxsz=500 

pid=-1 
touch ${log1} 
log2=${log1}-prev 

while true; do 
    if [[ ${pid} -eq -1 ]]; then 
     lines=${maxsz} 
    else 
     lines=$(wc -l <${log1}) 
    fi 
    if [[ ${lines} -ge ${maxsz} ]]; then 
     if [[ $pid -ge 0 ]]; then 
      kill $pid >/dev/null 2>&1 
     fi 
     sleep 1 
     rm -f ${log2} 
     mv ${log1} ${log2} 
     touch ${log1} 
     ${exe} >> ${log1} & 
     pid=$! 
    fi 
    sleep 5 
done 

И этот выход (от каждой секунды wc -l на два лог-файлах) показывает, что происходит на время переключения, отметив, что это приблизительная только из-за задержек, связанных с переключением:

474 prog.log  0 prog.log-prev 
496 prog.log  0 prog.log-prev 
518 prog.log  0 prog.log-prev 
539 prog.log  0 prog.log-prev 
542 prog.log  0 prog.log-prev 
21 prog.log  542 prog.log-prev 

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


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

Тогда вы бы просто сделать:

program_spitting_out_text | ringbuffer 4096 last4k.log 

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

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

+0

Спасибо, @paxdiablo. Я думал об этом пинг-понге между лог-файлами, но я надеялся, что я упустил какой-то классный однострочный лайнер, который выполнит эту работу. – MRT89

Смежные вопросы