Перенаправление журнала происходит с повернутым журналом вместо создания нового журнала

Задача

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

Я достиг этого путем перенаправления STDIN и STDOUT для замены процесса и написания небольшой функции, которая использует savelog для поворота журналов.

 #!/bin/bash LOGFILE="/var/log/ps.log" exec > >(tee "$LOGFILE") 2>&1 LOGPATH="/var/log" MAX_LOGFILE_SIZE=5 rotateLog() { currentsize=$(du -k $LOGFILE | cut -f1) if [ $currentsize -ge $MAX_LOGFILE_SIZE ]; then savelog -dn $LOGFILE &>/dev/null fi } while :; do echo "A computer program can easily produce gibberish - especially if it has been provided with garbage beforehand. This program does something a little different. It takes a block of text as input and works out the proportion of characters within the text according to a chosen order. For example, an order of 2 means the program looks at pairs of letters, an order of 3 means triplets of letters and so on. The software can regurgitate random text that is controlled by the proportion of characters. The results can be quite surprising." rotateLog sleep 5 done 

проблема

Проблема в том, что даже после ps.log журнала ps.log в ps.log.20180829131658 все журналы все еще записываются в ps.log.20180829131658 и ps.log.20180829131658 следующая ошибка:

du: не может получить доступ к /var/log/ps.log: такой файл или каталог не существует ./ps.sh: строка 12: [: -ge: ожидается унарный оператор

Не ведет к дальнейшей ротации логов !!!

предположение

Я предполагал, что как только ps.log будет повернут в ps.log.20180829131658 , будет создан новый файл журнала ps.log . Но это определенно не так, поскольку exec выполняется только один раз ( может кто-нибудь объяснить, что именно здесь происходит? ), То есть в начале скрипта.

наблюдение

Также я заметил, что для >(tee "$LOGFILE") создается >(tee "$LOGFILE") создается новый файловый дескриптор, который указывает на /var/log/p.log который переназначается на p.log.20180829131658 ! Это то, что явно приводит к тому, что журналы все еще записываются в p.log.20180829131658 . Может кто-нибудь объяснить, пожалуйста, это поведение?

 root@b537ccc2c1ab:/var/log# ls -lrt -rw-r--r-- 1 root root 7248 Aug 29 13:16 ps.log root@b537ccc2c1ab:/var/log# ls -lrt /proc/*/fd /proc/8979/fd: total 0 l-wx------ 1 root root 64 Aug 29 13:16 3 -> /var/log/ps.log lrwx------ 1 root root 64 Aug 29 13:16 2 -> /dev/pts/17 lrwx------ 1 root root 64 Aug 29 13:16 1 -> /dev/pts/17 lr-x------ 1 root root 64 Aug 29 13:16 0 -> pipe:[3889791] root@b537ccc2c1ab:/var/log# ls -lrt -rw-r--r-- 1 root root 11098 Aug 29 13:17 ps.log.20180829131658 root@b537ccc2c1ab:/var/log# ls -lrt /proc/*/fd /proc/8979/fd: total 0 l-wx------ 1 root root 64 Aug 29 13:16 3 -> /var/log/ps.log.20180829131658 lrwx------ 1 root root 64 Aug 29 13:16 2 -> /dev/pts/17 lrwx------ 1 root root 64 Aug 29 13:16 1 -> /dev/pts/17 lr-x------ 1 root root 64 Aug 29 13:16 0 -> pipe:[3889791] 

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

После того, как процесс открывает файл, вы можете добавить в него все, что угодно, например переименовать его, обрезать, даже удалить, но процесс все равно откроет этот файл. Распространенной ошибкой является то, что, когда файл журнала занимает все дисковое пространство, он удаляет файл, пытаясь освободить место. Однако процесс записи в файл журнала все еще открыт, поэтому пространство не освобождается. Только когда процесс закроет файл, блоки, выделенные для файла, будут освобождены. (Обходной путь здесь – обрезать файл, то есть > logfile .)

В вашем случае вы переименовали файл, но процесс записи в него не знает или не заботится об этом.

Утилита logcheck имеет опцию copytruncate для таких ситуаций: она копирует файл журнала в повернутое имя, а затем усекает оригинал. Вы можете сделать то же самое:

 rotateLog() { currentsize=$(du -k $LOGFILE | cut -f1) if [ $currentsize -ge $MAX_LOGFILE_SIZE ]; then ROTATEDLOG=$LOGFILE.$(date +%Y%m%d%H%M%S) cp -p $LOGFILE $ROTATEDLOG && true > $LOGFILE fi } 

Лучшей альтернативой было бы изменение процесса, чтобы понять, например, сигнал SIGHUP для закрытия и повторного открытия файла журнала. Посмотрите команду shell trap для обработки этого.

Основываясь на альтернативном решении, предложенном @wurtel, я получил его так,

 #!/bin/bash LOGFILE="/root/logr/simple.log" function sighuphandler() { exec > >(tee "$LOGFILE") 2>&1 } trap sighuphandler SIGHUP LOGPATH="/root/logr" MAX_LOGFILE_SIZE=5 rotateLog() { currentsize=$(du -k $LOGFILE | cut -f1) if [ $currentsize -ge $MAX_LOGFILE_SIZE ]; then savelog -dn $LOGFILE &>/dev/null kill -s SIGHUP $$ fi } sighuphandler while :; do echo "[`date "+%Y-%m-%d %H:%M:%S"`] [INFO] - A computer program can easily produce gibberish - especially if it has been provided with garbage beforehand. This program does something a little different. It takes a block of text as input and works out the proportion of characters within the text according to a chosen order. For example, an order of 2 means the program looks at pairs of letters, an order of 3 means triplets of letters and so on. The software can regurgitate random text that is controlled by the proportion of characters. The results can be quite surprising." ls + rotateLog sleep 5 done