👨‍⚖️

【備忘】Jenkinsビルド実行時に権限不足で実行失敗した件

に公開

背景

業務でJenkinsを使用してECSへアプリケーションをビルドしようとした際に、ECSのタスク初回実行時に下記ログが出力されて異常終了しました。

+ ./jenkins/slave_run_maven_build.sh
ファイルパス: 行 1:./jenkins/slave_run_maven_build.sh: 許可がありません

洗い出し

許可がないとのことでしたので、Jenkins実行シェルの権限を確認しました。

$ ls -l
total ○○
-rwxr-wr-w 1 user ○○ ○○ Month Day Time slave_run_maven_build.sh*

ログを見る限り、実行権限があるように見えます。


権限不足の正体

調査したところ、git ls-filesコマンドで実行権限の有無を確認しないといけませんでした。
ここで、lsコマンドとgit ls-filesコマンドの違いについてまとめました。

ls コマンド(Linux/Unixの基本コマンド)

  • 目的:ファイルシステム上のディレクトリやファイルを一覧表示する
  • 対象:現在のディレクトリや指定したパスに存在する実際のファイル・フォルダ
ls
ls -l /home/user/projects
  • 特徴:
    • Gitとは無関係
    • ファイルの存在や属性(サイズ、更新日時など)を確認するのに使う

git ls-files コマンド(Gitのサブコマンド)

  • 目的:Gitのインデックス(ステージングエリア)に登録されているファイルを一覧表示する
  • 対象:Gitリポジトリ内でGitが管理しているファイル
git ls-files
オプション 説明
オプションなし または –c インデックスされているファイルの一覧を表示する
-d working-directory(作業ディレクトリ)で削除したファイルが表示される
-m working-directory(作業ディレクトリ)で更新したファイルが表示される
-o インデックスに追加していない(追跡されていない)ファイルの一覧を表示する
-s リポジトリ格納されたblobのhash値とファイル名の一覧を表示する
  • 特徴:
    • ワーキングディレクトリに存在していても、Gitに追加(git add)されていないファイルは表示されない
    • .gitignore で無視されているファイルも表示されない
    • オプションでステージ情報や変更状態を確認できる

再確認

git ls-files コマンドで確認できることがわかりましたので、改めて確認しようと思います。

git ls-files -s
100644 hfahfeoegkaga 0 slave_run_maven_build.sh

コマンドの出力結果については、下記の通りです。
※出力結果左から

フィールド 説明
mode ファイルのパーミッション(例:100644 は通常のファイル、100755 は実行可能ファイル、120000 はシンボリックリンク)
object GitオブジェクトのSHA-1(またはSHA-256)ハッシュ。ファイルの内容を一意に識別するID
stage ステージ番号(通常は 0。マージ中の競合があると 1, 2, 3 などが表示される)
file ファイル名(パス)

git ls-files コマンドで確認しましたところ、
実行権限が無い
ことがわかりました。

権限付与対応

git update-index --add --chmod=+x slave_run_maven_build.sh

git update-indexコマンドの各種オプションは以下の通りです。
今回の事例でいうと、
Jenkinsの実行シェルに対して実行権限を追加する
処理を行いました。

オプション 説明
--add インデックスに存在しないファイルを追加
--remove インデックスにあるが、作業ツリーに存在しないファイルを削除
--force-remove 作業ツリーに存在していてもインデックスから強制的に削除
--refresh 作業ツリーとインデックスの差分をチェックして更新
--really-refresh assume-unchanged フラグを無視して強制的に更新
--ignore-missing --refresh 実行時に存在しないファイルを無視
--unmerged マージ中の未解決ファイルがあってもエラーにせず続行
--cacheinfo <mode>,<object>,<path> 指定した情報を直接インデックスに挿入
--index-info 標準入力からインデックス情報を読み込む
--chmod=+ 実行権限を持たせる
--[no-]assume-unchanged Gitに「このファイルは変更されない」と仮定させる
--[no-]skip-worktree Gitに「このファイルは作業ツリーで変更されない」と仮定させる
--info-only オブジェクトを作成せず、インデックスにIDだけ挿入
--unresolve 誤ってクリアされたマージ状態を復元
--verbose 詳細な出力を表示
--index-version <n> インデックスのバージョンを設定
--show-index-version 現在のインデックスバージョンを表示

参考:
https://runebook.dev/ja/docs/git/git-update-index

権限追加後の確認

git ls-files -s
100755 hfahfeoegkaga 0 slave_run_maven_build.sh

無事にJenkinsの実行シェルに実行権限が付与されました!


備考

Jenkinsと他CI/CDの違い

項目 Jenkins CircleCI GitHub Actions
実行形式 シェルスクリプトを直接実行 run ステップでコマンド実行 run ステップでコマンド実行
実行権限の扱い Gitの実行権限が影響する 明示的に chmod +x が必要 明示的に chmod +x が必要
実行環境 Jenkinsエージェント Docker executor など GitHubホストランナー or 自前

Jenkins の「実行シェル」

  • Jenkins では、「ビルドステップ」や「シェルスクリプト」 として .sh ファイルを直接実行することが多い
  • そのため、実行権限(chmod +x) が必要になるケースが多く、今回のような「Git上の実行権限」が問題になることがある
  • 実行環境は基本的に Jenkinsエージェント(slave)上のOS環境

CircleCI の場合

  • CircleCI では .circleci/config.yml に定義されたジョブ内で、run ステップを使ってコマンドを実行する
  • ここでも .sh ファイルを実行することは可能だが、実行権限が必要な場合は chmod +x を明示的に書くことが多い
  • ただし、CircleCI の場合は Docker イメージや executor の中で動作するため、Gitのインデックス上の実行権限が直接影響するケースは少ない
- run:
    name: 実行スクリプト
    command: |
      chmod +x ./scripts/deploy.sh
      ./scripts/deploy.sh

GitHub Actions の場合

  • GitHub Actions も .github/workflows/*.yml に定義されたジョブ内で run ステップを使用する
  • .sh ファイルを実行する場合、実行権限が必要な場合は chmod +x を明示的に記述する
  • GitHub Actions では、Gitのインデックス上の実行権限は無視されることが多く、ワークフロー内で明示的に権限を付与するのが一般的
- name: 実行スクリプト
  run: |
    chmod +x ./scripts/build.sh
    ./scripts/build.sh

補足:.gitattributes.gitignore の影響について

今回の事象には直接関係しませんが、Gitの挙動に影響する設定ファイルとして .gitattributes.gitignore の存在も知っておくと便利です。

  • .gitignore
    Gitが追跡しないファイルを指定するための設定ファイル
    例えば、ビルド成果物や一時ファイルなどを除外する際に使用
    .sh ファイルが .gitignore に含まれていると、git ls-files では表示されない

  • .gitattributes
    Gitがファイルを扱う際の属性(改行コード、マージ戦略、フィルタなど)を制御する設定ファイル
    例えば、WindowsとUnix間で改行コードの違いを吸収するために text=auto を指定することがある
    → 実行権限には直接影響しないが、CI環境でのファイルの整合性に関係することがある

なぜ Git の実行権限が Jenkins に影響するのか?
⇒JenkinsがGitからチェックアウトしたファイルをそのまま使うため、Gitのインデックスにある実行権限が反映される


最後に

今回はJenkinsの実行シェルについての実行権限の有無確認、権限付与についてまとめてみました。
この解決法が何かしらのお役に立てられたら幸いです。

Discussion