Linux / Editorial solution guide
A shell script reports Permission denied
Separate execution bits, directory traversal, mount policy, interpreter availability, and mandatory controls before changing a script’s access.
Read-only knowledge base · No public comments
Recognize the symptoms
A fictional ./report.sh cannot be launched directly and the shell prints Permission denied. Another invocation such as bash report.sh may appear to work. This difference is useful evidence, but it is not permission to bypass a deliberate execution policy. Work only with a newly created lab script.
Understand the likely causes
- Direct execution requires suitable execute permission, searchable parent directories, an accessible interpreter, and a filesystem and security policy that permit the operation. Reading a script with bash is a different operation: Bash opens its content as input. Missing interpreter paths and Windows-style line endings can cause related execution failures with different exact diagnostics.
1. Identify the exact operation and identity
Record the complete command, exact error, current directory, and acting identity. A successful read does not prove direct execution is permitted. Confirm the file is the intended synthetic script rather than a similarly named file found through PATH. Inspect the first line and identify its interpreter before making changes. Do not paste a real script or its environment into a public diagnostic transcript if it contains credentials.
id
pwd
ls -l -- ./report.sh
head -n 1 -- ./report.sh
These contextual read-only commands assume the lab script exists. They do not change ownership or mode.
2. Inspect the whole path and the intended mode
Check search permission on every parent and read the file mode as the acting account. If the private lab file belongs to you and its intended use is direct execution, adding only owner execute with chmod u+x is a narrow contextual fix. It does not repair an inaccessible parent, a broken interpreter, or a noexec mount. Avoid recursive chmod and never use 777 to suppress an unexplained denial.
lab=$(mktemp -d)
printf '%s\n' '#!/bin/sh' 'printf "lab-ok\n"' > "$lab/report.sh"
chmod u+x "$lab/report.sh"
"$lab/report.sh"
This non-runnable illustration assumes /bin/sh exists and the temporary filesystem permits execution. It changes only its new lab file, not a host script.
3. Inspect mount and security context
Use findmnt --target ./report.sh to locate the actual mount and inspect options. If noexec is deliberate, move the authorized lab to an appropriate execution location rather than bypassing or remounting host policy. If mode and path checks pass, inspect the installed mandatory-control audit evidence using the distribution’s supported tools. Validate the interpreter path and line endings separately; changing access bits cannot create a missing interpreter.
4. Change only the proven cause
Write down which check failed and why the required policy permits correcting it. Apply the smallest authorized fix in the disposable copy, keeping the original mode and content available for comparison. If the denial reflects an intentional organizational boundary, use the documented deployment process instead of weakening that boundary. Preserve the error evidence so a successful retest can be connected to the actual change.
Verify the fix
Repeat the original invocation as the same intended account from the same directory. Confirm the synthetic script prints the expected marker and returns zero, then inspect its final mode. Verify that unrelated users did not gain access and that no mount or mandatory policy was disabled. A different invocation succeeding is not equivalent to the original test succeeding.
Keep it from recurring
- Declare the interpreter, normalize source line endings, store executable mode intentionally in version control, and test the deployment path as the real service identity. Document whether the target mount permits execution. Keep access diagnosis separate from application debugging so broad permission changes do not become a routine workaround.