LINUX.ORG.RU

Как можно ограничить размер сохраняемого вывода?


0

1

Проблема: весь иксовый вывод я сохраняю в tmpfs

exec xinit -- -nolisten tcp &> /tmp/xsession.log

Естественно, проходит какое-то время, и в свопе у меня оказывается двести метров этого лога. Руками его порезать не удается, так как файл постоянно открыт.

Есть ли способ сбрасывать в файл только последние, скажем 10Мб? Например маленькая утилитка, которая слушает поток и автоматом сохраняет конец:

exec xinit -- -nolisten tcp |& trout 10MB /tmp/xsession.log

Написать такую тулзу не проблема, но может в практике администрирования уже есть готовое решение?

★★★

Ответ на: комментарий от baverman

выведет когда писун умрет.

Ты все-равно не сможешь нормально пользоваться выводом, если он будет писаться в файл до 10Мб, а потом seek'аться в начало и продолжать писать затирая предыдущее.

sdio ★★★★★
()
Ответ на: комментарий от sdio

выведет когда писун умрет.

Иксы не должны умирать до перезагрузки.

Ты все-равно не сможешь нормально пользоваться выводом

Как вариант, можно сбрасывать в два файла поочередно.

baverman ★★★
() автор топика
Ответ на: комментарий от x0r

logrotate может по особому обрезать файл, как этого нельзя сделать ручками?

Процесс держит открытым хендл на этот файл, и если его удалить или обрезать — эффект будет нулевой.

baverman ★★★
() автор топика
Ответ на: комментарий от baverman

baverman> Как вариант, можно сбрасывать в два файла поочередно.

Попробуй, если взлетит перепиши на awk/perl/C/...

#!/bin/sh
out=1
i=1
while read line; do
  if [ $i -gt 1000 ]; then
    # switch outfile
    if [ $out == '1' ]; then
       out=2
    else
       out=1
    fi

    # truncate new file
    :>/tmp/xsession${out}.log

    # drop line's counter
    i=1
  fi
  echo "$line" >> /tmp/xsession${out}.log
  i=$(($i+1))
done

З.Ы. писал прямо в браузер, так что возможны ляпы

sdio ★★★★★
()
Ответ на: комментарий от sdio

Спасибо, конечно за баш, но, право, не стоило. Как уже сказал, написать утилиту не проблема:

#!/usr/bin/env python2

import sys, fcntl, os
from select import select

def swap(names, idx):
    return open(names[idx], 'wb', 0), (idx + 1) % len(names)

def main(size, filename):
    infile = sys.stdin.fileno()
    fl = fcntl.fcntl(infile, fcntl.F_GETFL)
    fcntl.fcntl(infile, fcntl.F_SETFL, fl | os.O_NONBLOCK)

    names = [filename + '.0', filename + '.1']
    outfile, idx = swap(names, 0)
    collected = 0
    while True:
        readable, _, _ = select([infile], [], [])
        if readable:
            f = readable[0]
            while True:
                try:
                    data = os.read(f, 1024)
                except OSError, e:
                    if e.errno == 11:
                        data = None
                    else:
                        raise

                if not data:
                    break

                collected += os.write(outfile.fileno(), data)
                if collected > size:
                    outfile.close()
                    outfile, idx = swap(names, idx)
                    collected = 0

if __name__ == '__main__':
    main(int(sys.argv[1]), sys.argv[2])

Работает прекрасно, ест три метра rss, cpu нулевой.

baverman ★★★
() автор топика
Ответ на: комментарий от sdio

А шелл больше жрет что-ли?

Конкретно твой вариант, да. На каждую строку он открывает файл.

baverman ★★★
() автор топика
Ответ на: комментарий от sdio

И кстати, башевский read читает по одному байту, хе-хе.

baverman ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.