GNU версия locate - gupdatedb завершается с ошибкой "gfind: не удалось прочитать имена файлов из файловой системы"

Я пытаюсь протестировать версию locateкоманды GNU. Во-первых, мне нужно создать базу данных следующим образом:

sudo gupdatedb --prunepaths=/Volumes --output=$HOME/locatedb_gupdatedb

К сожалению, через 1 минуту после запуска команды я все еще получаю следующую ошибку:

gfind: failed to read file names from file system at or below '/': No such file or directory

Я не понимаю, откуда может появиться эта ошибка?

ОБНОВЛЕНИЕ 1: я заменил gfindзапятую findи правильный путь к findкоторой /usr/bin/. К сожалению, я получаю такие смущающие сообщения об ошибках, когда запускаю команду gupdatedbследующим образом:

sudo gupdatedb --prunepaths='/private/tmp /private/var/folders /private/var/tmp */Backups.backupdb /Volumes /System' --output=$HOME/locatedb_gupdatedb

Здесь сообщения об ошибках:

find: /System/Volumes/Data/.Spotlight-V100: No such file or directory
find: /System/Volumes/Data/.PKInstallSandboxManager: No such file or directory
find: /System/Volumes/Data/.PKInstallSandboxManager-SystemSoftware: No such file or directory
find: /System/Volumes/Data/.cleverfiles: No such file or directory
find: /System/Volumes/Data/mnt: No such file or directory
find: /System/Volumes/Data/.DocumentRevisions-V100: No such file or directory
etc ...

Я попытался изменить в /usr/local/Cellar/findutils/4.7.0/libexec/bin/gupdatedbфайл вариант:

: ${FINDOPTIONS="2 > /dev/null"}

Но проблема в том, что этот параметр установлен перед командой find, а не в конце, поэтому он неверен в следующем файле.

findУчитывая тот факт , что в скрипте много команд, я не могу каждый раз вручную добавлять 2 > /dev/nullопцию терминала.

Кто-нибудь мог увидеть, как подавить все эти сообщения об ошибках из findкоманды, когда я запускаю gupdatedbкоманду?

ОБНОВЛЕНИЕ 2: мне наконец удалось создать базу данных с помощью gupdatedb (версия GNU updatedbкоманды MacOS), выполнив:

sudo gupdatedb --prunepaths='/private/tmp /private/var/folders /private/var/tmp */Backups.backupdb /System /Volumes' --output=$HOME/locatedb_gupdatedb

Теперь проблема в том, что когда я провожу исследование подстроки файла или каталога, информация, кажется, дублируется в результатах ( sub_stringэто просто часть имени файла или каталога):

Например, если я делаю:glocate -d ~/locatedb_gupdatedb sub_string

Затем у меня есть дубликаты результатов, например:

/System/Volumes/Data/Users/fab/sub_string.dat
/Users/fab/sub_string.dat

Я не знаю, как исключить ' /System/Volumes/Data/' из этих результатов: однако я правильно указал в --prunepathsопции каталог System, почему он не учитывается в базе данных, созданной gupdatedb?

Или, может быть, я должен выполнить:

sudo gupdatedb --prunepaths='/private/tmp /private/var/folders /private/var/tmp */Backups.backupdb /System/Volumes/Data /Volumes' --output=$HOME/locatedb_gupdatedb

??

Любая помощь приветствуется, чтобы исключить этот каталог

/System/Volumes/Data

из базы данных индексации.

ОБНОВЛЕНИЕ 3: Вот пример быстрого создания базы данных с расширением updatedb on Debian 10 Buster. Между отметками времени двух команд было сделано несколько модификаций обычного использованияupdatedb .

введите описание изображения здесь

Итак, я пришел к выводу, что действительно существует разница между реализацией GNU/MacOS и GNU/Linux.

Любое объяснение приветствуется.

Не уверен, что мы правильное место, чтобы спросить о Linux, это также делает ваш вопрос довольно широким.

Ответы (2)

Проблема здесь в том, что вы используете GNU updatedbс macOS find. gupdatedb— это сценарий оболочки, который должен запускать GNU-совместимый файл find. В частности, он преобразуется --prunepathsв базовое регулярное выражение, совместимое с GNU.

--prunepaths='/private/tmp /private/var/folders /private/var/tmp */Backups.backupdb /Volumes /System'

превращается в

PRUNEREGEX="\(^/private/tmp$\)\|\(^/private/var/folders$\)\|\(^/private/var/tmp$\)\|\(^*/Backups.backupdb$\)\|\(^/System$\)\|\(^/Volumes$\)"

GNU BRE (базовые регулярные выражения) рассматриваются \|как «альтернативный» оператор:

'foo\|bar' соответствует либо 'foo', либо 'bar'

Это расширение GNU для синтаксиса BRE, и findоператор macOS его не принимает. Таким образом, вся строка обрезки ничему не соответствует.

В macOS (и POSIX) BRE нет альтернативного оператора, поэтому это не очень простое решение. Сценарий updatedb для macOS преобразует альтернативу в явные -orоператоры в findкоманде. Вы можете изменить сценарий GNU, чтобы сделать это. Или приступайте gfindк работе.

Кстати, скрипт GNU updatedb создает совершенно новую базу данных с нуля при каждом запуске, как и в macOS.

Ваша установка Debian использует mlocate , который является совершенно другой реализацией, чем GNU locate, не так широко перенесен и недоступен в macOS, насколько мне известно. И хотя mlocateна вашей установке Debian он работает быстро, это не значит, что он работает намного быстрее, чем GNU locate. Оба запускают под вторым созданием всей базы данных с нуля в моей установке Debian, когда все метаданные диска находятся в ОЗУ (что обычно и бывает).

Apple предоставляет mdfind, который использует инкрементную базу данных, созданную mds, которая в основном запускается событиями файловой системы. Это делает его (теоретически) намного более эффективным, чем даже mlocate, который все еще должен пройти через всю структуру каталогов в поисках измененных каталогов. Проблема в том, что инкрементальные сборки накапливают ошибки. Вот почему locate, с его полной перестройкой каждый раз, по-прежнему актуален и любим многими.

«Кстати, скрипт GNU updatedb создает совершенно новую базу данных с нуля при каждом запуске, как и в macOS». В случае с Linux это не так, не так ли?
@youpilat13 youpilat13 Я смотрю на код из GNU findutils 4.7.0 . Это не относится к macOS, поэтому я ожидаю, что в Linux будет то же самое. Если вы посмотрите на код в целом, updatedbпросто запустите findкоманду, чтобы найти все файлы, а затем обработайте вывод в файл базы данных. Поскольку в findлюбом случае приходится сканировать все дерево каталогов, чтобы найти новые файлы, добавочное обновление не дает выигрыша в производительности (по крайней мере, оно не стоит затраченных усилий).
@OlfPro Это странно, в моем Debian такого поведения нет, updateb обновляет только то, что было изменено между последним использованием, обычно через несколько часов или минут. Я пришел к выводу, что реализация не совсем такая же.
Знаете ли вы инструмент, который не строит каждый раз весь жесткий диск? mdfindдовольно хорошо, но нестабильно (иногда результаты появляются, а иногда нет).
@ youpilat13 Сообщите мне, какую версию updatedb вы используете в своей системе Debian. Когда я запускаю apt install locateDebian Buster, я получаю базу данных от GNU findutils 4.6.0, которая создает новую $LOCATE_DB.nи в случае успеха заменяет старую базу данных новой. Насколько я знаю, mdsделает добавочные обновления для mdfind. Если mdfindотсутствует что-то, что не исключено намеренно (например, настройками конфиденциальности или включением индексации диска), я рекомендую использовать locate:-) Он не пытается делать инкрементные обновления, поэтому он намного надежнее, хотя и несколько устарел.
@OdPro Я поместил в UPDATE3 пример простого обновления Debian 10 с помощью updatedb. Я сделал несколько модификаций (создал несколько файлов, каталогов между двумя датами). И как видите, база данных генерируется очень быстро. Так что действительно есть разница в реализации между Linux и MacOS.
@ youpilat13 youpilat13 Это не разница между GNU/macOS и GNU/Linux. Ваша установка Debian использует mlocate , который является совершенно другой реализацией, чем GNU locate, не так широко перенесен и недоступен в macOS, насколько мне известно. Кроме того, GNU locate и mlocate обновляют базу данных в моей системе Debian менее чем за 1 секунду. Вам нужно сравнить две утилиты в одной системе, чтобы получить справедливую оценку.
Кажется, что ответ здесь в том, что на самом деле ответа нет - или, по крайней мере, такого, который не требует больших усилий для преодоления - я правильно понял? Я установил свою копию locateс MacPorts - я немного разочарован, поскольку MacPorts обычно просто не выпускает порт, который не работает должным образом.

Версия Apple запускается через /usr/libexec/locate.updatedbсценарий оболочки. Там из поиска исключены некоторые дополнительные пути. В Мохаве это

: ${PRUNEPATHS:="/private/tmp /private/var/folders /private/var/tmp */Backups.backupdb"} # unwanted directories

PS: у меня нет Catalina, поэтому вам может потребоваться проверить, нужно ли исключать и другие пути.

Спасибо за ваш быстрый ответ, но проблема связана с корневым каталогом "/", сообщение: gfind: failed to read file names from file system at or below '/'Я пытался сделать с вашим предложением: sudo gupdatedb --prunepaths='/private/tmp /private/var/folders /private/var/tmp */Backups.backupdb /Volumes' --output=$HOME/locatedb_gupdatedbи я получаю сообщение об ошибке выше. Как вы думаете, это проблема sudo?
@ youpilat13 youpilat13 Вероятно, это сложнее, чем кажется, сценарий оболочки запускается find, а затем передает результат в средство обновления locateb. Не знаю, как работает версия GNU, но, возможно, вы можете просто использовать копию сценария оболочки, чтобы передать версию GNU.
Зачем вам нужно использовать GNU locate, если он уже установлен?
@МаркУилсон. Потому что я ожидаю, что версия GNU будет вести себя так же, как и в системах Linux, т. е. когда у нас уже есть база данных, если мы запустим другую команду updatedb после нескольких часов использования, текущая база данных будет обновлена, а не стерта, чтобы снова создать совершенно другую. Это пустая трата времени на восстановление всей базы данных, и, к сожалению, это ошибочное поведение классической команды updatedb в MacOS.
Документация, показывающая, что это поведение BSD locate?