вторник, 12 февраля 2019 г.

Про удаление файлов/папок через N дней через скрипт bash в Linux

При обмене отдельными файлами или файлами, организованными в папки, непременно возникает вопрос своевременного их удаления как устаревших или потерявших актуальность. Как правило, респонденты не удаляют предоставленные им данные: нет времени, потом, забыл(а) ... В итоге время нахождения контента в папках обмена начинает стремиться к бесконечности. Действительно, чего волноваться? Диски нынче большие, места хватает ...

Описанный ниже вариант используется в целях "найти и удалить контент старше N дней" в папках общего доступа таких ресурсов как Диск Яндекс, Dropbox, MEGA, pCloud. При этом каждая папка имеет свои настройки времени хранения контента, при превышении которого он подлежит удалению.

Примечание 1. Указанные в тексте команды могут быть не оптимальными с точки зрения правильного кодинга. Полагаю, что мне это может быть простительным, так как, не имея в данном вопросе профильного образования, информацию пришлось собирать по кусочкам с разных сайтов. Поэтому, по большому счёту, все приводимые ниже листинги являются своего рода компиляцией уже готовых решений.

Итак, обмен с использованием 5 ресурсов облачного хранения: 4 Яндекс Диска и 1 Dropbox. В каждом их них создана папка общего доступа.

Удалить файлы/папки старше N дней

Удаление устаревших файлов и папок осуществляется в ходе задания, запускаемого через cron, то есть без участия пользователя. В процессе выполнения задания создаются файлы отчётов - списка удалённого контента. При этом в имени файла отчёта содержится дата его создания. Файлы отчётов также подлежат удалению через определённое время (X дней).

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

Примечание 2. В силу особенностей запуска по расписанию клиентов pCloud и MEGA удаление в них файлов/папок старше N дней необходимо производить перед выполнением остановки клиента. Про остановку клиента читать здесь и здесь.

Объясняется это тем, что после запуска pcloud и megasync выполнение последующих за ними команд невозможно до тех пор, пока pcloud или megasync активны. А после выключения процессов pcloud или megasync нет синхронизации и, соответственно, передачи изменений в облако.


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

Скрипт очистки использует инструкции "если A, то B и если не А, то С".

if <запрос на соответствие условию>
then <действие 1>
else <действие 2>
fi

Самым первым действием является определения наличия какого-либо контента в папке обмена. Потому что если в ней ничего нет, то и дальнейшие действия не имеют смысла. Поэтому ищем файлы (а соответственно, будут найдены и папки, в которых они содержатся).

Перед выполнением указываются расположение папки для поиска (DIR1) и расположение папки отчётов (DIR2). DIR1 и DIR2 используются для того, чтобы в скрипте не писать каждый раз пути к папкам, заменяя их указанными переменными. Имена DIR1 и DIR2 указаны для примера. Для лучшего восприятия своих скриптов примените понятные Вам имена.

Формулировка условия описывается переменной filecount.

Команда "ничего не делать" соответствует символу двоеточия, то есть : .

DIR1=/home/user/Exchange/Beatrice
DIR2=/home/user/Exchange/Reports
filecount=`find $DIR1 -type f | wc -l`
if [ $filecount -eq 0 ];
then
:

Если же какие-то файлы присутствуют, то выполняется ряд последовательных операций:

– определить текущую дату;

– сформировать файл протокола с датой создания;

– удалить контент старше N дней.

else
date=`date '+%d'`
find $DIR1 -mtime +N > $DIR2/$date.Beatrice.txt
find $DIR1 -mtime +N -delete
fi

Примечание 3.

Результатом выполнения date является установка даты. В указанном выше случае файл будет иметь наименование, например, 18.Beatrice.txt, то есть за 18-число месяца. 


Если в имя файла есть необходимость включать и месяц, то переменная date должна быть указана в виде `date '+%m.%d'` Пример результирующего файла – 04.18.Beartice.txt

 %m соответствует текущему месяцу, а %d – дню месяца.

Примечание 4.
Имеется несколько вариантов команды удаления: 


 find /path -mtime +N -exec rm -rf {} \; 

 find /path -type f -mtime +N | xargs rm -rf  

 find /path -mtime +N -delete

В средней команде указан поиск файлов: -type f   Для папок вводить -type d

На одном из форумов было найдено, что -delete работать будет быстрее. Так как лично мне была более понятна команда -delete, то она и приводится во всех указанных ниже листингах команд.


Уточнение для Dropbox и MEGA. В папках общего доступа таких клиентов могут находиться скрытый файл .dropbox или папка .debris Поэтому целесообразно исключить их из удаления, добавив инструкцию "кроме".

Кроме –  ! -name 'имя_объекта'. Например:

find $DIR1 ! -name '.dropbox' -mtime +N -delete или

find $DIR1 ! -name '.debris' -mtime +N -delete

Примечание 5.

При использовании параметра +N Вы можете быть удивлены тем, что контент будет удалён не через N дней, а позднее. Это связано в тем, что аргумент -mtime интерпретируется как количество целых дней. То есть, -mtime +N означает строго больше , -mtime -N означает строго меньше. Другими словами, если возраст объекта составляет 1 день, 23 часа, 59 минут и 59 секунд, то -mtime +1 обрабатывает его, как будто это 1 день, 0 часов, 0 минут. Связано с особенностями программной реализации.

В итоге получается, что -mtime +1 выбирает файлы, которые были изменены как минимум 2 дня назад. Чтобы получить файлы, измененные не менее 1 дня назад, используйте -mtime +0

Другой способ. Если необходимо удалить файлы старше чем, например, ровно 48 часов, то используйте –daystart: find /path type -f -daystart -mtime +1

Если необходимо указывать минуты, то используется -mmin N, что соответствует утверждению "данные файлы последний раз изменены N минут назад.


Примечание 6.

Для использования других параметров ниже приводится краткая справка.

atime

atime означает время доступа. Эта временная метка сообщает, когда последний раз обращались к файлу. Изменяется, если использовались cat, vim, less или какой-либо другой инструмент для чтения или отображения содержимого файла.

mtime

mtime означает время изменения (модификации). Означает, что содержимое файла было изменено путем редактирования файла. При копировании или переносе в другое место хранения это значение не изменяется.

ctime

ctime означает время изменения статуса. Эта временная метка сообщает, когда был последний раз были изменены свойства и метаданные файла. Метаданные включают права доступа, права собственности, имя и местоположение файла.

Как просмотреть временные метки файла? Командой stat . Пример:

stat ~/winehq.key
Файл: /home/user/winehq.key
Размер: 3220 Блоков: 8 Блок В/В: 4096 обычный файл
Устройство: 801h/2049d Inode: 18880312 Ссылки: 1
Доступ: (0664/-rw-rw-r--) Uid: ( 1000/ minter) Gid: ( 1000/ user)
Доступ: 2018-12-20 03:48:48.108006716 +0300
Модифицирован: 2018-12-19 17:07:25.000000000 +0300
Изменён: 2018-12-20 03:48:42.368059166 +0300
Создан: -

Как узнать, когда был изначально создан файл?

Вы заметили последнюю строку вывода команды stat? В нём указывается «Создан». Можно предположить, что это представляет собой timestmap, когда файл был «рождён» (или создан, если быть более точным).

Хотя ext4 поддерживает временную метку создания, команда stat в настоящее время не может её показать. Возможно, будущие версии команды stat покажут временную метку создания в строке «Создан».

В некоторых случаях нужно выяснить, был ли файл удален и пересоздан заново или это тот самый оригинальный файл. По параметру ctime достоверно сказать об этом нельзя, так как он может меняться при любых изменениях атрибутов. Поэтому нужен другой параметр для проверки. В тот момент, когда файл удаляют и создают заново с тем же именем, большая часть его атрибутов остается неизменной. Меняются в основном два – ctime и inode. ctime покажет, когда последний раз изменились атрибуты файла (совсем не обязательно, что из-за удаления и создания), а inode изменится, так как для операционной системы это будет уже совсем другой файл с новым индексным дескриптором.

Смотреть inode можно двумя способами:

stat
ls -i


Ожидается, что в результате выполнения find $DIR1 -mtime +N -delete будут найдены и удалены все объекты старше N дней. Однако, как говорят, "гладко было на бумаге, да забыли про овраги".

На практике выяснилось, что могут иметь место случаи, когда "хорошая мысля пришла апасля" и файлы могут быть перемещены в другую созданную позднее папку. Получится ситуация, при которой mtime созданной папки более "молодой", чем mtime содержащихся в ней файлов. В итоге – после удаления в ней файлов эта папка не будет удалена (другое значение mtime) и будет представлять из себя пустой объект.

Также в ходе тестирования имели место случаи, когда после удаления файлов из папок с составными именами сами папки не были удалены:


В этом случае можно использовать условие "посчитаем пустые папки". Если ничего не будет найдено, то ничего и не делаем. Если что-то найдём, то удалим. При этом исключим из удаления саму папку общего доступа (в рассматриваемом случае Beatrice), так как было несколько случаев удаления подобной папки, не содержащей уже никаких данных.

dircount=`find $DIR1 -type d -empty | wc -l`
if [ $dircount -eq 0 ];
then
:
else
find $DIR1 ! -name 'Beatrice' -empty -delete
fi

Аналогичные описанным выше действия применяются и для файлов отчётов. То есть используется алгоритм:

– найти в папке отчетов файлы в имени которых присутствует Beatrice.txt. В самом начале процедуры удаления удаления такой файл был сформирован. Его полное имя будет, например, 18.Beatrice.txt (см. выше);

– если таких файлов не найдено, то ничего не делать;

– при нахождении удалить такие файлы старше X дней.

filecount=`find $DIR2 -name *.Beatrice.txt -mtime +X | wc -l`
if [ $filecount -eq 0 ];
then
:
else
find $R -name *.Beatrice.txt -mtime +X -delete
fi

Следует отметить, что файл отчёта будет создаваться всегда. Если никаких объектов для удаления не назначено, то такой файл будет пустым. Следовательно, во избежание "замусоривания" папки отчётов такие файлы необходимо найти и удалить.

filecount=`find $DIR2 -name *.Beatrice.txt -empty | wc -l`
if [ $filecount -eq 0 ];
then
:
else
find $R -name *.Beatrice.txt -empty -delete

Завершить выполнение скрипта командой exit

Итого, полный текст скрипта будет иметь вид:

#!/bin/bash
DIR1=/home/user/Exchange/Beatrice
DIR2=/home/user/Exchange/Reports
filecount=`find $DIR1 -type f | wc -l`
if [ $filecount -eq 0 ];
then
:
else
date=`date '+%d'`
find $DIR1 -mtime +N > $DIR2/$date.Beatrice.txt
find $DIR1 -mtime +N -delete
fi
dircount=`find $DIR1 -type d -empty | wc -l`
if [ $dircount -eq 0 ];
then
:
else
find $DIR1 ! -name 'Beatrice' -empty -delete
fi
filecount=`find $DIR2 -name *.Beatrice.txt -mtime +X | wc -l`
if [ $filecount -eq 0 ];
then
:
else
find $DIR2 -name *.Beatrice.txt -mtime +X -delete
fi
filecount=`find $DIR2 -name *.Beatrice.txt -empty | wc -l`
if [ $filecount -eq 0 ];
then
:
else
find $DIR2 -name *.Beatrice.txt -empty -delete
exit

Оформите как исполняемый файл. Например, clean или clean.sh. Принципиального значения наличие/отсутствие расширения не имеет. Важно лишь то, чтобы такой файл был исполняемым.

Примечание 7. На практике в Linux Mint 19 xfce через свойства файла в менеджере файлов Thunmar файлам без расширения (скриптам) не удавалось установить "исполняемый". В таком случае его можно переименовать из, например, clenan в clean.sh, назначить его исполняемым, а затем переименовать его обратно в clean. "Исполняемость" файла сохранится.

В случае отсутствия необходимости создания файлов отчётов и их последующего удаления через X дней приведенный выше текст скрипта упрощается до вида:

#!/bin/bash DIR=/home/user/Exchange/Beatrice
filecount=`find $DIR -type f | wc -l`
if [ $filecount -eq 0 ];
then
:
else
find $DIR1 -mtime +N -delete
fi
dircount=`find $DIR -type d -empty | wc -l`
if [ $dircount -eq 0 ];
then
:
else
find $DIR ! -name 'Beatrice' -empty -delete
fi
exit

Примечание 8. Не забывайте про особенность общих папок в Dropbox и MEGA. Добавляйте для них исключения .dropbox и .debris (см. выше).

Запустить клиент и удалить папки/файлы старше N дней

Запуск клиента Диска Яндекс

Поясняющие подробности можно прочитать здесь. Приводится только пример скрипта.

#!/bin/bash
crash=/home/user/.config/yandex-disk/crash.txt
D1=/home/user/.config/yandex-disk
D2=/home/user/scripts/yandex/client-1
if [ -f $crash ]; then
rm -f $D1/crash.txt
else
:
fi
rm -f $D1/config.cfg
rm -f $D1/iid
rm -f $D1/passwd
cp $D2/config.cfg $D1
cp $D2/iid $D1
cp $D2/passwd $D1
yandex-disk start
sleep 60
/home/user/scripts/clean-1
sleep 240
yandex-disk stop
sleep 5 && exit

Примечание 9.

После старта клиента Диска Яндекс (yandex-disk start) даётся время на запуск клиента и его соединение с облаком (sleep 60). Затем осуществляется очистка. После этого даётся 4 минуты на приём/передачу данных (sleep 240), после чего следует команда остановки клиента и завершения работы скрипта. 60 секунд и 240 секунд указаны условно. Пользователь сам определяет сколько времени должно пройти и следует ли ему использовать первое ожидание (sleep 60).


Если на Диске Яндекс больше чем 1 папка обмена, то тогда на каждую папку создаётся свой скрипт. Они, соответственно, должны быть запущены один за другим, например:

/home/user/scripts/clean-1
/home/user/scripts/clean-2
/home/user/scripts/clean-3

Ожидание 5 секунд после команды остановки Диска Яндекс введено "на всякий случай", чтобы гарантировать остановку клиента с используемой конфигураций. Это обусловлено тем, что у меня последовательно другом за другом запускаются 4 Диска Яндекс, каждый со своими настройками.

Если у Вас только 1 учётная запись Диска Яндекса, то нет необходимости переписывать конфигурацию клиента. Скрипт упрощается до вида:

#!/bin/bash
yandex-disk start
sleep 60
/home/user/scripts/clean-1
sleep 240
yandex-disk stop
exit

Запуск клиента Dropbox

Пример:

#!/bin/bash
dropbox start
sleep 40
/home/user/scripts/clean-4.sh
sleep 260
dropbox stop
exit

Скрипт запуска клиентов с очисткой

Например, у меня оформлен запуск 5-ти клиентов последовательно друг за другом. Перед запуском очереди заданий клиентов Диска Яндекс проверяется наличие уже запущенного экземпляра Диска Яндекс. Если такой экземпляр будет найден, то выдаётся команда на его остановку.

#!/bin/bash
yd=/tmp/yandex-disk-*
if [ -d $yd ]; then
yandex-disk stop
else
:
fi
sleep 5
/home/user/scripts/yandex/client1/daemon
/home/user/scripts/yandex/client2/daemon
/home/user/scripts/yandex/client3/daemon
/home/user/scripts/yandex/client4/daemon
/home/user/scripts/dropboxauto
exit

При включении мной такого задания по расписанию имелось в виду, что каждое задание выполняется не менее 5-ти минут. Следовательно, общее время выполнения указанных заданий составит не менее 25-ти минут. В реальности оно больше за счёт различного рода пауз между отдельными операциями, поэтому его продолжительность была оценена в 30 минут.

Комментариев нет:

Отправить комментарий