🔐 Permissions & Users

Permissions & Users: Linux file permissions are a three-audience access control system: every file has exactly three answers to "who can do what" — for the owner, for anyone in t

Linux file permissions are a three-audience access control system: every file has exactly three answers to "who can do what" — for the owner, for anyone in the same group, and for everyone else — and each answer is three bits: read (r), write (w), execute (x). The mechanism mirrors Java's access modifiers almost exactly: `private` (owner only, `chmod 700`), package-private (group can access, `chmod 750`), `public` (everyone can read, `chmod 644`) — except Linux applies this at the OS level to actual files, not just class members. But here is the question every QA engineer hits on their first CI failure: if I can read the script on my laptop, why does the pipeline say "Permission denied"? Because reading and executing are two completely separate bits — a file can be readable but not executable, and a test runner that tries to call `./run-tests.sh` needs the `x` bit set, not just `r`. In practice, forgetting to commit the execute bit (`git update-index --chmod=+x`) is one of the most common causes of CI-only failures in QA automation: the script looks fine in the editor, the test looks fine locally, and then every pipeline run fails immediately on line one with an opaque "Permission denied" that takes thirty minutes to trace back to a missing `chmod +x`.

Reading "ls -l" Output

A line like `-rwxr-xr-- 1 qa qa 4096 Jun 19 10:00 deploy.sh` breaks down as: file type (- = regular file, d = directory), then three groups of three letters for owner / group / other permissions (rwx), a link count, owner name, group name, size, date, and filename.

chmod — Numeric Permission Values

linux-permissions-lab

Permission Denied Workshop

See exactly why a CI script fails without execute permission.

`chown newowner:newgroup file` changes who owns a file. `sudo` (superuser do) runs a single command with root (administrator) privileges. Never get into the habit of prefixing every command with `sudo` — only use it for commands that genuinely need elevated access, like installing system packages or managing services.

Changing permissions and ownership

🎬 The x Bit: The Invisible Gatekeeper

`ls -l` reads an ID card: `-rw-r--r--` = three audiences (👤 owner / 👥 group / 🌍 others), each with three bits (r read, w write, x execute).

The critical distinction: r and x are COMPLETELY SEPARATE bits. Being able to read — even edit — a file does not mean you can EXECUTE it; a script that looks perfect in the editor can still be unrunnable.

The CI runner calls `./run-tests.sh`. At the gate, the kernel checks the x bit: MISSING. Result: "Permission denied" at line one — rejected at the door, without the content ever being read.

So why did it work locally? Because you were calling `bash run-tests.sh` — there, bash is what RUNS and the file is only READ (r suffices). `./run-tests.sh` executes the file ITSELF, which demands x.