ロックファイルで正常終了する定期処理:38回空振りした原因

ホームラボ運用を描いたアイキャッチ画像

移設後の定期処理は、本体を起動できる状態になっていました。それでも5本の処理は仕事をせず、正常終了として記録され続けていました。失敗したのは起動ではなく、多重起動を防ぐロックの設計でした。

これは、定期処理の実行記録とログ更新時刻だけを見て「動いているはず」と判断している自宅ラボ運用者に向く記録です。終了コード0が返っても、期待した通知・同期・集計などが実行されたとは限りません。

今回の修正後、e2の起動問題を通過していた1本は17:30の定時発火で通知件数0件を出力しました。2026-07-24以降、その処理の中身が初めて実際に走った記録です。0件は成果がなかった値ではなく、処理が対象を数えに行った痕跡でした。

目次

「正常終了」と「仕事をした」は別です

定期処理には二重の多重起動防止がありました。実行環境側の排他制御と、処理内部の多重起動チェックです。どちらも必要性はありましたが、同じロックファイルの置き場所を使っていました。

外側が先にロックを取得してから本体を起動すると、内部チェックはそのロックを別の実行中処理のものだと判断します。その結果、本体は何もせず終了コード0を返しました。プログラムにとっては「安全に重複実行を避けた成功」です。しかし運用者が期待する「定期処理が仕事をした成功」ではありません。

定期実行
  │
  ├─ 外側の排他制御:ロックを取得
  │
  └─ 処理本体を起動
       │
       └─ 内部の多重起動チェック:同じロックを検出
            └─ 「別の処理が実行中」と判断 → 何もせず exit 0
実測されたロック衝突の構成。外側と内部が同じロックを使ったため、自分自身を別実行と誤認しました。

死活判定は、定期実行が発火した記録とログ更新時刻を見ていました。空振りでも終了コード0が残り、ログも更新されます。そのため監視は空振り中の処理を健全と報告し続けました。

5本の沈黙と、38回の空振り

影響を受けたのは5本でした。そのうち4本は、前回までに扱った「本体が一度も起動しない」問題にも重なっていました。1つの起動障害を取り除いても、別のロック衝突が残れば、結果として見えるのは同じ沈黙です。

残る1本は起動障害を通過していました。それでもロック衝突だけで、2026-07-24 22:30の導入以降、全38回の定期実行が空振りしていました。ログには毎回 another instance holds the lock が残っていました。

処理の状態 本数 観測された結果
起動問題とロック衝突が重なった 4本 起動の問題を直しても、ロック衝突が残れば処理結果は出ない
ロック衝突だけが残った 1本 38回すべて空振り。終了コード0とログ更新で健全に見えた

同じ日、新設した別の2本でも同じ衝突が起きました。新設時には気づいて修正できましたが、同じ書き方をした既存処理を横並びで点検するところまでは届きませんでした。移設では、ひとつ直した処理を見て全体が直ったと判断しないことが必要です。旧側が動き続けて二重になる問題も、同じように処理単位ではなく運用全体で見る必要がありました。旧側の定期処理が残って二重実行になった記録も、この移設が一度の切替で終わらなかった理由の一部です。

ロック名を分け、初めて中身が走りました

図解: ロック名分離で実行へ(外側の排他制御 / 処理内部の多重起動チェック / 38回:ロック衝突で空振り、exit 0 / ロック名を分離 / 通知件数0件を出力)
図解: ロック名分離で実行へ(AI生成)

修正は単純でした。処理内部の多重起動チェックが使うロックファイル名を、外側の排他制御とは別名に分離しました。以後、外側と内部が同じロックを取り合いません。

修正後の17:30の定時発火では、対象の1本が通知件数0件を出力しました。この数値だけで通知機能全体の状態までは判断できませんが、少なくとも「ロックを見て即座に戻る」のではなく、処理内容が実行されたことを示しています。

導入:2026-07-24 22:30
  │
  ├─ 38回:ロック衝突で空振り、exit 0
  │
  └─ ロック名を分離
       │
       └─ 17:30の定時発火:通知件数 0件を出力
起動記録だけでは見えなかった処理内容の変化。0件は、処理が通知対象を評価した実行結果です。

監視を改善するなら、発火したか、ログが更新されたかに加えて、その処理が出す仕事量の指標を残す必要があります。通知なら件数、同期なら対象数、集計なら更新行数のような値です。値が0でも、処理が評価まで進んだことを後から追えます。

「開けない」は「ロックされている」とは限りません

ロックを調べる別の場面では、他ユーザーが所有するロックファイルを管理者権限でも直接開けない現象に当たりました。置き場のディレクトリ権限は1777でした。誰でもファイルを作成できる一方、sticky bitにより他人のファイルを自由に扱えない構成です。

さらにカーネル側の保護設定との組み合わせにより、他人所有ファイルへの書き込みオープンは権限に関わらず拒否されました。ここで重要なのは、ファイルを開けなかったことは、誰かがロックを握っている証拠ではないという点です。単に、確認しようとした方法が権限の壁に止められただけかもしれません。

観測した現象 直接には分からないこと 今回使った区別の方法
ロックファイルを開けない 実際にロックが保持されているか カーネルが管理するロック一覧を読む
another instance holds the lock 期待した仕事が実行されたか 通知件数など処理内容の値を見る

この違いを分けない限り、「開けない」はすべて同じ種類の不明として残ります。今回はカーネルのロック一覧を読む方法に切り替え、ロックの実際の状態を確かめました。

移設元が静かに壊れたときも、表面上の稼働記録だけでは処理の実体を捉えられませんでした。バックアップのマウント障害を追った移設初期の記録と合わせると、起動・排他・入出力を別々に観測する必要が見えてきます。

まだ、死活判定は変わっていません

今回、同じロックを使う衝突は解消しました。ただし、終了コードだけでなく処理内容の有無を見る死活判定への改修には、まだ手を付けていません。カーネルのロック一覧を読む確認方法も、あらゆるロック箇所で徹底できているわけではありません。

「開けない」と「握られている」は別の現象です。ただ、区別する手段を持たない間はどちらも同じ「分からない」に見えます。次に定期処理を点検するときは、終了コードとログ時刻の横に、その処理が実際に扱った件数を1つ置いてください。ロックが疑わしいときは、ファイルを開けたかではなく、ロックの保持状態を見られる手段を先に選びます。

この検証を回している環境

この検証は、自宅の常設ラボ(使い捨てVM/LXCを回す母艦+GPU+VLAN分離ネットワーク)で動かしています。使っている機材と選定理由、全体構成は1本にまとめています。

ラボ構成のまとめを見る →
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

目次