`--container-id` オプションでログ取得ができなかった問題をシェル実行で解決

basecamp/kamal

--container-id フラグが期待通りにログを出力しなかった問題を、echo コマンドをシェル経由で実行する形に修正しました。これにより、コンテナ ID が正しく xargs に渡り、リアルタイムでログが取得できるようになります。

背景

--container-id が指定されたときにログが全く出力されないという不具合が Issue #1841 で報告されました。kamal app logs --container-id=CONTAINER_ID を実行しても、対象コンテナが稼働中でも停止中でも空結果でした。根本原因は、コンテナ ID を供給する echo がシェルで実行されず、xargs に入力が届かなかったことです。

技術的な変更

container_id_command メソッドにシェルラッパーを導入し、文字列型のコンテナ ID を echo で出力する処理を shell ヘルパーで実行するよう変更しました。

@@ -21,7 +21,7 @@ def follow_logs(host:, container_id: nil, timestamps: true, lines: nil, grep: ni
   def container_id_command(container_id)
     case container_id
     when Array then container_id
-    when String, Symbol then "echo #{container_id}"
+    when String, Symbol then shell(["echo #{container_id}"])
     else current_running_container_id
     end
   end

この変更により echo がシェル (sh -c) 上で実行され、出力が xargs に正しく渡ります。

テストコードも同様に期待文字列を更新し、シェルラッパーが反映されたことを検証しています。

@@ -486,9 +486,9 @@ class CliAppTest < CliTestCase
   test "logs with follow and container_id" do
     SSHKit::Backend::Abstract.any_instance.stubs(:exec)
-      .with("ssh -t root@1.1.1.1 -p 22 'echo ID123 | xargs docker logs --timestamps --tail 10 --follow 2>&1'")
+      .with("ssh -t root@1.1.1.1 -p 22 'sh -c '\''echo ID123'\'' | xargs docker logs --timestamps --tail 10 --follow 2>&1'")

-    assert_match "echo ID123 | xargs docker logs --timestamps --tail 10 --follow 2>&1", run_command("logs", "--follow", "--container-id", "ID123")
+    assert_match "sh -c '\''echo ID123'\'' | xargs docker logs --timestamps --tail 10 --follow 2>&1", run_command("logs", "--follow", "--container-id", "ID123")
   end

同様に test/commands/app_test.rb でもローカルコマンド文字列が sh -c 'echo C137' | xargs … へと更新され、シェル実行が保証されることを確認しています。

設計判断

開発者は新たにメソッドを追加するのではなく、既存の shell ヘルパーを活用する方針を採りました。これにより変更箇所は container_id_command のみで済み、Docker ログ取得ロジックや他のフラグとの互換性を保ったまま機能を補完できます。最小限の差分で目的を達成するこのアプローチは、回帰リスクを低減しつつユーザビリティを向上させます。

まとめ

--container-id オプションが正しく機能し、指定したコンテナのログがリアルタイムで取得できるようになりました。shell ラッパーの導入は既存コードへの影響を最小化し、今後の機能拡張でも同様のパターンで安全にシェルコマンドを組み立てられる基盤を提供します。

記事メタデータ

Generated by:
gpt-oss-120b for DiffDaily
LLM Trace:
43748049

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
gpt-oss-120b for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文、背景、技術的な変更、設計判断(任意)、まとめが揃っており、層構造「総論→各論→結論」が明確に示されています。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

コードブロックは正しい diff シンタックスで記載され、GitHub リンクは PR 番号が適切にハイパーリンク化されています。ファイル名付きハイライトは不要なので問題ありません。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

対象は Ruby/Rails エンジニアを想定した技術的内容で、初心者向けの過剰な説明はありません。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションは総論・各論・結論のパラグラフで構成され、トピックセンテンスが先頭に配置されています。段落は 1 トピックに絞られ、長さも適切です。

Diff内容との照合 ⚠ WARNING

コードブロックとDiff内容の一致

記事中の lib/kamal/commands/app/logging.rb と test/cli/app_test.rb の diff は PR の内容と完全に一致しています。ただし、test/commands/app_test.rb の diff が記載されておらず、言及のみとなっています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

使用されている用語(shell ラッパー、container_id_command など)は PR と合致しており、誤用は見られません。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

問題の原因と修正内容の説明が PR の Diff と一致しており、技術的に正確です。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

全ての主張は Issue #1841、PR #1851、及び Diff に裏付けられています。外部的な推測や捏造はありません。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR 番号 #1851、Issue 番号 #1841、ファイル名・行番号等の数値は正確です。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事タイトルは PR のタイトル「Fix --container-id to produce log output」の趣旨を日本語で適切に表現しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

記事内に PR で言及されていないバージョン情報やリリース日程等の外部知識は含まれていません。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

時間表現の記述はなく、PR の記述と食い違う表現もありません。