У меня есть скрипт, который всегда выдает вывод, перенаправляя его в файл. Я пытаюсь повернуть перенаправленный файл. Ниже показано, где я запускаю скрипт и перенаправляю его:
.
somecode
.
su - username -c "command >> /path/to/directory/output.txt" &
.
.
code continues..
и ниже представлен файл crontab, который я пытаюсь создать:
cd /path/to/directory/
timestamp=`date "+%Y%m%d"`
mv ./output.txt ./logs/output.txt_$timestamp
touch output.txt
chmod 757 ./output.txt
gzip ./logs/output.txt_$timestamp
find ./logs/output.txt* -type f -mtime +2 | xargs rm
или этот тоже не справился с задачей:
timestamp=`date "+%Y%m%d"`
cp ./output.txt ./logs/output.txt_$timestamp
echo "" > ./output.txt
gzip ./logs/output.txt_$timestamp
в первом коде исходный скрипт дает сбой и больше не работает, а во втором скрипте он не очищает файл output.txt.
Есть ли способ сделать это, сохранив работоспособность скрипта? Примечание: я использую Unix Solaris.
Заранее спасибо.
решение1
Обычно это делается путем добавленияПОДПИШИТЕСЬобработчик, который перезапускает командупосле того, как какая-то другая команда (обычно logrotate
) переместила файл. В операционных системах *nix вы можете перемещать файлы во время записи в них (я полагаю, с оговоркой, что они должны все еще находиться в той же файловой системе); дополнительные строки будут добавлены к файлу в новом месте.
решение2
Вы действительно не можете изменить перенаправление запущенного процесса stdout
и/или stderr
указать новый файл (см. примечание ниже) (Это одна из причин, по которой использование перенаправления stdout
или stderr
файлов журнала для длительно запущенных процессов являетсяплохойИдея.)
Когда процесс запускается, элементы перенаправления команды выполняются оболочкой, которая запускает процесс. Целевой файл открывается и создается, если необходимо, в правильном режиме (добавление или перезапись) и, возможно, усекается до нулевых байтов в зависимости от режима перенаправления. Затем открытый файловый дескриптор передается дочернему процессу. Этот открытый файловый дескриптор является единственной ссылкой на перенаправленный файл, которая есть у дочернего процесса — буквально. Это ссылка на файл.
И это важный момент - как ссылка непосредственно на файл, открытый дескриптор находится на одном уровне с записью каталога для файла - "имя файла". Изменение этого имени или даже удаление этой записи каталога - например, с помощью команды rm
- абсолютно не влияет на открытый дескриптор файла в процессе.
@l0b0 ответил правильно, что процессы, которым нужно ротировать журналы, как правило, используют SIGHUP
обработчики для выполнения таких ротаций, но «ротация журналов» на самом деле не так проста в случае перенаправленного вывода — как называется новый выходной файл? Дочерний процесс не имеет представления о том, каково «имя» его stdout
и/или stderr
— и выходной «файл» может вообще не быть файлом.
Схемы ротации бревен должны бытьразработанныйв процесс — например, ведение журнала должно быть интегрировано таким образом, чтобы записи журнала не терялись в процессе ротации файла журнала.
(Хорошо, это может бытьвозможныйдля изменения потоков stdout
/ stderr
для запущенного процесса - но это то, что должно быть - опять же -разработанныйв процесс. Это не то, что может сделать готовый двоичный файл, который bash
будет делать это автоматически, если вы отправите ему SIGHUP
...)
решение3
Большое спасибо всем за ответы, не смог найти способ это сделать, поэтому в качестве обходного пути я настроил crontab так, чтобы он остановил исходный скрипт, выполнил ротацию и снова запустил его в непиковое время.