The solution for your problem is very simple (and it can be found at the end of this answer). But if you want to know better why the error is occurring and why the proposed solution works, you can read the entire answer.
What exactly does locate.updatedb?
This is the current behavior of locate.updatedb
:
- If you are running the script as
root
, it calls itself again with the user nobody
and, then the children returns, it updates the final locale database with the database saved by the children process (nobody
user) in a temporary location, and then exits;
Code (/usr/libexec/locate.updatedb
, line 31, with additional comments added by me):
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
- When running with another user (it is, the user
nobody
), the script indexes your system (ignoring the paths which it doesn't have permission) and then saves the result in a temporary file (actually, the previously temp file created by its father); - So, part of the logic is executed as root, and other part as nobody;
- If the script is called without
sudo
, it won't work (only root
has permission in the /var/db
directory). It is, you really must initially run the script as root
; - As a result,
locate.updatedb
can't index files inside your home (the nobody
user doesn't have permission to access it); - I think
locate.updatedb
indexes this way because it will be impossible to an user to discover name of files that belongs to another user (in another home directory); - If you want to locate files inside your home, you can use
mdfind
, as proposed by @ted-naleid.
Some code (/usr/libexec/locate.updatedb
, line 93, with additional comments):
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 [...]
Why are you getting "Permission Denied" errors?
It was said that locale.updatedb
launchs a new instance of itself as the nobody
user. However, you can't start a script inside a workdir in which the script has no permission.
Probably, you are getting "Permission denied" errors because you're running locale.updatedb
inside your home.
I'm creating a simple script to show this fact:
#!/bin/bash if [ $(id -un) != "nobody" ]; then sudo -u nobody "$0" exit 0 fi find / -mindepth 1 -maxdepth 1 | wc -l
If you put this script inside /tmp/test.sh
and set execution permission to it (chmod +x /tmp/test.sh
), depending of your workdir, it can show or not errors:
$ 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
How to update your locate db?
Now, it's simple! Only change your workdir to a place where nobody
has permission before executing locale.updatedb
:
cd / sudo /usr/libexec/locate.updatedb