Назад | Перейти на главную страницу

Как `найти` файлы, которые не открываются никаким процессом

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

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

Есть ли способ сказать find чтобы пропустить открытые файлы, или мне нужно прибегнуть к lsof?

Насколько мне известно, простого способа сделать это с помощью find нет.

Решение первое

Создать список открытых файлов в целевой папке lsof.lst. и сгенерируйте список поиска этой папки. затем отобразить файлы в find.lst что не в lsof.lst список.

для создания lsof.lst используйте следующую команду:

lsof +D folderName | awk '{ if(NR>1)print $9 }' | sort | uniq > lsof.lst

а затем следующую команду, чтобы показать файлы, которые в настоящее время не открыты в той же папке:

find folderName | grep -v -f lsof.ls

Решение второе

Вы также можете сделать это за один раз вот так:

find folderName | grep -v -E `lsof +D folderName | awk '{ if(NR>1)print $9 }' | sort | uniq | awk '{print $0}' ORS='|' | sed 's/.$//'`

Объяснение

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

find folderName создаст список всех файлов в этой папке и подпапках. вывод команды find передается по конвейеру grep который здесь используется с -v переключатель, чтобы исключить элементы, указанные в -E параметры из конвейерного вывода команды find. Результатом будет вывод find минус элементы, указанные в -E параметр.

Хитрость здесь в том, чтобы сгенерировать список открытых файлов и поместить его в формат, который grep -v -E ожидает и может работать с. grep -E принимает список строк, разделенных знаком "|".

lsof +D FolderName сгенерирует список открытых файлов в этой папке, но список включает заголовок и множество столбцов, один из которых является именем файла, и он может содержать дубликаты. Итак, мы используем awk '{ if(NR>1)print $9 }' чтобы сделать две вещи, удалите первую строку с помощью if(NR>1) и распечатайте только столбец, содержащий имя файла с print $9. Результатом является список имен файлов открытых файлов в этой папке без заголовка.

Чтобы удалить дубликаты, вывод передается на sort а потом uniq, а следующая команда awk '{print $0}' ORS='|' превращает список в предложение, разделенное символом "|", а последняя команда удаляет последний символ "|" поскольку это чрезмерно.

заключая эту команду в обратные кавычки '' executes that command in that spot and feeds the output to thegrep -v -E` команда.