BASH: Как создать сценарий, который заставляет "tail -f" всегда записывать последний файл в каталог, live - PullRequest
1 голос
/ 14 июля 2020

Я в основном пытаюсь упростить отладку для других моих скриптов.

(Centos 7.6)

Мне нужен скрипт, выполняющий:

  1. tail -f последняя запись файла в каталоге
  2. , если новый файл появляется в этом каталоге, он плавно регистрирует этот новый файл
  3. , если я отправляю SIGINT (Ctrl + C) , он не оставляет сирот
  4. с менее возможными надстройками для максимальной переносимости

Это мое неработающее решение:

CURRENT_FILE=`ls -1t | head -n1`
tail -n 100 -f "$CURRENT_FILE" &
PID=$!

while [ true ];
do
    #is there a new file in the directory ?
    NEW_FILE=`ls -1t | head -n1`
    if [[ "$CURRENT_FILE" != "$NEW_FILE" ]]; then
            #yes, so kill last tail
            kill -9 $PID
            clear

            #tail on the new file
            CURRENT_FILE=$NEW_FILE
            tail -n 100 -f "$CURRENT_FILE"
            PID=$!
    fi
    sleep 1s
done

Проблема с этим решением состоит в том, что когда я отправляю SIGINT (Ctrl + C), то, что я обычно делаю при выходе из "tail -f", оставляет сиротского ребенка в фоновом режиме. Я искал решение с "ловушкой", но у меня ничего не получилось, и похоже, что оно не работает с таким вечным процессом, как "tail -f".

Я буду рад здесь свои мысли об этом и углубляйтесь в bash программирование.

Ответы [ 2 ]

3 голосов
/ 14 июля 2020

Вы можете trap при выходе из сценария и затем убить процесс. Вам не нужно -9, чтобы убить ваш tail, это излишне.

Вы также можете использовать inotify, чтобы сообщить вам, когда что-то происходит в каталоге, вместо сна и повторной проверки. Вот строительный блок basi c. inotify имеет много событий, которых вы можете дождаться. Вы можете добавить обнаружение, если файл был перемещен / переименован, поэтому вам не нужно перезапускать tail в этих случаях et c.

#!/bin/bash

killpid() {
    if [[ -n $PID  ]]; then
        kill $PID
        PID=""
    fi
}

trap killpid EXIT

DIR="."

CURRENT_FILE="$(ls -1t "$DIR" | head -n1)"

tailit() {
    echo "::: $CURRENT_FILE :::"
    tail -n 100 -f "$CURRENT_FILE" &
    PID=$!
}

tailit

# wait for any file to be created, modified or deleted
while EVENT=$(inotifywait -q -e create,modify,delete "$DIR"); do
    # extract event
    ev=$(sed -E "s/^${DIR}\/ (\S+) .+$/\1/" <<< "$EVENT")

    # extract the affected file
    NEW_FILE=${EVENT#${DIR}/ $ev }

    case $ev in
        MODIFY)
            # start tailing the file if we aren't tailing it already
            if [[ $NEW_FILE != $CURRENT_FILE ]]; then
                killpid
                CURRENT_FILE="$NEW_FILE"
                tailit
            fi
            ;;
        CREATE)
            # a new file, tail it
            killpid
            CURRENT_FILE="$NEW_FILE"
            tailit
            ;;
        DELETE)
            # stop tailing if the file we are tailing was deleted
            if [[ $NEW_FILE == $CURRENT_FILE ]]; then
                echo "::: $CURRENT_FILE removed :::"
                CURRENT_FILE=""
                killpid
            fi
            ;;
    esac
done
1 голос
/ 14 июля 2020

Вы можете использовать trap решение в начале вашей оболочки.

#! /bin/bash
trap ctrl_c INT
function ctrl_c() {
    if [[ -n "$PID" ]]; then
        kill -9 $PID
    fi
    exit 0
}

CURRENT_FILE=`ls -1t | head -n1`
tail -n 100 -f "$CURRENT_FILE" &
PID=$!

while [ true ];
do
    #is there a new file in the directory ?
    NEW_FILE=`ls -1t | head -n1`
    if [[ "$CURRENT_FILE" != "$NEW_FILE" ]]; then
            #yes, so kill last tail
            kill -9 $PID
            clear

            #tail on the new file
            CURRENT_FILE=$NEW_FILE
            tail -n 100 -f "$CURRENT_FILE" &
            PID=$!
    fi
    sleep 1s
done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...