トラブルシューティング

最後に,問題が発生したときの対処方法について説明を行い,本記事を終了したいと思います.

ログメッセージの確認

問題発生時にまず行うべき事柄の1つは,システムから出力されるログを確認することです.以下のコマンドは,mirakcコンテナーの最新1000行のログを表示します.

sudo docker logs --tail=1000 mirakc

特定のログレベルのメッセージのみ表示させたい場合は,grepを使います.

sudo docker logs --tail=1000 mirakc 2>&1 | grep -e WARN -e ERROR

例えば,受信できないチャンネル番号が指定されていた場合,以下のようなエラーが出力されます.

... scan-services: Failed: JSON error: EOF while parsing a value at line 1 column 0
... sync-clocks: Failed: JSON error: EOF while parsing a value at line 1 column 0

ログレベルを変更することで,より多くの情報を得られるようになります.

# docker-compose.ymlからの抜粋
...
    environment:
      # mirakcのログレベルをdebugに
      RUST_LOG: info,mirakc=debug

フィルター等の外部プログラムがstderrに出力するログを確認したい場合は,環境変数 MIRAKC_DEBUG_CHILD_PROCESSを以下のように定義してください.

# docker-compose.ymlからの抜粋
...
    environment:
      MIRAKC_ARIB_LOG: info
      MIRAKC_ARIB_NO_TIMESTAMP: 1
      MIRAKC_DEBUG_CHILD_PROCESS: 1
      RUST_LOG: info,mirakc=debug

環境変数MIRAKC_ARIB_LOG_NO_TIMESTAMP=1を定義すると,mirakc-aribのログメッセージからタイムスタンプを削除できます.

デフォルト設定では,mirakc-aribは何もログを出力しません.必ず,環境変数 MIRAKC_ARIB_LOGでログレベルを指定してください.RUST_LOGのように,コマンド毎にログレベルを指定することも可能です.

# docker-compose.ymlからの抜粋
...
    environment:
      # filter-serviceとfilter-programはdebug,それ以外はinfo
      MIRAKC_ARIB_LOG: info,filter-service=debug,filter-program=debug

MIRAKC_ARIB_LOGに指定可能なログレベルの一覧が こちらにあります.

パイプラインの動作確認

mirakcは,TSストリームに関する処理のほぼ全てを外部プログラムで実行します.この設計には,余分なリソースを消費するデメリットがある一方で,以下のようなメリットがあります.

  • 既存のTSストリーム処理を行うプログラムを再利用できる
  • スクリプト等でTSストリーム処理をカスタマイズできる
  • TSストリーム処理部のみ取り出しでデバッグできる

mirakcでは,TSストリーム処理プログラムをパイプで連結したものを「パイプライン」と呼んでいます.パイプラインの基本的構成については こちらを参照してください.

ログレベルをdebugに変更すると,パイプラインに関するログが出力されるようになります.

... DEBUG pipeline{id=0.0 label="tuner"}: ...
... DEBUG pipeline{id=0.0.1 label="epg.scan-services"}: ...
... DEBUG pipeline{id=0.1.1 label="epg.sync-clocks"}: ...

上記のように,パイプラインには一意のidと処理毎にlabelが付与されています.これらを使いログをgrepすることで,特定のパイプラインの動作を確認できます.

各パイプラインの最初のログには,以下のように実行したコマンドの情報が出力されます.

... Spawned command="<実行したコマンド>" pid=<そのPID>

動作確認対象のパイプラインを構成するコマンドを集めた後,これらを直接実行することで問題の発生源を切り分けることが可能です.以下はGET /api/channels/GR/27/stream で実行されるパイプラインを直接実行する場合の例です.

# チューナーコマンドで`curl`を,`decode-filter`に`socat`を使用しています
curl -fsSL http://remote:40772/api/channels/GR/27/stream?decode=0 | \
  socat -,cool-write tcp-connect:tsd:40773

通常のコマンド実行と同じなので,各プログラムのログレベルを変更することも,gdb などをアタッチすることも可能です.

フィルターの動作確認

フィルターで問題が発生している場合,フィルターに指定した外部プログラムを単独実行することで,問題の切り分けが可能です.

例えば,以下のコマンドでmirakc-arib filter-serviceの動作を確認できます.

sudo docker exec -it mirakc sh -c \
  'curl -s http://localhost:40772/api/channels/GR/27/stream?decode=0 | \
     MIRAKC_ARIB_LOG=debug mirakc-arib filter-service --sid=1024 >/dev/null'

本記事では説明しませんでしたが,ジョブ設定(jobs)に指定されている外部プログラムも上記と同様の方法で動作を確認できます.

EPGStationの番組表が更新されない

稀にこのような状況が発生します.考えられる原因が複数存在するため,1つづつ確認してください.

空きチューナーが存在しない

EPG関連のジョブの優先度は低く設定されているため,ストリーミングにより全てのチューナーが使用されていると,番組表更新のためのジョブが実行できません.その結果,いつまで経っても番組表が更新されないという状況が発生します.

以下のコマンドでチューナーの使用状況が確認できます.

curl -s http://mirakc:40772/api/tuners | jq .[].isFree

全てのチューナーが使用されている場合,falseのみが表示されます.

この状況では,少なくとも1つのチューナーを開放しないと,番組表は更新されません.

EPG関連ジョブが終了しない

EPG関連ジョブは多くても1つだけ実行されるようになっています.そのため,あるEPG関連ジョブが終了しなくなると,他のEPG関連ジョブを実行することができず,番組表が更新されない状態に陥ります.

この状態に陥った場合,以下のようなログが繰り返し出力されます.

... WARN mirakc::job: update-schedules: Already running, skip

update-schedulesジョブは,進捗しない状態が30秒続くと停止するようになっています.この値は,config.jobs.update-schedules.commandのコマンドラインオプションとして指定可能です.詳しくはmirakc-arib -h collect-eitsを参照してください.

ジョブ停止時間を過ぎても停止しない場合,特定セクションのデータが到着しないような状況に陥っています.この場合は,update-schedulesジョブを停止するしかありません. psコマンドでジョブのPIDを調べてkillしてください.ジョブは登録してある時間になったら再び実行されるので,これをkillしても問題ありません.

いちいちPIDを調べてkillするのが面倒だという人は,timeoutをジョブのコマンドに付けておきましょう.以下の例では,update-schedulesジョブの最大実行時間を10分に設定しています(Mirakurun互換の動作).

jobs:
  update-schedules:
    command: >-
      timeout 600 mirakc-arib collect-eits
      {{#sids}} --sids={{{.}}}{{/sids}}{{#xsids}} --xsids={{{.}}}{{/xsids}}
    schedule: '0 7,37 * * * * *'

timeoutによりジョブが中断された場合,番組表の一部が未取得・未更新の状態になります.前述のように,ジョブは再実行されるため,時間が経てば全ての番組情報が取得されます.

No space for tnuer#x.x.x, drop the chunk

mirakcはチューナー共有をサポートしており,チューナーから読み込んだデーターをクライアント毎のキューに書き込みます.このキューが溢れた場合,以下のようなワーニングメッセージが出力されます.

...: No space for tuner#0.6.1, drop the chunk

本事象に関する問題がいくつか報告されています.

解析の結果,環境依存問題であることがわかっています.まずはログレベルを上げてログメッセージから何が起きているのか確認してください.その後の対処は,発生している事象に依存するため,ここで明確に対処法を記述することはできません.上記報告済み不具合のやり取りを確認の上,自分で問題を解決してください.もちろん,mirakcの不具合と思われる事象については,問題を登録していただけると助かります.

mirakc/mirakcイメージでTSストリームがデコードできない

mirakc/mirakcイメージにはTSストリームをデコードするためのコマンドが含まれていません.そのため,このイメージに対してarib-b25-stream-testを設定すると,以下のようなエラーが表示されて,TSストリームを取得できなくなります.

$ curl -sG http://localhost:40772/api/channels/GR/27/stream
{"code":500,"reason":null,"errors":[]}

# actix-webのログレベルをdebug以上に設定しておく必要があります
$ docker logs mirakc | grep arib-b25-stream-test
... DEBUG ... CommandFailed(UnableToSpawn("arib-b25-stream-test", ...

デコードするためには,以下のいずれかの対応が必要です.

  • filters.decode-filter.commandに指定したコマンドを含むカスタムイメージを作成する
  • filters.decode-filter.commandに指定したコマンドをdocker run-vオプションでホスト上のコマンドをコンテナーにマウントする
    • ただし,コンテナー内で実行可能なコマンドに限る
  • socatを使って外部サーバー上でデコードする

mirakc-timeshift-fsが起動しない

mirakc-timeshift-fs起動時に以下のようなエラーメッセージが表示され起動できない場合,

Error: IoError(Os { code: 2, kind: NotFound, message: "No such file or directory" }

fusermount(もしくはfusermount3)が環境にインストールされていないか,インストール先がPATHに含まれていない可能性があります.

docker/Dockerfile.debian などを参考に,不足パッケージをインストールし,PATHを適切に設定してください.

-o allow_otherなどのオプションを使用する場合は,起動前に/etc/fuse.confを適切に設定しておく必要があります.詳細はman fuseを参照してください.

GitHub Issuesの検索

同様の問題が他の人の環境でも発生している場合,GitHub Issuesに既に報告済みかもしれません.思いつくキーワードを指定して,報告済みの問題を検索することで,解決方法が見つかるかもしれません.

問題が既に解決済みである場合もあります.is:closedでの検索してみてください.

もし同様の問題が見つからない場合は,問題を登録してください.既に問題の回避・解決方法が分かっている場合は,その方法も一緒に登録しましょう.同様の問題に悩んでいる人の手助けになります.

results matching ""

    No results matching ""