logcat
端末を変えるシステムログを流し読みします。端末で起きていることすべての実況です。
- コマンド
- adb shell logcat
- コマンド
- システムとログ
- リスク
- 端末を変える
構文
logcat [-v <format>]フラグと引数
| トークン | 意味 |
|---|---|
| -v <format> | 行の形式を選びます。持つ価値があるのは `threadtime`(日付、時刻、pid、tid、レベル、tag)で、`brief` はより簡潔な `I/Tag( 1234):` の形です。 |
| -b <buffer> | どのリングバッファを読むか。`default` は main、system、crash をまとめて覆い、`all` は shell が開けるものすべてを取ります。このビルドが知らない名前は、無視されるのではなく名指しで断られます。 |
| -d | 流し読みせず、いまバッファにあるものを吐いて終了します。ストリームにはない境界で、自動化するものの正しい既定です。 |
| -t <count> | 最後の N 行を印字して終了します。`-d` を含意します。バッファが満杯の端末では全部を吐くより安く、何かが起きた後に前後関係を掴む実用的な方法です。 |
| -m <count> | N 行印字したら止まります。`-t` とは併用できません。あちらは天井ではなく始点を決めるものだからです。コマンドはそう言って、どちらの意味かを推測せずに終了します。 |
| -c | バッファを消します。破壊的で、しかも権限は要りません。行は消え、端末に控えは残らず、コマンドは尋ねません。 |
| -G <size> | バッファの大きさを変えます。数値のあとに乗数を付けて書き、裸の数値は断られます。新しい大きさはケーブルを抜いても残るので、このページでいちばん長生きするものです。 |
使用例
logcat -v threadtime全フィールドが揃った形式で、ビューアが解析すべきものです。
logcat -v brief古い簡潔な形。貼り付けられたログではいまも見かけます。
logcat -t 200 -v threadtime最後の 200 行を全フィールド付きで出して終了します。止め方を考えなければならないストリームを開く前に試すべき、境界のある形です。
logcat -b crash -d -v threadtimecrash のバッファだけを 1 回吐きます。アプリを殺した fatal な例外が記録される場所を、周りの何千行も抜きで見られます。
出力の読み方
出力例
07-26 13:37:01.234 1234 1250 I ActivityManager: Start proc 3062:com.example/u0a234
07-26 13:37:02.010 3062 3062 E MyApp : java.lang.IllegalStateException: not attached`threadtime` なら日付、時刻、プロセス id、スレッド id、1 文字のレベル、tag、そしてコロンと空白のあとにメッセージです。tag はそのコロンまで空白を含み得ます。すべての行がログレコードとは限りません。`--------- beginning of main` や空行はログ自身のバナーなので、解析しようとせず表示してください。
出力フィールド
| フィールド | 意味 |
|---|---|
| MM-DD HH:MM:SS.mmm | 端末自身のローカル時刻。タイムゾーンは印字されません。 |
| pid tid | プロセス id とスレッド id。同じ数値ならメインスレッドです。 |
| V D I W E F | Verbose、Debug、Info、Warn、Error、Fatal の順に深刻度が上がります。 |
| tag | 書いた側が選んだ文字列。ログを絞り込む実用的な手段です。 |
| --------- beginning of … | バッファの境界で、レコードではありません。 |
| --------- switch to … | 同じバナーのもう 1 つの形で、既に始まっているバッファから後の行が来たときに印字されます。複数のバッファを同時に読むとき、この 2 つが出どころの変わった地点をすべて印します。 |
必要な権限
root も `adb root` も、USB デバッグを超えて開発者向けオプションで入れるものも要りません。そしてこのリファレンスの大半と違い、それは既定の結果ではなく意図した付与です。`adbd` は権限を落とす前に `shell` ユーザーへ渡す補助グループの一覧に `AID_LOG` を入れます。Jelly Bean 以来アプリが自分の行しか読めないのに、ケーブルがすべてのアプリの行を読めるのはそれがあるからです。コマンド自身のヘルプも、root と log と system のユーザーだけが他の uid のログを見られると、反対側から同じことを言っています。その付与はすべてを覆うわけではありません。`security` のバッファは shell 向けには開かれず、しかも名指しで頼んだときだけは、黙って飛ばすのではなく拒否を報告する唯一のバッファです。読むことに権限は要りませんが、このコマンドができることのうち 3 つは読み取り専用ではなく、どんな書き込みとも同じ注意に値します。バッファの消去は、1 分後に欲しくなる証拠を壊します。サイズ変更はケーブルを抜いた後も残ります。ファイルへの書き出しは端末自身のストレージにバイトを置きます。3 つとも root は要らないので、集めるために接続したログを紛れ込んだフラグ 1 つが捨てるのを止めるものは、注意のほかにありません。Android Logcat Viewer はそのどれも使わずに流し読みし、絞り込みはブラウザ側でやるので、バッファは見つけたときのまま残ります。
エラーメッセージの読み解き
| メッセージ | 意味 |
|---|---|
| logcat: Unexpected EOF! | 読み手が書き手に追いつけなかったか、ロギングのデーモンが消えました。メッセージはさらに数行続き、2 つの原因と対処(バッファを大きくする)を名指しします。忙しい端末ではクラッシュではなくスループットの問題だからです。このストリームを消費するものは追いつくか、頼む量に境界を付けるかのどちらかで、3 つめの選択肢はありません。 |
| logcat: Unable to open log device 'security'. | そのバッファは存在しますが shell からは読めません。しかもこれは、使えないことが報告される唯一のバッファです。暗黙に選ばれて存在しないバッファは黙って飛ばされ、自分で名前を渡したときだけこの行が出ます。要求の残りの部分には影響しません。 |
| logcat: Failed to wait for logd.ready to become true. logd not running? | ロギングのデーモンが、尋ねられてから 1 秒のうちに自分を公開しませんでした。起動の早い時期と、デーモンを再起動した後には想定内です。ログ自体が失われたわけではなく、端末の起動が終わってからもう一度尋ねるのが対処のすべてです。 |
| logcat: Unknown buffer 'radio1' listed for -b. | そのバッファ名はこのビルドが知るものではありません。使える組はリリースやベンダーで固定ではないので、他の端末から一覧を持ち込まず `logcat --help` で端末に尋ねてください。そしてこのコマンドは、認識できたバッファを読むのではなく呼び出し全体を断ります。 |
| logcat: Invalid filter expression in logcat args. | tag とレベルのフィルタ式が解析できませんでした。レベルは 1 文字、tag はコロンで終わるので、コロンを含む tag はこの方法ではまったく絞り込めず、行が届いた後に照合するしかありません。何も読まれておらず、バッファを開く前に終了します。 |
何が変わるか、そして戻る道
ログを読むだけなら何も変わりませんが、2 つのフラグは変えます。`-c` はバッファを消去し、その行は失われて端末には控えも残りません。`-G <サイズ>` はバッファのサイズを変え、この設定はケーブルを抜いても残ります。どちらもコマンドでは元に戻せません。`-G` は元のサイズを書き戻すしかないので変更前に控えておき、`-c` は消す前に `-d` で保存してください。素の `logcat`、`-d`、`-t`、`-v` は読み取り専用です。
バージョンとメーカーに関する注意
- 何かが止めるまで流れ続け、忙しい端末では毎分数千行になります。これを消費する側には上限が必要で、なければ機械が音を上げるまで増え続けます。
- 長い行は転送の途中で半分に切られ得るので、読む側はチャンクの境界をまたいで部分行を保持しなければ、100 行に 1 行くらい壊します。
- どのバッファがあるか、このビルドがどのフィルタ式を理解するかは変わります。仮定せず `logcat --help` で端末に尋ねてください。
- 他のアプリの行を読めるのは、`adbd` が権限を落とす前に shell へ `log` グループを与えているからです。要求する実行時の権限はなく、`adb root` も要りません。そしてそれは、アプリがケーブルの見るものを再現できない理由でもあります。
- 消去、サイズ変更、ファイルへの書き出しは、読むためのコマンドのページに隠れた書き込みで、どれも先に尋ねません。始まった途端に終わるストリームは、端末を責める前に紛れ込んだ消去のフラグを疑う価値があります。
これには UI があります
Android Logcat Viewer はこのコマンドを USB 経由で実行し、返ってきたものを解析します。Chromium 系ブラウザだけで、SDK も不要、どこにもアップロードしません。
関連コマンド
logcat と同じ作業で出てくるコマンド。
| コマンド | 何をするか |
|---|---|
| dumpsys dropbox | クラッシュ、ANR、tombstone を保持するプラットフォームのリングバッファ。root なしで ANR トレースを読む方法です。 |
| dumpsys activity activities | いまどのアプリが前面にいるか、そしてその背後のタスクとスタックの構造。 |
| run-as | あるアプリ自身の uid でコマンドを実行します。root なしで debuggable ビルドのプライベートファイルを読む方法です。 |
他のシステムとログコマンド
Web ADB ツール群のパーサを書きながら、AOSP・toybox・カーネルのソースに突き合わせて確認しています。バージョンやメーカーで本当に挙動が変わるところは、世界の半分の端末で間違いになる数値を出す代わりに、そう書いてあります。