无法手动更新数据库以进行定位?

无法手动更新数据库以进行定位?

我一直在尝试更新 Macbook(10.6.3 Snow Leopard)上locate使用的数据库,但即使按照此命令线什么也没发生。我只是收到错误 - 如果我尝试通过 sudo 使用它,我会收到一些关于拒绝访问某某目录的提示。我尝试以 root 身份运行它(sudo su,然后是命令),但这也不起作用。退出回到我的常规终端提示符,现在我只得到

macbook:~ monte$ sudo /usr/libexec/locate.updatedb
find: .: 权限被拒绝
macbook:~ monte$

我彻底糊涂了,有点担心自己可能在这个过程中搞砸了什么。任何帮助或建议都将不胜感激!

蒙特

答案1

您的问题的解决方案非常简单。但是,如果您想更好地了解错误发生的原因以及建议的解决方案为何有效,您可以阅读整个答案。

否则,如果您只想获得答案,请直接进入“如何更新您的定位数据库?”会话。

那么locate.updatedb到底起什么作用呢?

这是当前的行为locate.updatedb

  • 如果你以 的身份运行该脚本root,该脚本将使用用户 调用自身nobody。然后,当 children 返回时,它会使用 children 进程(用户)在临时位置保存的数据库更新最终的区域设置数据库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

如何更新您的定位数据库?

现在,很简单!只需nobody在执行之前将您的工作目录更改为有权限的位置locale.updatedb

cd /
sudo /usr/libexec/locate.updatedb

答案2

您可能需要尝试修复文件权限(在磁盘实用程序应用程序中)。听起来这可能是一个问题。

此外,与locate没有直接关系,但我发现在mac上mdfind实际上比locate做得更好。它是spotlight的命令行界面,如果你想模仿locate,它允许你只通过文件名进行查找:

mdfind -name <filename>

只需使用“mdfind”即可找到文件名并查看文件内部(类似于 grep/find 的组合)。

无需手动更新数据库,因为 OSX 会为您维护聚光灯信息。

答案3

launchctl load -wF /System/Library/LaunchDaemons/com.apple.locate.plist

如果没有帮助,请尝试:

launchctl stop com.apple.locate

launchctl start com.apple.locate

答案4

(这有点旧了,但是因为我今天正在研究 10.6 中的类似问题......)

macbook:~ monte$ sudo /usr/libexec/locate.updatedb
find: .: Permission denied
macbook:~ monte$

确切地说,这并不是问题 - 这是locate.updatedb 对nobody发出su'ing的副作用,但是你的主目录不能被“nobody”用户读取。

您可能会发现系统文件仍可通过locate找到,但主目录中的任何文件都无法找到。您需要使主目录可读/可执行。例如:

chmod a+rx $HOME

您可能还需要检查主目录的内容 - 但您可能不想对整个树进行递归 chmod。(例如,~/.ssh 有特定要求)。如果您有自定义 umask 设置,您也需要检查它。

作为一种 hackaround 替代方法,您可以编辑 /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,您可能不会现在更新;)

相关内容