4

Я пытался обновить базы данных, используемые locate на моем Macbook (10.6.3 Snow Leopard), но даже следование командам, приведенным в этой теме , никуда меня не привело. Я просто получаю сообщение об ошибке - если я пытаюсь использовать его через sudo, я получаю некоторую информацию об отказе в разрешении для такого-n-такого каталога. Я попытался запустить его как root (sudo su, затем команда), и это тоже не сработало. Вернитесь к моей обычной терминальной подсказке, и теперь я просто получаю

macbook: ~ monte $ sudo /usr/libexec/locate.updatedb
найти:.: В доступе отказано
MacBook: ~ Монте $

Я полностью сбит с толку и наполовину боюсь, что, возможно, что-то спрятал в процессе. Любая помощь или предложения будут с благодарностью!

Monte

4 ответа4

7

Возможно, вы захотите попробовать восстановить права доступа к файлам (в приложении Дисковая утилита). Похоже, это может быть проблемой с этим.

Кроме того, не имеет прямого отношения к locate, но я обнаружил, что на mac этот mdfind действительно делает то, что я хочу, немного лучше, чем locate. Это интерфейс командной строки для подсветки, и он позволяет вам найти только по имени файла, если вы хотите имитировать locate:

mdfind -name <filename>

Просто используя "mdfind", вы найдете имена обоих файлов и загляните внутрь файлов (вроде grep/find вместе взятых).

Нет необходимости обновлять базу данных вручную, так как OSX предоставляет информацию о вас.

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
1
launchctl load -wF /System/Library/LaunchDaemons/com.apple.locate.plist

Если это не поможет, попробуйте:

launchctl stop com.apple.locate

launchctl start com.apple.locate
1

(это немного устарело, но так как я копал аналогичную проблему с 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, например, имеет особые требования). Если у вас есть пользовательский набор umask, вы также захотите просмотреть его.

В качестве альтернативы взлома вы можете отредактировать скрипт /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, вы, вероятно, не собираетесь обновлять сейчас;)

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .