treedown’s Report

システム管理者に巻き起こる様々な事象を読者の貴方へ報告するブログです。会社でも家庭でも"システム"に携わるすべての方の共感を目指しています。

※https化しました。その影響でしばらくリンク切れなどがあるかもしれませんが徐々に修正していきます。 リンク切れなどのお気づきの点がございましたらコメントなどでご指摘いただけますと助かります。

sambaサーバのファイルロックでsmb.conf設定変更

最近sambaサーバの共有フォルダに保管してあったスクリプトを実行するときに「ファイルが他で使用中です。」とエラーが出ることがあり、その対処をご報告です。

現象と環境

ちょっと環境依存な部分が多い今回の話、PalletControlというサードパーティ製品を使用している共有フォルダで、PalletControlでPC起動時に自動実行されるスクリプトの一部でエラーが出るようになった、という話です。

共有フォルダはsambaサーバで構成されたファイルサーバの共有、その共有フォルダ内にPalletControlで自動実行されるスクリプトが保管されています。

そのスクリプトはPalletControlクライアントがインストールされている各PCで起動(サインイン)時に自動実行されるのですが、そのスクリプトの一部実行時に

「プロセスはファイルにアクセスできません。別のプロセスが使用中です。」

というメッセージが表示されてスクリプトが実行されなかったり、冒頭に記載した

「ファイルが他で使用中です。ファイル名 = %共有フォルダ%\スクリプト名」

というエラーメッセージが表示されたりとエラーになることが何回かありました。

また、これは散発的に発生し、時間が経過すると収まる(エラーにならなくなる)という動きをしていたため、調査に手間取ったという側面もありました。

調べる

いくつか調べていったものの、これだと思える動きを発見できていなかったのですが、以下で特定することができました。

エラーのタイミングで(PCの)プロセスを(タスクマネージャの詳細タブで)監視しているとエラーになるコマンドラインを確認することができます。※以下

タスクマネージャの「列の選択」オプションで上記のように「コマンドライン」を有効にしておくと、例えばsvchost.exe内で実行されるコマンドの中身が確認できるようになります。この機能を利用して、エラー発生時のプロセス(で実行されるスクリプト名)を特定しました。

で、特定したスクリプト名をメモしておいて、今度はsambaサーバ側での確認です。

コマンド:smbstatus
を使ってsambaサーバの状況を確認していると、エラーの起きるスクリプトファイルとエラーにならないスクリプトファイルに差があることが分かりました。

「smbstatus」実行後に「Locked files:」にあるロックファイルの表記を確認すると、

エラーにならないほうのファイルは「Access」が0x100081、「Oplock」の箇所がNONEとなっているのに対して、
エラーになるスクリプトファイルは「Access」が0x120089、「Oplock」の箇所がLEASE(RWH)となっていて、「LEASE(RWH)」の表記になったファイルはしばらく「Locked files:」に記録される、という動きをしていました。

「Oplock」と「LEASE(RWH)」が鍵になりそうです。

「Oplock」と「LEASE(RWH)」とは何か

ロックファイルの表記にあったように、RDONLY=ReadOnly(DENY_WRITEの表示もあるので書き込み拒否でロックされている)でファイルを開いているので、WordやExcelファイルのようにロックファイルで排他アクセスの禁止というようなロックがかかっているわけではないと判断できましたが、実際にファイルを取り扱う際には排他アクセスの禁止が掛けられているときのような動きをスクリプトファイルが見せています。

「Oplock」の欄には「LEASE(RWH)」と表示されていて、

「Oplock」はOpportunistic Lock(オポチュニスティックロック)と言って、クライアント(ここではPC側)がファイルアクセスを独占してファイルの内容をキャッシュするという動きをするようです。

※参考:日本Sambaユーザ会:smb.conf
https://www.samba.gr.jp/project/translation/current/htmldocs/manpages/smb.conf.5.html#OPLOCKS

↑「oplocks (S) 」のセクションにoplock (opportunistic lock = 便宜的ロック)の解説があります。

※参考2:日本Sambaユーザ会:Chapter 17. ファイルとレコードのロッキング
https://www.samba.gr.jp/project/translation/Samba3-HOWTO/locking.html

↑「Opportunistic Lockingの概要」以下の解説が参考になります。

PC側にsambaサーバがスクリプトファイルをキャッシュしてよい、と許可することでファイルの読み書きが高速化するのですが、その代償としてファイルはロックされ、他のユーザからアクセスできなくなるようにsambaサーバが制限する、という動きをしているようです。

スクリプトファイルはReadOnlyで使われているのですが、Oplockによって使用中のクライアントに独占的なロックをsambaサーバが提供してしまっている、ということのようです。つまり、このOpportunistic Lockが今回のエラーの要因ということのようです。

対処を考える

今回の対処としては、sambaサーバの該当する上記が発生している共有フォルダだけに設定を入れて動作の検証・対処としました。

再度、前述の
※参考:日本Sambaユーザ会:smb.conf
https://www.samba.gr.jp/project/translation/current/htmldocs/manpages/smb.conf.5.html

から、以下のオプションに効果があることが分かりました。

oplocks (S) で oplockオプションの有効化・無効化の解説が確認できます。
level2 oplocks (S) で共有上で level2(読みとり専用) oplockサポートについての記述が確認できます。
kernel oplocks (S) ではカーネルベースの oplocksについての解説が確認できます。
また、SMB2以降のoplocksは「smb2 leases (G) 」で制御することになるようです。
※ページにはsmb2 leasesが「SMB2 特有の機能であり、クライアントに、SMB1 の oplock 機能 によるキャッシュ以上に、積極的にファイルをローカルにキャッシュできる。」と記載があります。

基本的にWindows側のプロセスはファイルをReadOnlyで使うような動きをするため、sambaサーバがキャッシュによる独占を許可する必要性はないといえます。

ファイルロックの「LEASE(RWH)」は上記のoplocksとsmb2 leasesオプションのデフォルト値によって動作が変化しますので、今回の対象となる共有フォルダでだけ、これらのオプションを明示的に無効化し、sambaサーバがキャッシュを独占的に提供する動作を制限する必要があると考えられました。

ただし、今回の共有フォルダではログやWord・Excelファイルといった文書ファイルはなくスクリプトファイルしかありませんし、アクセスもWAN経由でのアクセスはなく、すべてLAN(有線or無線)経由でのアクセスとなります。そのためキャッシュ効果はすべて無効化してエラーを抑制する方法で正しいと考えました。

対処する=smb.conf追記

/etc/samba/smb.confファイルを以下のように追記しました。

※smb2 leasesなどは[global]セクションに記載するオプションではあるのですが、影響を考慮して共有フォルダ内に今回は設定しています。

※設定前
--------------------------------------------------------------
[ShareFolder]
        comment = scripts & installers (oplock/lease disabled)
        path = /home/samba/Share1
        read only = no
        browseable = no
        inherit permissions = yes
        inherit acls = yes
        create mask = 0777
        directory mask = 0777
--------------------------------------------------------------

※設定後:「oplocks = no/level2 oplocks = no/kernel oplocks = no/smb2 leases = no」を追記しています。
--------------------------------------------------------------
[ShareFolder]
        comment = scripts & installers (oplock/lease disabled)
        path = /home/samba/Share1
        read only = no
        browseable = no
        inherit permissions = yes
        inherit acls = yes
        create mask = 0777
        directory mask = 0777
        oplocks = no
        level2 oplocks = no
        kernel oplocks = no
        smb2 leases = no
--------------------------------------------------------------

追記後にtestparm実行で、今回追記した部分の構文エラーが出力されないことを確認し、

systemctl restart smbd

にてsambaサーバのプロセスをリスタートしました。

これで対処は完了です。

設定更新後の動作確認

確認はsmbstatusでもいいのですが、実際にエラーが出ていたPCを動作させつつ、リアルタイムでsmbstatusの動作を確認するため、

watch -n 1 smbstatus

を使うと便利でした。上記で実行すると、topのようにsmbstatusの実行結果がリアルタイムで画面上に表示更新されていきます。

LEASE(RWH)だったOplock欄がNONEで処理されるようになりました。

今回は共有フォルダ内にスクリプトやインストーラだけでWord&Excelのような文書ファイルが存在しない共有なので、これらのキャッシュ無効化による設定でファイルロックを制御しエラーの解消ができました。

ファイルの作成・編集が頻繁に実行されるWord&Excelといった文書ファイルを保存する共有だった場合、今回実施した設定とは全く逆となり、oplocks関連やsmb2 leasesの設定は「yes」で有効化されていることが推奨設定となりますので、注意が必要となります。