トラブルシューティング
最後に,問題が発生したときの対処方法について説明を行い,本記事を終了したいと思います.
ログメッセージの確認
問題発生時にまず行うべき事柄の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
での検索してみてください.
もし同様の問題が見つからない場合は,問題を登録してください.既に問題の回避・解決方法が分かっている場合は,その方法も一緒に登録しましょう.同様の問題に悩んでいる人の手助けになります.