Fix 'Permission denied' on Linux when running shell scripts

Linux & Unix Beginner 👁 1 views 📅 May 29, 2026

Running a shell script with 'Permission denied' usually means the execute bit is missing. Here's how to check and fix it fast.

Quick answer

Run chmod +x script.sh then run ./script.sh. That's it 90% of the time.

What's actually happening here

When you get bash: ./script.sh: Permission denied, the shell itself can read the file but the OS won't let it execute. Linux file permissions have three sets — owner, group, and others — each with read (r), write (w), and execute (x) bits. Execute means the kernel allows the file to be loaded as a process. A script file you just downloaded or created won't have the execute bit set by default. The fix is to add it.

This error hits most often when you curl or wget a script from GitHub, or when you copy a script from a USB drive that was formatted with different permissions. It can also show up if you're on a shared system where your home directory has the noexec mount option — but that's rarer. Let's cover the common fix first, then diagnostics.

Fix steps

  1. Check current permissions. Run ls -l script.sh. You'll see something like -rw-r--r--. The first - means a regular file. The next three characters are owner permissions: rw- means read and write but no execute. Group and others have r-- (read only). That's your problem.
  2. Add execute permission for the owner. chmod u+x script.sh. The u means owner/user, +x adds execute. Now ls -l shows -rwxr--r--.
  3. Or add execute for everyone. chmod +x script.sh (no u) adds execute for owner, group, and others. That's fine for personal scripts but on shared systems you might want to keep it tighter.
  4. Run the script. ./script.sh. If you still get permission denied, the file itself might be the wrong type, or the filesystem has restrictions.

Alternative fixes if the main one fails

Filesystem mounted with noexec

Check with mount | grep $(df . --output=target | tail -1). If you see noexec in the options, the filesystem won't allow any execute, even with the right permission. Common places: /tmp, /var, or a separate /home partition mounted with noexec. Fix: copy the script to /home/youruser (if that's not noexec) or run it with the interpreter directly: bash script.sh. That bypasses the execute bit entirely — the shell reads the file and interprets it.

Wrong script header

If the shebang line (first line like #!/bin/bash) is wrong or the interpreter doesn't exist, you'll get No such file or directory or bad interpreter, not permission denied. But sometimes the error message is confusing. Use file script.sh to confirm it's a script, then check the shebang with head -1 script.sh.

SELinux or AppArmor interference

This is rare for a home machine. If you're on RHEL/CentOS/Fedora, SELinux might block execution. Check with ls -Z script.sh — if the context looks weird (like unconfined_u:object_r:user_home_t:s0), try restorecon -v script.sh. On Ubuntu/Debian with AppArmor, check sudo aa-status for profiles that might block script execution from certain directories.

File ownership

If you don't own the file and it's in your home, someone else put it there. chmod +x won't help if you're not the owner — you need sudo or you ask the owner to do it. Check ls -l for the owner column.

Prevention tip

Set a default umask of 022 in your ~/.bashrc or ~/.profile so newly created files are readable but not executable by default — then add execute only when you intend to run them. That way you never accidentally leave a script executable when it's not meant to be. Also, when downloading scripts from the internet, always inspect them with cat or less before running. A quick chmod +x on a malicious script is all an attacker needs.

Was this solution helpful?