Bash で「Permission denied」が出てシェルスクリプトを実行できない
./script.sh が Permission denied になるのは、ファイルに実行ビットが立っていないか、置き場所が noexec でマウントされているかのどちらかである。chmod +x で実行ビットを付けるか、bash script.sh とインタプリタを明示して回避する。
公開:
要約
bash: ./script.sh: Permission denied は、スクリプトを実行しようとしたが実行権が無いときに出る。
文法エラーでもインタプリタの不在でもないので、まず ls -l で権限を見るのが最短である。
$ ./deploy.sh
bash: ./deploy.sh: Permission denied
$ ls -l deploy.sh
-rw-r--r-- 1 user user 512 Aug 10 09:00 deploy.sh-rw-r--r-- に x が無い。
この状態でスクリプト名を直接叩くと、カーネルの execve が EACCES を返し、Bash がそれを Permission denied として表示する。
終了ステータスは 126 になる。
よくある原因
- 実行ビットが立っていない: 一番多い。
git cloneした直後、unzipで展開した直後、Windows 側のエディタで作った直後などに起きる。 #!行のインタプリタ側に実行権が無い: スクリプトにはxがあるのに落ちる場合はこちらを疑う。- 置き場所が noexec:
/tmpをnoexecでマウントしている環境や、外部メディア・一部のコンテナでは、実行ビットがあっても実行できない。 - 親ディレクトリに検索権が無い: ディレクトリの
xはそこを通り抜ける権限を意味する。
これが無いとファイルへ到達できない。 - 所有者が自分ではない:
sudoを付けて展開・コピーした結果、root 所有の-rwx------になっていると、自分では実行できない。
なお ./dir のようにディレクトリを実行しようとした場合は Is a directory になり、このエラーにはならない。
メッセージが Permission denied であるうちは、上の 5 つのいずれかである。
解決策
1. 実行ビットを付ける
ls -l deploy.sh # 所有者が自分か、x があるかを見る
chown "$USER" deploy.sh # 所有者が違うときだけ
chmod +x deploy.sh
./deploy.sh+x は所有者・グループ・その他のすべてに実行権を足す(chmod の仕様(新しいタブで開く))。
自分だけに限定したいなら chmod u+x deploy.sh を使う。
2. 権限を変えずに実行する
bash deploy.sh
sh deploy.sh # POSIX sh として動かしたい場合インタプリタを明示すると、実行されるのは bash であってスクリプトファイルではないため、実行ビットが無くても動く。
読み取り権さえあればよい。
noexec なディレクトリでも通る。
3. noexec を確認する
mount | grep -E ' /tmp | on /mnt'出力に noexec があれば、そこに置いたスクリプトは実行ビットがあっても実行できない。
ホームディレクトリなど別の場所へ移す。
4. 実行ビットを Git に記録する
git update-index --chmod=+x deploy.sh
git commit -m "make deploy.sh executable"ローカルで chmod しても、実行ビットを commit していなければ他の開発者や CI では再び Permission denied になる。
Bash スクリプトをリポジトリに置くときはここまでやっておく。