この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
CX事業本部の岩田です。
Greengrassのローカルシャドウを操作していたところ、シャドウの状態が意図通りに更新されずどハマりしてしまいました。 原因を切り分けようにもローカルシャドウの中身を確認するために、いちいちLambdaを実行するのが面倒で面倒で...
nsenter
を使って、いわゆる「コンテナの中に入る」操作を行ってからGreengrass SDKを使用すればLambdaを使わなくても行けるか?と思ったのですが、普通にGreengrass SDKを使用すると動作に必要な環境変数が不足し正常に動作しませんでした。
Greengrass SDKを正常動作させるにはGreengrass Core経由でLambdaの中で利用する必要があるようです。
色々と調べた結果、ローカルシャドウを管理しているDBを直接参照する方法を発見したのでご紹介します。
Greengrassにおけるローカルシャドウの管理
Greengrass Coreのシャドウ同期に関連するログは/greengrass/ggc/var/log/system/GGShadowSyncManager.log
に出力されます。このログファイルを眺めていたところ、以下のような出力を発見しました。
[2019-08-06T04:01:32.367Z][INFO]-Using /state/shadow/shadow.db file for sqlite3
ん?!SQLite?どうもローカルシャドウの管理にはSQLite3を利用しているようです。
ということは普通にsqlite3
コマンドから中身を覗けるのでは...
早速やってみましょう
SQLiteの中身を覗いてみる
先ほど確認した通り、ローカルシャドウのDBは/greengrass/ggc/var/state/shadow/shadow.db
に作成されています。Greengrass Coreを稼働させているOSからsqlite3
コマンドを使ってDBの中身を確認してみましょう。
DBに接続
まずは接続から...
sqlite3 /greengrass/ggc/var/state/shadow/shadow.db
SQLite version 3.7.17 2013-05-20 00:56:22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite>
テーブル一覧表示
テーブル一覧です
sqlite> .tables
doc sync
doc
とsync
2つのテーブルを持っているようです
テーブルのスキーマ表示
doc
とsync
2つのテーブルのスキーマを確認してみます
まずはdoc
テーブルから
sqlite> .schema doc
CREATE TABLE doc
(arn text not null, name text, state text);
- arn
- name
- state
3つの列で構成されています。名前から察するにこれがローカルシャドウのシャドウドキュメントを格納しているテーブルでしょう。
続いてsync
テーブル
sqlite> .schema sync
CREATE TABLE sync (arn text not null, local text, cloud text);
- arn
- local
- cloud
3つの列で構成されています。こちらがローカルシャドウとAWS IoT上のシャドウの同期を管理するテーブルなのでしょう
テーブルの中身表示
テーブルの中身を表示してみます。まずはdoc
テーブルから
sqlite> .headers ON
sqlite> select * from doc;
arn|name|state
thing_hogehoge|thing_hogehoge|{"ggFlv":{"reported":{"hoge":{"version":14}}},"isDeleted":false,"metadata":{"reported":{"hoge":{"timestamp":1565069505}}},"state":{"reported":{"hoge":"fuga"}},"version":20}
state列をフォーマットするとこのような形になります
{
"ggFlv": {
"reported": {
"hoge": {
"version": 14
}
}
},
"isDeleted": false,
"metadata": {
"reported": {
"hoge": {
"timestamp": 1565069505
}
}
},
"state": {
"reported": {
"hoge": "fuga"
}
},
"version": 20
}
続いてsync
テーブルです。
sqlite> select * from sync;
arn|local|cloud
thing_hogehoge|{"ggFlv":{"reported":{"hoge":{"version":14}}},"isDeleted":false,"metadata":{"reported":{"hoge":{"timestamp":1565069505}}},"state":{"reported":{"hoge":"fuga"}},"version":20}|{"metadata":{"reported":{"hoge":{"timestamp":1565069505}}},"state":{"reported":{"hoge":"fuga"}},"version":98}
カラムlocal
の値をフォーマットするとこのような形になります
{
"ggFlv": {
"reported": {
"hoge": {
"version": 14
}
}
},
"isDeleted": false,
"metadata": {
"reported": {
"hoge": {
"timestamp": 1565069505
}
}
},
"state": {
"reported": {
"hoge": "fuga"
}
},
"version": 20
}
先ほどのdocテーブルの中身と一致しています。
同様にcloud
の値をフォーマットすると以下のようになります
{
"metadata": {
"reported": {
"hoge": {
"timestamp": 1565069505
}
}
},
"state": {
"reported": {
"hoge": "fuga"
}
},
"version": 98
}
AWS IoT上でシャドウドキュメントを確認すると以下のような状態でした
sync
テーブルのcloud
列と同期が取れていることが分かります。
最後に
Greengrass Coreの裏側に少し詳しくなれました。 これでデバッグが捗りそうです。
誰かの参考になれば幸いです。