Не удается разорвать цикл чтения while, даже если выполняется условие

Вы можете запустить tail -fна nohup.out, как указано в комментариях. Но для длительной задачи вам может быть лучше запустить ее под экраном GNU(или tmux ). Он выделяет виртуальный терминал, где может выполняться команда, позволяя вам отключаться и снова подключаться к «сеансу» по желанию.

Внутри экрана вы можете просто запустить свою команду, и последний вывод будет виден на терминале, или, например,. запустите mycmd > outputfile, чтобы сохранить вывод в файл, или даже mycmd | tee outputfile, чтобы получить вывод как на терминал, так и в файл. А экран даже позволяет открывать несколько окон, поэтому вы можете легко просматривать выходной файл во время выполнения команды.

0
01.05.2021, 12:56
2 ответа

Вам необходимо отделить проверку "стоп-файла" от чтения лог-файла, потому что tail -fне завершится. Следующий сценарий оболочки делает это, заставляя фоновую задачу проверять наличие «стоп-файла» раз в секунду. Всякий раз, когда файл появляется, он убивает процесс tail -fсигналом PIPE(, тем же самым сигналом, который он получил бы, если бы grepпрекратил чтение ). Когда tail -fзавершается из-за сигнала PIPE, процесс grepтакже завершается, поскольку его входной поток закрывается.

#!/bin/sh

stopfile=/usr/local/FOLDER/.myworkisdone

set -- tail -f /var/log/server22.log 

"$@" | {
        while true; do
                if [ -e "$stopfile" ]; then
                        pkill -PIPE -fx "$*"
                        break
                fi
                sleep 1
        done &

        grep -e 'Downloading Config' \
             -e 'Copying all files of'
} >/var/tmp/MyOwnLogFile.log

Это устанавливает позиционные параметры для команды tail -f. Это немного облегчает обращение к нему с помощью pkillпозже. Утилита pkillвызывается как с -f, так и с -x, чтобы иметь возможность убить именно ту команду, которую мы начали ранее.

Значение "$*"представляет собой единую строку, состоящую из всех позиционных параметров (команды tail -f)с пробелом в -между ними (по умолчанию ).

Использование bashи именованного массива для команды tail -f:

#!/bin/bash

stopfile=/usr/local/FOLDER/.myworkisdone

talicmd=( tail -f /var/log/server22.log )

"${tailcmd[@]}" | {
        while true; do
                if [ -e "$stopfile" ]; then
                        pkill -PIPE -fx "${tailcmd[*]}"
                        break
                fi
                sleep 1
        done &

        grep -e 'Downloading Config' \
             -e 'Copying all files of'
} >/var/tmp/MyOwnLogFile.log

(Я также заметил, что пара одинарных кавычек вокруг ваших регулярных выражений, используемых с grepв вопросе, являются не обычными одинарными кавычками, а «причудливыми кавычками».)

0
28.07.2021, 11:36

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

     #!/usr/bin/perl

     use File::Tail;
     tie *FH,"File::Tail",(name=>shift,nowait=>1);

     while (<FH>) {
         print if (m/Downloading Config|Copying all files of/);
         exit if ( -e '/usr/local/FOLDER/.myworkisdone')
     }

сохранить как, например, watch.pl, сделать его исполняемым с chmod +x watch.plи запустить как:

$./watch.pl /var/log/server22.log

или просто вставьте его как один -лайнер в сценарий оболочки, так же, как вы делаете это для сценария awk или sed:

perl -MFile::Tail -e 'tie *FH,"File::Tail",(name=>shift,nowait=>1);
      while (<FH>) {
        print if (m/Downloading Config|Copying all files of/);
        exit if ( -e '/usr/local/FOLDER/.myworkisdone')
      }' /var/log/server22.log

Это отслеживает файл журнала, названный первым аргументом скрипта(name=>shift). Он печатает все строки файла журнала, соответствующие шаблону, и завершает работу, если файл.myworkisdone существует.

nowait=>1предотвращает блокировку скрипта при чтении входного файла. Это далеко не идеально, но подходит для быстрого -и -грязного сценария. Лучшим решением было бы использовать метод File ::Tail’s select(). См. man File::Tail.

Кстати, метод select()также упрощает одновременный мониторинг нескольких файлов журналов.

0
28.07.2021, 11:36

Теги

Похожие вопросы