хвіст -f, вставити перерву рядка після простою журналу протягом 3 секунд?


14

Як робити tail -f error.log, як програматично вставити розрив рядка після того, як у файл протягом 3 секунд нічого не було додано?

(очевидно, щойно додано один розрив рядка, жоден інший розрив рядка не слід додавати, поки інші файли тексту не будуть додані до файлу журналу)

Наприклад, ці рядки додаються до error.log:

foo
bar
boo [[wait 4 seconds]]
2far
2foo
2bar
2boo [[wait 40 seconds]]
2far

Це буде вихід на консолі:

foo
bar
boo

2far
2foo
2bar
2boo

2far

Ви, ймовірно, можете адаптувати мою функцію в askubuntu.com/a/993821/158442 , або скористатися tsдля додавання часових позначок до виводу та обробки часових міток
muru

1
Варто зазначити, що якщо ви робите це в інтерактивному режимі, ви можете просто натиснути клавішу введення кілька разів. :)
Wildcard

Відповіді:


12

Ви завжди можете реалізовувати tail -f(ну тут, якщо ви не відмежуєте це seek(), більше, як, наприклад tail -n +1 -f, ми завантажуємо весь файл) вручну, perlнаприклад:

perl -e '
  $| = 1;
  # seek STDIN, 0, 2; # uncomment if you want to skip the text that is
                      # already there. Or if using the ksh93 shell, add
                      # a <((EOF)) after < your-file
  while (1) {
    if ($_ = <STDIN>) {
      print; $t = 0
    } else {
      print "\n"            if $t == 3;
      # and a line of "-"s after 10 seconds:
      print "-" x 72 . "\n" if $t == 10;
      sleep 1;
      $t++;
    }
  }' < your-file

Або дозвольте tail -fвиконувати хвостик і використовувати perlдля вставки нових рядків, якщо немає вводу протягом 3 секунд:

tail -f file | perl -pe 'BEGIN{$SIG{ALRM} = sub {print "\n"}} alarm 3'

Ті припускають, що вихід сам по собі не сповільнений (наприклад, коли вихід йде в трубу, яка не зчитується активно).


Мені знадобилося багато часу, щоб зрозуміти, чому другий насправді працює :)
хобби

Я спробував перший, і він надрукував ВСІ файли перед рукою, тому це не оптимально. Другий працює як шарм. Я додав "хвіст -n 0 -f $ 1 |" варіант (-n 0), щоб не відображати старі рядки файлів.
Седрік

Невелике запитання: як я міг змінити друге рішення, щоб відобразити додатковий рядок тире (-------) через 10 секунд? (Я пробував декілька способів, але нічого не можу зробити)
Седрік,

1
@Cedric, див. Редагування для першої точки. Ваша друга вимога була б простішою з першим підходом.
Стефан Шазелас

8

bash+ dateрішення:

while IFS= read -r line; do        
    prev=$t         # get previous timestamp value
    t=$(date +%s)   # get current timestamp value
    [[ ! -z "$prev" ]] && [[ "$((t-prev))" -ge 3 ]] && echo ""
    echo "$line"    # print current line
done < <(tail -f error.log)

У Bash ви можете використовувати $SECONDSпідрахунок часових інтервалів. Я думаю, що це кількість секунд з моменту запуску оболонки, а не те, що це має значення, коли приймаєш різницю.
ilkkachu

@ilkkachu, або read -tабо $TMOUT. $SECONDSрозбивається в bashі mksh. time bash -c 'while ((SECONDS < 3)); do :; done'триватиме від 2 до 3 секунд. Краще використовувати zsh або ksh93, а не тут (з typeset -F SECONDS)
Stéphane Chazelas

@ StéphaneChazelas, я не думаю, що це відрізняється від використання date +%s. Обидва надають час у повних секундах, що робить, що інтервал від, скажімо, 1,9 до 4,0 виглядає як 3 повних секунди, хоча це дійсно 2,1. Важко обійти це, якщо всі, до яких ви не можете отримати доступ до дробових секунд. Але так, вони, ймовірно, повинні спати тут, а не зайнятий циклом, і тоді вони read -tмогли б так само добре використовуватися. Навіть якщо ви спите вручну, це time bash -c 'while [[ $SECONDS -lt 3 ]]; do sleep 1; done'працює чудово.
ilkkachu

1
ksh93 і zsh добре з цим (zsh раніше не використовувався). Навіть при цілому $ SECONDS, налаштування SECONDS=0гарантує, що $SECONDSдосягне 1 рівно за 1 секунду. Це не так, bashяк це використовується time()для відстеження $SECONDSзамість gettimeofday(). Я повідомляв про помилки mksh, zsh та bash деякий час тому, лише zsh було виправлено. (хороший момент щодо того, що питання є таким самим date +%s). Зауважте, що це не зайнятий цикл, як ми читаємо з виходу tail -fнад трубою.
Стефан Шазелас

+1 і Bash має «ярлик» , використовуючи вбудований printfемулювати dateбез зовнішніх інструментів або підстановки команд: printf -v t '%(%s)T' -1.
Девід Фоерстер

6

Pythonрішення (з аргументом динамічного часового розриву ):

tailing_by_time.py сценарій:

import time, sys

t_gap = int(sys.argv[1])    # time gap argument
ts = 0
while True:
    line = sys.stdin.readline().strip()    # get/read current line from stdin
    curr_ts = time.time()                  # get current timestamp
    if ts and curr_ts - ts >= t_gap:
        print("")                          # print empty line/newline
    ts = curr_ts
    if line:
        print(line)                        # print current line if it's not empty

Використання:

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