Sambaで公開しているボリュームをSpotlight検索できるようにしたので、備忘録を書いておく。
なぜSpotlightを動かそうと思ったのか
TimeMachineをsamba上で動かそうとしていた所、うまく動作しない理由にSpotlightが関係しているらしいと思われた。これを検証する為に動かしてみた。下のリンク先はそのドタバタ記である。
前提
- 「Spotlightが動作した」と言うだけ1であり、それ以上の検証は行っていない。
- 筆者はJavaやelasticsearchでは ど素人 なので、elasticsearchやfscrawlerの設定には ほぼ確実に 不適切な所があると思われる2。ご指摘頂ければ幸いである。
- elasticsearchへのアクセスにはパスワードすら設定できない。これはsamba4.1.13でパスワード等を指定する手段が無い為。おそらく近い将来のバージョンでサポートされると思われる。
- 以下の例では、sambaサーバ上の
/share1, /share2
と言うディレクトリを、それぞれShare1, Share2
と言う名前で公開している。
環境
- OS: FreeBSD 12.2-RELEASE-p11 amd64
- samba: 4.13.14
samba
sambaのコンパイル
ports/pkg の sambaは、Spotlight非対応である。よってportsをSpotlight対応に設定した上で、コンパイル&インストールする必要がある。
# cd /usr/ports/net/samba413
# make config
(SPOTLIGHTにチェックを入れる)
# make clean all deinstall reinstall
smb4.conf
最低限必要な設定は、[global]
セクションに
# Spotlight
spotlight backend = elasticsearch
elasticsearch:address = 127.0.0.1
elasticsearch:port = 9200
を追加し、Spotlightをサポートするボリュームに、
spotlight=yes
を加えれば良い。
参考までに筆者が運用しているsmb4.confの抜粋を以下の折りたたみ部分に示す。
`smb4.conf`の例
[global]
workgroup = WORKGROUP
security = USER
server min protocol = SMB2
server string = <your server>
server role = standalone server
dos filemode = yes
store dos attributes = yes
map archive = no
unix extensions = no
# veto files
delete veto files = yes
veto files = /._*/.DS_Store/
# Spotlight
spotlight backend = elasticsearch
elasticsearch:address = 127.0.0.1
elasticsearch:port = 9200
# vfs
# ZFSの場合
vfs objects = zfsacl catia fruit streams_xattr
# UFSの場合
# vfs objects = acl_xattr catia fruit streams_xattr
# vfs_zfsacl
nfs4:chown = yes
# vfs_fruit
fruit:zero_file_id = yes
fruit:metadata = stream
fruit:veto_appledouble = no
fruit:resource = xattr
fruit:model = PowerMac
# vfs_streams_xattr
streams_xattr:store_stream_type = no
streams_xattr:prefix = user.
[Share1]
path = /share1
read only = no
valid users = <yourname>
browseable = yes
writable = yes
spotlight = yes
[Share2]
path = /share2
read only = no
valid users = <yourname>
browseable = yes
writable = yes
spotlight = yes
elasticsearch
インストール
# pkg install elasticsearch7 openjdk15
設定
elasticsearch本体の設定
cluster.name: samba
node.name: node1
path.data: /var/db/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 127.0.0.1
http.port: 9200
xpack.ml.enabled: false
discovery.type: single-node
xpack.security.enabled: false
JVMの設定
####################################
## IMPORTANT: JVM heap size
####################################
:
(略)
:
##
## -Xms4g
## -Xmx4g
##
を、以下のように変更(heap sizeを2GByteにする場合)
-Xms2g
-Xmx2g
elasticsearchは、デフォルトでは物理メモリの半分を確保してしまう。Spotlightのみに使うなら、2Gbyte程度で十分である。
以下のscript(esmem.py)でelasticsearchが消費しているheapの割合を調べられるので、割り当て量が妥当か確認できる。
スクリプト: `esmem.py`
#!/usr/bin/env python3
import requests
import json
import time
r = requests.get('http://localhost:9200/_nodes/stats/jvm')
j = json.loads(r.text)
for node in j['nodes'].items():
id, properties = node
timestamp = time.strftime('%Y-%m-%d %H:%M:%S %z',
time.localtime(properties['timestamp']/1000))
name = properties['name']
total = properties['jvm']['mem']['heap_used_percent']
percent = properties['jvm']['mem']['heap_used_percent']
print(timestamp, name, percent, sep=',')
break
/etc/rc.conf
以下を追加
# elasticsearch
elasticsearch_enable="YES"
elasticsearch_java_home="/usr/local/openjdk15"
起動
$ sudo service elasticsearch start
起動後の設定
以下の設定3 により、クラスタヘルスが yellow → greenとなった。
# 新しく作られるインデックスのレプリカ数を 0 に設定する。
$ curl -H "Content-Type: application/json" -XPUT localhost:9200/_template/template_1 -d '
{
"template" : "*",
"settings" : {
"number_of_shards" : 1, "number_of_replicas" : 0
}
}'
# 既にインデックスが存在する場合、レプリカ数を 0 に変更する。
$ curl -H "Content-Type: application/json" -XPUT localhost:9200/*/_settings -d '{"number_of_replicas":0}'
fscrawler
インストール
こちらから適切なパッケージをダウンロードし、適当なディレクトリに展開する。
ここでは例として、fscrawler-es7-2.9.zip
をダウンロードし、/usr/local/fscrawler-es7-2.9/
に展開、/usr/local/fscrawler -> fscrawler-es7-2.9
と言うシンボリックリンクを張った。
$ cd /usr/local
$ sudo unzip <somewhere>/fscrawler-es7-2.9.zip
$ sudo ln -s fscrawler-es7-2.9 fscrawler
設定
実行時の設定
fscrawlerの実行時の設定ファイルは、defaultでは実行ユーザの$HOME/.fscrawler/
以下に置かれるが、ここでは /usr/local/fscrawler/config/
以下に置く事とする。
以下を実行する。
$ sudo JAVA_HOME=/usr/local/openjdk15 /usr/local/fscrawler/bin/fscrawler job_share1 --config_dir /usr/local/fscrawler/config/
その結果、/usr/local/fscrawler/config/job_share1/_settings.yaml
が生成されるので、これを編集する。
---
name: "job_share1"
fs:
url: "/share1"
update_rate: "15m"
excludes:
- "*/~*"
- "*/*~"
- "*/[.]*"
json_support: false
filename_as_id: false
add_filesize: true
remove_deleted: true
add_as_inner_object: false
store_source: false
index_content: true
attributes_support: false
raw_metadata: false
xml_support: false
index_folders: true
lang_detect: false
continue_on_error: true
ocr:
language: "eng"
enabled: true
pdf_strategy: "ocr_and_text"
follow_symlinks: false
elasticsearch:
nodes:
- url: "http://127.0.0.1:9200"
bulk_size: 100
flush_interval: "5s"
byte_size: "10mb"
ssl_verification: false
変更したのは、name
(セッション名), url
(インデックスを作る対象のpath), excludes
(インデックス対象から除外するpath), continue_on_error
(エラー発生時に続けるか), ssl_verification
(SSL証明書の検証を行うか)のみである。
最初excludes:
でdotで始まるファイルを除外するために、- "*/.*"
としていたが、これでは正常動作しない。
- "*/[.]*"
とするのが正しい。
上記と同様に、
$ sudo JAVA_HOME=/usr/local/openjdk15 /usr/local/fscrawler/bin/fscrawler job_share2 --config_dir /usr/local/fscrawler/config/
を実行し、/usr/local/fscrawler/config/job_share2/_settings.yaml
を適宜編集する。
cron
fscrawlerはsambaサーバ上に常駐させる事もできるが、ここではcronで定期的に動作させる事にする。
#!/bin/sh
export JAVA_HOME=/usr/local/openjdk15
export FS_JAVA_OPTS="-DLOG_DIR=/var/log/fscrawler"
args="--loop 1 --config_dir /usr/local/fscrawler/config"
OPTS=""
JOBS=""
for OPT in "$@"; do
case $OPT in
--*)
OPTS="$OPTS $OPT"
;;
*)
JOBS="$JOBS $OPT"
;;
esac
done
for job in $JOBS; do
/usr/local/fscrawler/bin/fscrawler $job $OPTS $args
done
fscrawler.sh
では環境変数FS_JAVA_OPTS
によりログを/var/log/fscrawler
以下に保存するように設定しているが、fscrawler-es7-2.7
ではcronから実行した場合ログが正常に保存されなかった。なおfscrawler-es7-2.9
にバージョンアップする事で解決した。
# fscrawler
#%M %H %d %m %w user command
0 4 * * 1-6 root /usr/local/sbin/fscrawler.sh --silent job_share1 job_share2
0 4 * * 0 root /usr/local/sbin/fscrawler.sh --silent --restart job_share1 job_share2
その他
fscrawlerにインデックスを作らせたくないディレクトリには、.fscrawlerignore
と言うファイルを作っておく。
$ cd somewhere-you-want-to-hide-from-spotlight
$ touch .fscrawlerignore
なお上記設定では、.(dot)で始まるか、~(tilde)が先頭か最後に付いているファイル・ディレクトリを無視するように設定している。
ログ4の整理
上記設定では、elasticsearchは/var/log/elasticsearch
以下にログファイルを作る。特にsamba-YYYY-MM-DD-1.{json,log}.gz
と言うファイルが毎日作成される。
同じようにfscrawlerは/var/log/fscrawler
以下にdocuments-YYYY-MM-DD.log.gz
とfscrawler-YYYY-MM-DD-[0-9]+.log.gz
と言うファイルが作成される。
これらの古い物を消したいが、UNIXで使われる newsyslog
やlogrotate
では無理である。その為Pythonで簡単なスクリプトを書いて、cron
で動かしている。
スクリプト: /usr/local/sbin/elasticlog.py
#!/usr/bin/env python3
#
# log cleaner for elasticsearch
# usage:
# elasticlog.py [-d <days>] <path>
#
# log file name
# samba-%Y-%m-%d-1.{log,json}.gz
from datetime import datetime, date, timedelta
import argparse
import os
import re
import sys
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--days", help="expire if file is older than days", ty
pe=int, default=7)
parser.add_argument("path", help="path to log files", type=str, default='.')
parser.add_argument("-n", "--dry_run", help="check files but do not remove", act
ion="store_true")
args = parser.parse_args()
if not os.path.isdir(args.path):
print(args.path, "is not a directory", file=sys.stderr)
exit(1)
if re.match(r'.*/$', args.path):
p = args.path
else:
p = args.path+'/'
reg=re.compile('(^[A-Za-z][A-Za-z0-9]*)\-([0-9]{4}\-[0-9]{2}\-[0-9]{2})')
lastdays=timedelta(days=args.days)
today=date.today()
for f in os.scandir(path=p):
m=reg.match(f.name)
if m:
fdate=date.fromisoformat((m.group(2)))
if (today-fdate) > lastdays:
if args.dry_run:
print("rm", p+f.name, file=sys.stderr)
else:
try:
os.unlink(p+f.name)
except (IsADirectoryError,FileNotFoundError,PermissionError) as f:
print(f, file=sys.stderr)
else:
if args.dry_run:
print(f.name, "is newer than", args.days, "days",
file=sys.stderr)
exit(0)
cron設定
# elasticlog.cron
#%M %H %d %m %U user command
0 11 * * * root /usr/local/sbin/elasticlog.py /var/log/elasticsearch
5 11 * * * root /usr/local/sbin/elasticlog.py /var/log/fscrawler
なおelasticsearch本体を使って行う方法もあるようだが、
よく分からなかったので使っていない。
参考
-
Samba with macOS Spotlight on FreeBSD with Elasticsearch
このページを元に調べた -
Spotlight - SambaWiki
Samba projectによるSpotlight解説 -
Elasticsearchリファレンス [5.4] | Elastic
古いバージョン向けの日本語ドキュメント -
Elasticsearch Guide [7.16] | Elastic
英語ドキュメントは、最新版が公開されている -
Welcome to FSCrawler’s documentation! — FSCrawler 2.9-SNAPSHOT documentation
FSCrawlerのドキュメント
-
実際Spotlightの動作がMac本体に比べてやや遅いような... ↩
-
elasticsearchの用語はデータベース分野の物?のせいか、理解しづらいのが一因である。 ↩
-
ここで言うログとは、UNIX文化でのログ(
/var/log/
以下に作られるファイル)を指している。データベース文化での(トランザクション)ログとは異なるので注意。 ↩