web-dev-qa-db-ja.com

見つけるためにデータベースを手動で更新できませんか?

Macbook(10.6.3 Snow Leopard)のlocateで使用されるデータベースを更新しようとしていますが、この thread に示されているコマンドを実行しても、どこにも到達しません。エラーが発生するだけです。Sudo経由で使用しようとすると、such-n-suchディレクトリのアクセスが拒否されたというラケットが表示されます。 root(Sudo su、次にコマンド)として実行しようとしましたが、それも機能しませんでした。通常のターミナルプロンプトに戻ると、

macbook:〜monte $ Sudo /usr/libexec/locate.updatedb
検索:。:許可が拒否されました
macbook:〜monte $

私は完全に混乱していて、その過程で何かをホースで止めたのではないかと半分恐れています。どんな助けや提案も大歓迎です!

モンテ

5
memilanuk

(ディスクユーティリティアプリケーションで)ファイルのアクセス許可を修復してみることをお勧めします。それが問題になるかもしれないように聞こえます。

また、ロケートとは直接関係ありませんが、Macでは、mdfindが実際にロケートよりもかなり優れた方法で実行することがわかりました。これはスポットライトへのコマンドラインインターフェイスであり、ロケートを模倣したい場合はファイル名だけで検索できます。

mdfind -name <filename>

「mdfind」を使用するだけで、ファイル名が検索され、ファイル内が検索されます(grep/findを組み合わせたもの)。

OSXがスポットライト情報を保持しているため、データベースを手動で更新する必要はありません。

7
Ted Naleid

あなたの問題の解決策は非常に簡単です(そしてそれはこの答えの最後にあります)。ただし、エラーが発生している理由と提案されたソリューションが機能する理由を詳しく知りたい場合は、回答全体を読むことができます。

Locate.updatedbは正確には何ですか?

これはlocate.updatedbの現在の動作です。

  • スクリプトをrootとして実行している場合、スクリプトはユーザーnobodyで再度呼び出し、その後、子が戻り、子プロセスによって保存されたデータベースで最終的なロケールデータベースを更新します(nobody user)を一時的な場所に置き、終了します。

コード(/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)で実行する場合、スクリプトはシステムにインデックスを付け(権限のないパスを無視します)、結果を一時ファイル(実際には以前のファイル)に保存します。父親によって作成された一時ファイル);
    • したがって、ロジックの一部はrootとして実行され、他の部分はnobodyとして実行されます。
    • スクリプトがSudoなしで呼び出された場合、スクリプトは機能しません(rootのみが/var/dbディレクトリで権限を持っています)。つまり、最初はスクリプトをrootとして実行する必要があります。
    • その結果、locate.updatedbは家の中のファイルにインデックスを付けることができません(nobodyユーザーにはアクセスする権限がありません)。
    • locate.updatedbは、ユーザーが別のユーザー(別のホームディレクトリ)に属するファイルの名前を見つけることができないため、この方法でインデックスを作成すると思います。
    • 家の中のファイルを見つけたい場合は、@ ted-naleidによって提案されているようにmdfindを使用できます。

いくつかのコード(/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ユーザーとして起動すると言われていました。ただし、スクリプトに権限がないworkdir内でスクリプトを開始することはできません

おそらく、家の中で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)を設定すると、workdirに応じて、エラーが表示される場合と表示されない場合があります。

$ 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

ロケートデータベースを更新する方法は?

今、それは簡単です! locale.updatedbを実行する前に、workdirをnobodyが権限を持っている場所にのみ変更してください。

cd /
Sudo /usr/libexec/locate.updatedb
5
launchctl load -wF /System/Library/LaunchDaemons/com.Apple.locate.plist

それでも問題が解決しない場合は、次を試してください。

launchctl stop com.Apple.locate

launchctl start com.Apple.locate
1
Adrian Zaugg

(これは少し古いですが、今日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または手動で機能するはずです。ただし、OSを更新すると元に戻る可能性があります。 (それに直面しましょうが、2014年にまだ10.6を実行している場合は、おそらく今は更新しないでしょう;)

1
keen