我一直在尝试更新 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,您可能不会现在更新;)