Не удается вручную обновить базу данных для поиска?
Я пытался обновить базы данных, используемые locate на моем Macbook (10.6.3 Snow Leopard), но даже выполнение команд, показанных в этой теме, никуда меня не привело. Я просто получаю сообщение об ошибке - если я пытаюсь использовать его с помощью sudo, я получаю некоторую информацию об отказе в разрешении для такого-n-такого каталога. Я попытался запустить его как root (sudo su, затем команда), и это тоже не сработало. Вернитесь к моей обычной терминальной подсказке, и теперь я просто получаю
macbook:~ monte$ sudo /usr/libexec/locate.updatedb
найти: .: В доступе отказано
MacBook: ~ Монте $
Я полностью сбит с толку и наполовину боюсь, что, возможно, что-то спрятал в процессе. Любая помощь или предложения будут с благодарностью!
Monte
4 ответа
Решение вашей проблемы очень простое (и его можно найти в конце этого ответа). Но если вы хотите лучше узнать, почему происходит ошибка и почему работает предложенное решение, вы можете прочитать весь ответ.
Что именно делает locate.updatedb?
Это текущее поведение locate.updatedb
:
- Если вы запускаете скрипт как
root
опять звонит сам с пользователемnobody
и затем потомки возвращаются, он обновляет окончательную базу данных локали с базой данных, сохраненной процессом потомков (nobody
пользователь) во временном местоположении, а затем выходит;
Код (/usr/libexec/locate.updatedb
, строка 31, с дополнительными комментариями, добавленными мной):
if [ "$(id -u)" = "0" ]; then ## IF ROOT USER
rc=0
export FCODES=`mktemp -t updatedb` ## CREATE A TEMP FILE
chown nobody $FCODES # TEMP FILE OWNED BY THE NOBODY USER
tmpdb=`su -fm nobody -c "$0"` || rc=1 ## CALL ITSELF AS USER NOBODY
if [ $rc = 0 ]; then
install -m 0444 -o nobody -g wheel $FCODES \
/var/db/locate.database ## INSTALL THE LOCATE DATABASE SAVED \
## BY THE CHILDREN IN THE TEMP FILE
fi
rm $FCODES
exit $rc ## EXIT
fi
- При работе с другим пользователем (это пользователь
nobody
) сценарий индексирует вашу систему (игнорируя пути, на которые у него нет разрешения), а затем сохраняет результат во временный файл (фактически, ранее временный файл, созданный его отцом);- Итак, часть логики выполняется как корень, а другая часть как никто;
- Если скрипт вызывается без
sudo
не сработает (толькоroot
имеет разрешение в/var/db
каталог). Вы действительно должны изначально запустить скрипт какroot
; - В следствии,
locate.updatedb
не может индексировать файлы в вашем доме (nobody
у пользователя нет прав доступа к нему); - Я думаю
locate.updatedb
индексирует таким образом, потому что пользователю будет невозможно обнаружить имена файлов, принадлежащих другому пользователю (в другом домашнем каталоге); - Если вы хотите найти файлы в вашем доме, вы можете использовать
mdfind
как предложено @ted-naleid.
Некоторый код (/usr/libexec/locate.updatedb
, строка 93, с дополнительными комментариями):
if $find -s $SEARCHPATHS $excludes -or -print 2>/dev/null | ## SEARCH
$mklocatedb -presort > $tmp ## CREATE LOCALEDB
then
case X"`$find $tmp -size -257c -print`" in
X) cat $tmp > $FCODES;; ## SAVE LOCALEDB IN THE TEMP FILE
[...]
Почему вы получаете сообщение об ошибке "Отказано в доступе"?
Было сказано, что locale.updatedb
запускает новый экземпляр себя как nobody
пользователь. Однако вы не можете запустить скрипт внутри рабочего каталога, на который у скрипта нет разрешения.
Возможно, вы получаете ошибки "Отказано в доступе", потому что вы работаете locale.updatedb
в вашем доме.
Я создаю простой скрипт, чтобы показать этот факт:
#!/bin/bash
if [ $(id -un) != "nobody" ]; then
sudo -u nobody "$0"
exit 0
fi
find / -mindepth 1 -maxdepth 1 | wc -l
Если вы поместите этот скрипт внутри /tmp/test.sh
и установить для него разрешение на выполнение (chmod +x /tmp/test.sh
), в зависимости от вашего рабочего каталога, может показывать или нет ошибки:
$ cd /tmp
$ ./test.sh
29
$ cd ~
$ /tmp/test.sh
shell-init: error retrieving current directory: getcwd: cannot access parent directories: Permission denied
job-working-directory: error retrieving current directory: getcwd: cannot access parent directories: Permission denied
find: .: Permission denied
0
Как обновить вашу базу данных locate?
Теперь все просто! Измените только ваш рабочий каталог на место, где nobody
имеет разрешение до выполнения locale.updatedb
:
cd /
sudo /usr/libexec/locate.updatedb
Возможно, вы захотите попробовать восстановить права доступа к файлам (в приложении Дисковая утилита). Похоже, это может быть проблемой с этим.
Кроме того, не имеет прямого отношения к locate, но я обнаружил, что на mac этот mdfind действительно делает то, что я хочу, немного лучше, чем locate. Это интерфейс командной строки для подсветки, и он позволяет вам найти только по имени файла, если вы хотите имитировать locate:
mdfind -name <filename>
Просто используя "mdfind ", вы найдете имена обоих файлов и загляните внутрь файлов (вроде grep/find вместе взятых).
Нет необходимости обновлять базу данных вручную, так как OSX предоставляет информацию о вас.
launchctl load -wF /System/Library/LaunchDaemons/com.apple.locate.plist
Если это не поможет, попробуйте:
launchctl stop com.apple.locate
launchctl start com.apple.locate
(это немного устарело, но так как я копал аналогичную проблему с 10.6 сегодня...)
macbook:~ monte$ sudo /usr/libexec/locate.updatedb
find: .: Permission denied
macbook:~ monte$
это точно не проблема - это побочный эффект от locate.updatedb, который никому не нужен, но ваш домашний каталог не читается пользователем "nobody".
Вы, вероятно, обнаружите, что системные файлы все еще можно найти с помощью locate, но внутри вашего домашнего каталога ничего нет. Вам нужно сделать свой мир homedir читабельным / исполняемым. Например:
chmod a+rx $HOME
Возможно, вам также потребуется просмотреть содержимое вашего homedir - но, скорее всего, вы не хотите выполнять рекурсивный chmod по всему дереву. (~/.ssh, например, имеет особые требования). Если у вас есть пользовательский набор масок, вы также захотите просмотреть его.
В качестве альтернативы взлома вы можете отредактировать скрипт /usr/libexec/locate.updatedb, чтобы не переключаться на пользователя nobody:
if [ "$(id -u)" = "0" ]; then
rc=0
export FCODES=`mktemp -t updatedb`
chown nobody $FCODES
tmpdb=`su -fm nobody -c "$0"` || rc=1
if [ $rc = 0 ]; then
install -m 0444 -o nobody -g wheel $FCODES /var/db/locate.database
fi
rm $FCODES
exit $rc
fi
Удалить или закомментировать этот блок - или просто настроить тест на что-то другое -
if [ "$(id -u)" = "-99" ]; then
Это должно работать независимо от того, как обновление вызывается - launchd или вручную. Но может вернуться, если вы обновите ОС. (хотя давайте посмотрим правде в глаза, в 2014 году, если вы все еще используете 10.6, вы, вероятно, не собираетесь обновлять сейчас;)