インストールスクリプトで `sudo` 実行時のコマンド解決エラーを修正

basecamp/once

インストールスクリプトが sudo でバックグラウンドサービスをインストールする際に発生していた command not found エラーを、絶対パスを使った ONCE_BIN 変数の導入により修正しました。

背景

sudo はセキュリティ上の理由から、実行時に /etc/sudoerssecure_path で定義された制限付きの PATH を使用します。そのため、ユーザーの PATH に含まれているコマンドでも、sudo <command> の形式で呼び出すと command not found になるケースがあります。

#13 では、Oracle Linux 9.6 環境で curl https://get.once.com | sh を実行した際に、once 本体のインストール自体は成功しているにもかかわらず、続く sudo once background install の段階で sudo: once: command not found が発生することが報告されました。インストール完了後に手動で once を実行すると動作するという事実から、原因が sudo の PATH 制限にあることが明確でした。

この問題は /usr/local/bin のような非標準のインストールディレクトリが secure_path に含まれていない環境で特に顕在化します。

技術的な変更

ONCE_BIN 変数を導入し、once バイナリの絶対パスを保持することで、sudo 経由の呼び出しを含む全ての実行箇所をPATH解決に依存しない形に統一しました。

install_once() 関数では、once が既にインストール済みの場合は command -v once の出力、新規インストールの場合は ${INSTALL_DIR}/onceONCE_BIN に格納するよう変更されました。

変更前:

if command -v once >/dev/null 2>&1; then
  echo "once is already installed at $(command -v once)"
  return
fi

# ...

echo "Installed once to ${INSTALL_DIR}/once"

echo "Installing background service..."
if is_root; then
  once background install
else
  sudo once background install
fi

変更後:

if command -v once >/dev/null 2>&1; then
  ONCE_BIN=$(command -v once)
  echo "once is already installed at ${ONCE_BIN}"
  return
fi

# ...

ONCE_BIN="${INSTALL_DIR}/once"
echo "Installed once to ${ONCE_BIN}"

echo "Installing background service..."
if is_root; then
  "${ONCE_BIN}" background install
else
  sudo "${ONCE_BIN}" background install
fi

ONCE_BIN への代入は2箇所に分かれています。既存インストールのパスは command -v once で取得するため、/usr/local/bin 以外の場所にインストールされていた場合でも正しく追跡できます。この変更は run_once() 関数内の呼び出しにも波及し、exec onceexec sudo oncesg docker -c "once ..." のすべてが ${ONCE_BIN} を使った絶対パス指定に統一されています。

設計判断

ONCE_BIN をスクリプト全体で共有するグローバル変数として宣言する方式が採用されました。

install_once() で設定した値を run_once() でも参照する必要があるため、変数のスコープはスクリプトトップレベルに置かれています。空文字列で初期化しておくことで、変数が未設定のまま参照される状態を防いでいます。また command -v once を使った既存インストールのパス取得は、非標準ロケーションへのインストールを考慮した堅牢な判定方法であり、which コマンドへの依存を避ける慣用的なシェルスクリプトの書き方に沿っています。

sudo "${ONCE_BIN}" のようにダブルクォートで変数を囲んでいる点も、スペースを含むパスへの対応として適切です。

まとめ

ONCE_BIN という単一変数の導入により、インストール済みか否か・標準パスか否かを問わず、スクリプト全体でバイナリの絶対パスが一貫して使われるようになりました。sudo のPATH制限という環境依存の問題を、シェルスクリプトの慣用的なパターンで根本から解消した修正です。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
f5539fbd

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

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

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

リード文(総論)→ 背景・技術詳細・設計判断(各論)→ まとめ(結論)という「総論→各論→結論」の構成が記事全体と各セクションで明確に適用されており、非常に分かりやすい。

カスタムMarkdown構文 ✓ PASS

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

ファイル名付きシンタックスハイライト(```bash:installer/templates/install.sh)およびGitHubのIssueへのリンク記法([#13](URL))が正しく使用されている。

対象読者への適合性 ✓ PASS

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

`sudo`の`secure_path`やシェルスクリプトの慣用句など、専門知識を持つエンジニアを対象とした適切な技術レベルと表現で記述されている。

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

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

各セクションが総論→各論→結論で構成され、各段落がトピックセンテンスで始まるなど、パラグラフ・ライティングの原則が徹底されており、可読性が高い。

Diff内容との照合 ✓ PASS

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

記事内の変更前後のコードブロックは、提供されたDiffの内容と完全に一致しており、変更点を正確に反映している。「run_once()」への波及についても言及されており、Diffを深く理解していることがわかる。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`secure_path`、`PATH解決`、`command -v`などの技術用語が、文脈に沿って正確に使用されている。

説明の技術的正確性 ✓ PASS

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

`sudo`実行時のPATH制限という問題の原因と、絶対パス指定による解決策という因果関係が、技術的に正確かつ論理的に説明されている。

事実の突合 ✓ PASS

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

記事内のすべての主張(`sudo`のPATHリセット、`ONCE_BIN`の導入など)は、PRのDescriptionやDiffのコード内容によって完全に裏付けられており、ハルシネーションは見られない。「設計判断」はコードから読み取れる妥当な解説であり、創作ではない。

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

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

PR番号「#14」、Issue番号「#13」、変数名「ONCE_BIN」など、記事に含まれる数値や固有名詞はすべて正確である。

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

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

記事のタイトル「インストールスクリプトで `sudo` 実行時のコマンド解決エラーを修正」は、PRの主題を読者にとって分かりやすく要約しており、内容と完全に一致している。

外部知識の正確性 ✓ PASS

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

記事に含まれる知識はすべてPR情報か、そこから直接導かれる技術的な解説に留まっており、PRに記載のない外部知識の持ち込みはない。

時間表現の正確性 ✓ PASS

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

記事内での時間表現は条件分岐(「既にインストール済みの場合」など)の説明に限定されており、PR情報との間で時間的な歪曲は見られない。