web-dev-qa-db-ja.com

UNIX用の標準のキー/値データストア

私はUNIX用のkey/valueライブラリについて知っています(berkeleydbgdbmredis ...)。しかし、コーディングを始める前に、次の操作を実行できるUNIX用の標準ツールがあるかどうか疑問に思います。

$ tool -f datastore.db put "KEY" "VALUE"
$ tool -f datastore.db put -f file_key_values.txt
$ tool -f datastore.db get "KEY"
$ tool -f datastore.db get -f file_keys.txt
$ tool -f datastore.db remove "KEY"
$ etc...

ありがとう

17
Pierre

そのための標準的なツールはないと思います。 grep/awk/sedなどを除きます。ただし、これを使用すると、ロック、フォーマット、特殊文字など、他の多くの問題に注意する必要があります。

sqlite を使用することをお勧めします。単純なテーブルを定義してから、tool_get()およびtool_put()シェル関数を作成します。 sqliteはポータブルで、高速です。

あなたは無料で追加の柔軟性を得るでしょう。制約を定義したり、スクリプトを微調整するためのインデックスを作成したり、いつか他の言語でそのDBを使用したりできます。

11
Michał Šrajer

データベースが十分に小さい場合は、ファイルシステムを使用できます。このアプローチの利点は、非常にローテクであり、非常に少ないコードでどこでも機能することです。キーが印刷可能な文字で構成されており、/が含まれていない場合は、ファイル名として使用できます。

put () { key=$1; value=$2; printf %s "$value" >"datastore.db/$key"; }
get () { key=$1; cat "datastore.db/$key"; }
remove () { key=$1; rm "datastore.db/$key"; }

任意のキーに対応するには、ファイル名としてキーのチェックサムを使用し、オプションでキーのコピーを保存します(キーを一覧表示できない、または特定のエントリのキーが何であるかがわからない場合を除く)。

put () {
  key=$1; value=$2; set $(printf %s "$key" | sha1sum); sum=$1
  printf %s "$key" >"datastore.db/$sum.key"
  printf %s "$value" >"datastore.db/$sum.value"
}
get () {
  key=$1; set $(printf %s "$key" | sha1sum); sum=$1
  cat "datastore.db/$1.value"
}
remove () {
  key=$1; set $(printf %s "$key" | sha1sum); sum=$1
  rm "datastore.db/$1.key" "datastore.db/$1.value"
}

上記のおもちゃの実装はすべてではないことに注意してください。それらには、原子性などの有用な トランザクションプロパティ はありません。ただし、ファイルの作成や名前の変更などの基本的なファイルシステム操作はアトミックであり、上記の関数のアトミックバージョンを構築することは可能です。

これらのファイルシステムへの直接実装は、数千ファイルまでの小さなデータベースにのみ適した一般的なファイルシステムに適しています。この点を超えると、ほとんどのファイルシステムは大きなディレクトリに対処するのに苦労します。階層化されたレイアウトを使用することで、スキームをより大きなデータベースに適合させることができます。たとえば、すべてのファイルを1つのディレクトリに保存するのではなく、名前の最初の数文字に基づいて別々のサブディレクトリに保存します。これは git が行うことです。たとえば、SHA-1ハッシュでインデックス付けされたオブジェクトは、.git/objects/01/2345679abcdef0123456789abcdef01234567というファイルに保存されます。セマンティックレイヤリングを使用するプログラムの他の例は、Webキャッシングプロキシ Wwwoffle および polipo ;です。どちらも、URLで見つかったページのキャッシュされたコピーをwww.example.com/HASHというファイルに保存します。ここで、HASHはURLのハッシュのエンコードです。¹

非効率のもう1つの原因は、ほとんどのファイルシステムが小さなファイルを保存するときに多くのスペースを浪費することです。通常のファイルシステムでは、ファイルのサイズに関係なく、ファイルごとに最大2kBの浪費があります。

実際のデータベースを使用することを選択した場合、透過的なファイルシステムアクセスの利便性を放棄する必要はありません。いくつかの Fuse ファイルシステムから データベースへのアクセス Berkeley DB( Jeff Garzikのdbfs )、Oracle( Oracle DBFS =)、MySQL( mysqlfs を使用)など。

¹ http://unix.stackexchange.com/questions/21943/standard-key-value-datastore-for-unixのようなURLの場合、Polipoはファイルunix.stackexchange.com/M0pPbpRufiErf4DLFcWlhw==を使用し、ファイル内にヘッダーを追加して、実際のURLをクリアテキストで示します。ファイル名は、URLのMD5ハッシュ(バイナリ)のbase64エンコーディングです。 Wwwoffleはファイルhttp/unix.stackexchange.com/DM0pPbpRufiErf4DLFcWlhwを使用します。ファイルの名前はMD5ハッシュの自家製エンコーディングであり、コンパニオンファイルhttp/unix.stackexchange.com/UM0pPbpRufiErf4DLFcWlhwにはURLが含まれています。

dbmutil あなたが望むものを手に入れるかもしれません。質問で説明する操作用のシェルユーティリティがあります。正確に標準とは言えませんが、必要な設備が整っています。

名前を付けたので、標準のredisクライアントにはredis-cliを介したコマンドラインインターフェイスがあります。 redis-cli -hからのいくつかの例:

 cat /etc/passwd | redis-cli -x set mypasswd
 redis-cli get mypasswd
 redis-cli -r 100 lpush mylist x

(ファイルシステムを介してdbにアクセスする場合は、-sでソケットを使用できます。呼び出しごとにdbインデックスを直接読み取るツールは、非常に非効率的です。)

5

使用したい場合 GDBM GNUデータベース

DebianベースのOS(バスター)でテスト済み:

apt install gdbmtool

Stdinからfrombash gdbmtool readコマンドを使用します。

$ gdbmtool -s datastore.gdbm <<<"store KEY VALUE"
  # load from file (rows format "key: value")
$ gdbmtool -s datastore.gdbm < <(awk -F: '{print "store "$1" "$2}'  file_key_values.txt)
$ gdbmtool -s datastore.gdbm <<< "fetch KEY"
  # fetch many keys (only values outputed in order)
$ gdbmtool -s datastore.gdbm < <(awk '{print "fetch "$1}' file_keys.txt)
$ gdbmtool -s datastore.gdbm <<<"delete KEY"
$ gdbmtool -s datastore.gdbm list

でより多くの man gdbmtool

投げ捨てる

$ gdbm_dump datastore.gdbm > mydump.txt

ロードダンプ

$ gdbm_load mydump.txt datastore.gdbm
0
Sylvain