自作のシェルスクリプトや Python スクリプトを実行しようとしたとき、次のようなエラーが出ることがあります。
-bash: ./script.sh: Permission denied
日本語環境では「許可がありません」と表示されます。このエラーの原因として真っ先に思い浮かぶのは「実行権限がない」ですが、スクリプトを置いたパーティションのマウントオプションや、スクリプト1行目のインタープリタ指定が原因になることもあります。それぞれ確認方法が異なるため、以下の順番に進めると素早く原因を絞り込めます。
1. 実行権限を確認する
Linux では、ファイルに「読み取り・書き込み・実行」の3種類の権限があります。./script.sh の形式でスクリプトを起動するには、実行権限(x)が必要です。まずファイルの権限状態を確認します。
ls -l script.sh
出力の先頭がたとえば -rw-r--r-- のように x を含まない場合、実行権限がありません。次のコマンドで付与できます。
chmod +x script.sh
付与後に ls -l を再実行すると、-rwxr-xr-x のように x が入った状態に変わります。ファイルオーナーにだけ実行権限を付けたい場合は chmod u+x script.sh と書きます。
なお、bash script.sh や python3 script.py のようにインタープリタを明示して起動する場合は実行権限が不要です。./script.sh の形式で直接実行するときにだけ必要になります。実行権限を付けても同じエラーが出る場合は、次の項目に進みます。
2. ファイルシステムのマウントオプション(noexec)を確認する
スクリプトを置いたパーティションが noexec オプションでマウントされている場合、chmod +x をしてもそのパーティション上のファイルは実行できません。noexec はファイルの権限とは別にカーネルレベルで実行を禁止するオプションです。
スクリプトを置いたパスのマウントオプションは次のコマンドで確認できます。
findmnt -o TARGET,OPTIONS /tmp
/tmp の部分は確認したいディレクトリのパスに変えてください。OPTIONS 列に noexec が含まれていれば、そのパーティションでは実行が禁止されています。
/tmp や /dev/shm などの一時領域は、セキュリティ対策として noexec を設定しているサーバーが多くあります。これらの場所にスクリプトを置いて実行しようとすると、権限を確認しても解決しないため原因が分かりにくくなりがちです。
対処方法は、スクリプトを noexec の付いていない場所(ホームディレクトリや /usr/local/bin など)に移動することです。マウントオプションを変更する権限がある場合は /etc/fstab の該当行から noexec を削除して再マウントする方法もありますが、セキュリティ上の意図で設定されていることが多いため、変更前にシステムの運用ルールを確認することをおすすめします。
3. 1行目のインタープリタ指定(shebang)を確認する
スクリプトの1行目に書く #!/bin/bash や #!/usr/bin/python3 などの記述を「shebang(シェバン)」と呼びます。./script.sh で実行するとき、OS はこの1行目を読んでどのインタープリタに処理を渡すか決めます。ここに書いたパスにインタープリタが存在しないか、パスが間違っていると「許可がありません」や「そのようなファイルやディレクトリはありません」が表示されます。
インタープリタが実際にどこにあるかは次のコマンドで確認できます。
which bash
which python3
出力されたパスと shebang の記述が一致しているかを照合してください。ディストリビューションによっては bash が /bin/bash ではなく /usr/bin/bash にある場合があります。また、python コマンドが存在せず python3 のみの環境もあります。
インストール先に依存しない書き方として #!/usr/bin/env bash を使う方法があります。env が PATH を検索してインタープリタを見つけてくれるため、環境による差異を吸収しやすくなります。複数のサーバーや環境で動かすスクリプトに向いている書き方です。
4. 改行コードが原因になるケース
Windows 上で作成・編集したスクリプトを Linux に転送すると、改行コードが CRLF(\r\n)のままになっていることがあります。CRLF のスクリプトでは shebang の末尾に \r が混入するため、OS が /bin/bash\r という存在しないパスを探してエラーになります。file script.sh を実行して CRLF line terminators と表示された場合は、dos2unix script.sh コマンドで改行コードを LF に変換できます。dos2unix がなければ sudo apt install dos2unix(Debian 系)や sudo yum install dos2unix(RHEL 系)でインストールできます。
よくあるつまずき
- sudo をつけたら動いた:
sudoを付けると root 権限で実行されるため、一部の権限エラーを回避できます。ただし根本原因の解決にはなっていないことが多く、スクリプトのオーナー・グループや権限設定を見直すほうが適切なケースが一般的です。 - 編集後に急に動かなくなった:エディタによっては保存時に実行権限がリセットされることがあります。スクリプトを編集した後は
ls -lで権限を確認してください。 - パスにスペースが含まれている:
./my script.shのようにパスにスペースがあると、シェルがmyとscript.shを別の引数として解釈します。パスをダブルクォートで囲む("./my script.sh")か、ファイル名のスペースをアンダースコアなどに変えることで対処できます。 - NFS などのネットワークマウントから実行している:NFS マウントにも
noexecオプションが設定されている場合があります。findmntでマウントオプションを確認してください。
「コマンドは打てる。次は”現場で通用する型”を最短で身につけたい」——そんなあなたへ。
ネットの断片的なTipsをコピペするだけでは、体系的な運用スキルはなかなか積み上がりません。リナックスマスター.JPの無料メルマガ「リナマガ」では、現場で実際に使うLinuxサーバー運用の考え方を、順を追って実務目線でお届けしています。いま登録された方には、安全なサーバー構築の「型」をまとめた『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼント中です。
>> 図解60P『Linux入門マニュアル』を無料で受け取る
(メルマガ登録は10秒・いつでも解除OK)
※ 「独学の時間がもったいない」「プロから現場の技術を最短で学びたい」という本気の方には、2日で実務レベルが身につく初心者向けハンズオンセミナーもご用意しています。
