<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: The Linux Camp</title>
    <description>The latest articles on DEV Community by The Linux Camp (@thelinuxcamp).</description>
    <link>https://dev.to/thelinuxcamp</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4057391%2F0ff37f29-79c9-4ded-9225-1fbeb3696077.png</url>
      <title>DEV Community: The Linux Camp</title>
      <link>https://dev.to/thelinuxcamp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thelinuxcamp"/>
    <language>en</language>
    <item>
      <title>Linux Permissions, Explained by Breaking Them on Purpose" published: true</title>
      <dc:creator>The Linux Camp</dc:creator>
      <pubDate>Sat, 01 Aug 2026 03:28:45 +0000</pubDate>
      <link>https://dev.to/thelinuxcamp/linux-permissions-explained-by-breaking-them-on-purposepublished-true-12l0</link>
      <guid>https://dev.to/thelinuxcamp/linux-permissions-explained-by-breaking-them-on-purposepublished-true-12l0</guid>
      <description>&lt;p&gt;Most permission tutorials start with the table. Nine bits, three triplets, r is 4, w is 2, x is 1. You read it, you nod, and a week later you are pasting &lt;code&gt;chmod 777&lt;/code&gt; from a forum answer like everyone else.&lt;/p&gt;

&lt;p&gt;This one runs backwards. We break things on purpose, read the exact error each breakage produces, and work out what the system was checking. The table arrives at the end, where it stops being trivia and becomes the name for something you have already felt.&lt;/p&gt;

&lt;p&gt;You need any Linux machine: a VM, a cheap cloud box, a Raspberry Pi, WSL on Windows. Everything happens inside one throwaway folder, and the worst outcome available to you is deleting that folder. Twenty minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three questions
&lt;/h2&gt;

&lt;p&gt;Hold one model in your head the whole way. Every time you touch a file, the kernel, the core of Linux that referees every file access, asks three questions in this order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Are you the owner of this file?&lt;/li&gt;
&lt;li&gt;If not, are you a member of the file's group?&lt;/li&gt;
&lt;li&gt;If neither, you are everyone else.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It takes the first category that matches you, reads that category's three permissions (read, write, execute), and stops. It never falls through to the next category to see whether some other category would have been kinder. That "and stops" is where all the strangeness lives, and Break 1 makes it hurt.&lt;/p&gt;

&lt;h2&gt;
  
  
  The sandbox
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;zayden@lab:~$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;playground
&lt;span class="gp"&gt;zayden@lab:~$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;playground
&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything below stays in there. When you are finished, the whole crime scene comes off in two commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~              &lt;span class="c"&gt;# step out of the playground first&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; playground  &lt;span class="c"&gt;# delete the directory and everything inside it&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use a normal user account that can run sudo, not a root login. Root skips almost every permission check, which would quietly spoil each experiment before it starts. Why root gets that treatment is Break 4's job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Break 1: Lock yourself out of your own file
&lt;/h2&gt;

&lt;p&gt;Make a file and look at it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"secret plans"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; notes.txt
&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; notes.txt
&lt;span class="go"&gt;-rw-r--r-- 1 zayden zayden 13 Jul 30 10:02 notes.txt
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That string of dashes and letters at the front is the permission readout. Ignore it for a few more minutes. Now remove every permission from everyone, including yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;000 notes.txt
&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; notes.txt
&lt;span class="go"&gt;---------- 1 zayden zayden 13 Jul 30 10:02 notes.txt
&lt;/span&gt;&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;notes.txt
&lt;span class="go"&gt;cat: notes.txt: Permission denied
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You own this file. Your name is on it twice. The kernel refused you anyway, and the reason is that "and stops" rule. Question one: are you the owner? Yes. So it read the owner's three permissions, found no read there, and stopped. Whether the group or everyone else could read the file was never considered. First match, then verdict, no appeal.&lt;/p&gt;

&lt;p&gt;So are you locked out forever?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;644 notes.txt
&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;notes.txt
&lt;span class="go"&gt;secret plans
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;chmod&lt;/code&gt; worked while &lt;code&gt;cat&lt;/code&gt; did not, because changing permissions is not governed by the permission bits at all. It is a right of ownership. The owner can always change a file's mode, even when the current mode grants the owner nothing. You can lock yourself out of a file's contents, but you cannot lock yourself out of the lock.&lt;/p&gt;

&lt;h2&gt;
  
  
  Break 2: The script that refuses to run
&lt;/h2&gt;

&lt;p&gt;Write a two-line script and try to run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'#!/bin/bash\necho "hello from the script"\n'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; hello.sh
&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./hello.sh
&lt;span class="go"&gt;bash: ./hello.sh: Permission denied
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same error text as Break 1, completely different check underneath. &lt;code&gt;./hello.sh&lt;/code&gt; asks the kernel to execute this file as a program, and execute is its own separate permission. Reading was never the problem, which you can prove in one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bash hello.sh
&lt;span class="go"&gt;hello from the script
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;bash hello.sh&lt;/code&gt; runs bash, which is already executable over in /usr/bin, and bash merely reads your file the way &lt;code&gt;cat&lt;/code&gt; would. Read is granted, so it works. Running the file directly is the thing that needs the x bit on the file itself. One chmod flips it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x hello.sh
&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; hello.sh
&lt;span class="go"&gt;-rwxr-xr-x 1 zayden zayden 41 Jul 30 10:05 hello.sh
&lt;/span&gt;&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./hello.sh
&lt;span class="go"&gt;hello from the script
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;+x&lt;/code&gt; with no letter in front of it means "add execute everywhere the umask allows", and a standard umask of 022 blocks only write bits, so all three x characters appeared at once. That asymmetry between &lt;code&gt;./hello.sh&lt;/code&gt; and &lt;code&gt;bash hello.sh&lt;/code&gt; is worth remembering. When a script suddenly stops running after you copy it between machines or pull it out of a zip archive, the file is usually fine and the x bit is what went missing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Break 3: Seal a directory shut
&lt;/h2&gt;

&lt;p&gt;This is the one that bends brains. Directories carry the same nine bits, but x means something different on them: not "run this", but "pass through this". Watch what happens when it goes missing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;vault
&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"gold"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; vault/treasure.txt
&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;a-x vault
&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-ld&lt;/span&gt; vault
&lt;span class="go"&gt;drw-r--r-- 2 zayden zayden 4096 Jul 30 10:07 vault
&lt;/span&gt;&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;vault
&lt;span class="go"&gt;bash: cd: vault: Permission denied
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;cd&lt;/code&gt; is pure pass-through, so it dies instantly. Now the strange part:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;vault
&lt;span class="go"&gt;ls: cannot access 'vault/treasure.txt': Permission denied
treasure.txt
&lt;/span&gt;&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; vault
&lt;span class="go"&gt;ls: cannot access 'vault/treasure.txt': Permission denied
total 0
-????????? ? ? ? ?            ? treasure.txt
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An error and a result at the same time, then a row of question marks. Here is the unlock: a directory is a file whose contents are a list of names. The r bit lets you read that list, which is why &lt;code&gt;treasure.txt&lt;/code&gt; still prints. But the file's size, owner, permissions and timestamps live with the file itself, on the far side of the door you just sealed, and reaching them requires x. &lt;code&gt;ls&lt;/code&gt; could read the guest list and could not walk in, so every fact about the file came back as a question mark.&lt;/p&gt;

&lt;p&gt;If you are wondering why plain &lt;code&gt;ls&lt;/code&gt; needed those details at all, it did not. Most systems alias &lt;code&gt;ls&lt;/code&gt; to &lt;code&gt;ls --color=auto&lt;/code&gt;, and picking a color per file requires the same blocked lookup. That is the alias talking, not &lt;code&gt;ls&lt;/code&gt; itself.&lt;/p&gt;

&lt;p&gt;Reading the file is fully off the table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;vault/treasure.txt
&lt;span class="go"&gt;cat: vault/treasure.txt: Permission denied
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is not only the last directory in the path, either. To reach &lt;code&gt;vault/treasure.txt&lt;/code&gt; the kernel needs x on every directory along the way, starting at &lt;code&gt;/&lt;/code&gt;. One sealed door anywhere above a file blocks everything below it, which is why a permission problem is so often three levels higher than the file you are shouting at.&lt;/p&gt;

&lt;p&gt;Now flip the experiment and give the directory x without r:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;711 vault  &lt;span class="c"&gt;# 7 = rwx for you, 1 = execute only for group and everyone else&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is a speakeasy instead of a sealed vault. As group or other, &lt;code&gt;cd vault&lt;/code&gt; works and &lt;code&gt;cat vault/treasure.txt&lt;/code&gt; works if you already know the name, but &lt;code&gt;ls vault&lt;/code&gt; fails outright. A menu with no door, or a door with no menu. The two bits really are that independent, and web servers lean on the door-with-no-menu form constantly.&lt;/p&gt;

&lt;p&gt;One more directory surprise: deleting a file is an edit to the directory, because you are erasing a name from its list. &lt;code&gt;rm&lt;/code&gt; therefore cares about w and x on the directory, not about the file's own bits. That is why &lt;code&gt;rm&lt;/code&gt; can delete a read-only file inside a writable directory (it asks first) and cannot delete anything inside a directory you cannot write.&lt;/p&gt;

&lt;p&gt;Repair the vault before moving on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;755 vault
&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;vault/treasure.txt
&lt;span class="go"&gt;gold
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Break 4: Try to give your file away
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;chown &lt;/span&gt;root notes.txt
&lt;span class="go"&gt;chown: changing ownership of 'notes.txt': Operation not permitted
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;New error text, and the difference matters more than any bit in this article. "Permission denied" means the kernel checked the bits and the bits said no. "Operation not permitted" means the bits were never consulted, because the operation itself is reserved. On Linux, giving a file away is root-only. If ordinary users could hand files to each other, you could dump junk onto someone else's disk quota, or plant a file that looks like somebody else wrote it. So there are no three questions here. There is one: are you root? You are not.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo chown &lt;/span&gt;root notes.txt
&lt;span class="go"&gt;[sudo] password for zayden:
&lt;/span&gt;&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; notes.txt
&lt;span class="go"&gt;-rw-r--r-- 1 root zayden 13 Jul 30 10:02 notes.txt
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same file, same folder, same you. Try to append a line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"one more line"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; notes.txt
&lt;span class="go"&gt;bash: notes.txt: Permission denied
&lt;/span&gt;&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;notes.txt
&lt;span class="go"&gt;secret plans
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the three questions yourself before reading on. Owner? No, that is root now. Group? Yes, the file's group is still &lt;code&gt;zayden&lt;/code&gt; and you are in it, so the kernel reads the group triplet: read yes, write no, and stops, exactly like Break 1. Reading works, appending does not. The error names &lt;code&gt;bash&lt;/code&gt; rather than &lt;code&gt;echo&lt;/code&gt; because your shell opens the file for the &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; redirect before echo ever runs, which is a useful tell: when the complaint comes from &lt;code&gt;bash&lt;/code&gt;, the redirect failed and the command never started.&lt;/p&gt;

&lt;p&gt;So what did sudo actually do? It ran chown as root, and root passes nearly every file permission check automatically. Sudo does not grant you permission. It removes the questions. That is why it fixes almost everything, and why reaching for it by reflex is a bad habit. You are not solving the puzzle, you are unplugging the referee. (Nearly every check: even root cannot execute a file that has no x bit anywhere. The kernel wants at least one signal that the thing was meant to be a program.)&lt;/p&gt;

&lt;p&gt;Take your file back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;zayden@lab:~/playground$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo chown &lt;/span&gt;zayden notes.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The notation you already felt
&lt;/h2&gt;

&lt;p&gt;Now the table, which at this point is a summary rather than a mystery.&lt;/p&gt;

&lt;h3&gt;
  
  
  The ten characters at the front of ls -l
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- rwx r-x r-x
^  ^   ^   ^
|  |   |   everyone else
|  |   group
|  owner
type: - file, d directory, l symlink
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ls&lt;/code&gt; prints those with no spaces, as &lt;code&gt;-rwxr-xr-x&lt;/code&gt;. They are spaced out here to show the grouping. Three triplets, one per question, each answering read, write and execute with a letter for yes and a dash for no. Every error you caused above was the kernel landing on one triplet and finding a dash where it needed a letter.&lt;/p&gt;

&lt;h3&gt;
  
  
  The three digits in chmod 755
&lt;/h3&gt;

&lt;p&gt;The numeric form compresses each triplet into a single digit: r is 4, w is 2, x is 1, add them up. So 7 is rwx, 6 is rw-, 5 is r-x, 4 is r--, and 0 is nothing at all.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Octal&lt;/th&gt;
&lt;th&gt;Triplets&lt;/th&gt;
&lt;th&gt;Where you felt it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;000&lt;/td&gt;
&lt;td&gt;--- --- ---&lt;/td&gt;
&lt;td&gt;Break 1, locked out of your own notes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;644&lt;/td&gt;
&lt;td&gt;rw- r-- r--&lt;/td&gt;
&lt;td&gt;notes.txt as created, hello.sh before +x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;755&lt;/td&gt;
&lt;td&gt;rwx r-x r-x&lt;/td&gt;
&lt;td&gt;hello.sh after +x, the repaired vault&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;711&lt;/td&gt;
&lt;td&gt;rwx --x --x&lt;/td&gt;
&lt;td&gt;the speakeasy vault, door with no menu&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;600&lt;/td&gt;
&lt;td&gt;rw- --- ---&lt;/td&gt;
&lt;td&gt;private files, and ssh refuses keys looser than this&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The chmods you have been pasting for years now decode themselves. &lt;code&gt;chmod 644&lt;/code&gt; is "owner reads and writes, everyone else reads". &lt;code&gt;chmod 755&lt;/code&gt; is the same plus execute for all, the standard for scripts and for directories people are meant to enter. &lt;code&gt;chmod 777&lt;/code&gt; hands all nine yeses to everyone, and usually marks the spot where somebody stopped debugging and started gambling.&lt;/p&gt;

&lt;h3&gt;
  
  
  The symbolic form
&lt;/h3&gt;

&lt;p&gt;The letters address the same three lanes: &lt;code&gt;u&lt;/code&gt; owner, &lt;code&gt;g&lt;/code&gt; group, &lt;code&gt;o&lt;/code&gt; everyone else, &lt;code&gt;a&lt;/code&gt; all three, combined with &lt;code&gt;+&lt;/code&gt; to add, &lt;code&gt;-&lt;/code&gt; to remove, and &lt;code&gt;=&lt;/code&gt; to set exactly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;u+x deploy.sh     &lt;span class="c"&gt;# add execute for the owner only&lt;/span&gt;
&lt;span class="nb"&gt;chmod &lt;/span&gt;go-w report.txt   &lt;span class="c"&gt;# take write away from group and everyone else&lt;/span&gt;
&lt;span class="nb"&gt;chmod &lt;/span&gt;a-x vault         &lt;span class="c"&gt;# remove execute from all three, which is what Break 3 did&lt;/span&gt;
&lt;span class="nb"&gt;chmod &lt;/span&gt;&lt;span class="nv"&gt;u&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;rw,go&lt;span class="o"&gt;=&lt;/span&gt; key.pem  &lt;span class="c"&gt;# set exactly: owner reads and writes, nobody else gets anything&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Symbolic form is the safer habit when you are adjusting one thing, because it changes only the bits you name. Octal replaces all nine at once, so a typo in a hurry rewrites permissions you never meant to touch.&lt;/p&gt;

&lt;h2&gt;
  
  
  The error decoder
&lt;/h2&gt;

&lt;p&gt;Four messages cover most permission trouble, and you have now caused every one of them on purpose.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;cat: notes.txt: Permission denied&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The bits denied a read. The same shape comes from &lt;code&gt;cp&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;less&lt;/code&gt; and anything else that opens a file. Check first: run &lt;code&gt;ls -l notes.txt&lt;/code&gt;, work out which single triplet applies to you, and look for r in it.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;bash: ./hello.sh: Permission denied&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;An execute was refused. Check first: &lt;code&gt;ls -l hello.sh&lt;/code&gt; and look for x in your triplet. If x is present and it still fails, check whether the filesystem is mounted &lt;code&gt;noexec&lt;/code&gt;, which is common on /tmp and on USB drives.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;bash: cd: vault: Permission denied&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Pass-through was refused. Check first: &lt;code&gt;ls -ld vault&lt;/code&gt;, where the &lt;code&gt;d&lt;/code&gt; makes &lt;code&gt;ls&lt;/code&gt; describe the directory itself instead of listing its contents. Remember that the check applies to every directory on the path, not only the last one.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;chown: changing ownership of 'notes.txt': Operation not permitted&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Not a bits problem. This is a root-only operation, so chmod will never fix it. Check first: whether the change genuinely needs sudo, and whether you are sure it does. Any time you see "Operation not permitted" where you expected "Permission denied", stop staring at the permission bits and go looking for the rule instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to practice safely
&lt;/h2&gt;

&lt;p&gt;Not on machines you care about. Permission experiments escalate: today you &lt;code&gt;chmod 000&lt;/code&gt; a note, next month you fat-finger a recursive chmod in the wrong terminal window. Do your breaking where mistakes are free.&lt;/p&gt;

&lt;p&gt;A local VM is the classic answer. VirtualBox with a Debian or Ubuntu image, take a snapshot before you start, roll back when things get strange. A cheap cloud box you can rebuild on demand works the same way. WSL handles everything in this article too, as long as you work inside your Linux home directory rather than under /mnt/c, where the permission bits behave oddly because they are being translated from Windows.&lt;/p&gt;

&lt;p&gt;Full disclosure, I built the third option: The Linux Camp (thelinuxcamp.com), real Linux VMs in your browser that boot in about a second, made for exactly this break-and-inspect style of learning. Wreck the machine, reset it, go again, and your progress is verified from the commands you actually type. Sign-up is required to launch a VM, the first track is free, and everything past it is $14.99 a month. Every experiment above runs identically on any Linux box you already have, so start wherever you are.&lt;/p&gt;

&lt;p&gt;However you practice, keep the habit. Next time something denies you, do not paste a fix from a forum. Ask which of the three questions matched you, and which single bit said no. The system is not being difficult. It is answering exactly the question you asked, and you now speak enough of its language to ask better ones.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>computerscience</category>
      <category>cybersecurity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Learn Linux in 2026 (Hands-On, Free, No Experience Needed)</title>
      <dc:creator>The Linux Camp</dc:creator>
      <pubDate>Sat, 01 Aug 2026 03:05:10 +0000</pubDate>
      <link>https://dev.to/thelinuxcamp/how-to-learn-linux-in-2026-hands-on-free-no-experience-needed-19hg</link>
      <guid>https://dev.to/thelinuxcamp/how-to-learn-linux-in-2026-hands-on-free-no-experience-needed-19hg</guid>
      <description>&lt;p&gt;Here is the whole method: get access to a real Linux machine, type commands on it for 30 to 60 minutes every day, and follow a plan that builds from navigating the filesystem up to running your own web server. Do that and you will be comfortable in four weeks and genuinely fluent in about eight.&lt;/p&gt;

&lt;p&gt;No experience required, no money required. The rest of this article is the specific plan: what to type each week, where to get a free machine you can safely break, what the three scariest errors mean, and how to tell you are actually improving.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why most people fail at Linux
&lt;/h2&gt;

&lt;p&gt;The pattern is nearly universal. Someone decides to learn Linux, finds a nine-hour video course, watches it at 1.5x speed, takes beautiful notes, and three weeks later cannot list the contents of a directory without checking those notes.&lt;/p&gt;

&lt;p&gt;Watching someone else type is not practice. It feels like learning because the explanation makes sense while you hear it. But command line skill is muscle memory wrapped around a mental model, and both are built one way: typing, failing, reading the error, trying again. An hour of reading about &lt;code&gt;ls&lt;/code&gt; teaches you less than typing &lt;code&gt;ls&lt;/code&gt; twenty times in twenty directories. Videos are fine as a preview. They are just not the workout.&lt;/p&gt;

&lt;p&gt;So flip the ratio: for every minute reading or watching, spend five with your hands on a keyboard. This article included. Read a section, then go type it.&lt;/p&gt;

&lt;p&gt;Two smaller failure modes show up almost as often.&lt;/p&gt;

&lt;h3&gt;
  
  
  Trying to memorize everything
&lt;/h3&gt;

&lt;p&gt;Linux has thousands of commands. Working engineers lean hard on a core of about 25 and look up the rest without shame. The plan below teaches that core and nothing else.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fear of breaking things
&lt;/h3&gt;

&lt;p&gt;On a practice machine, breaking things is the goal, not the risk. A system you broke and fixed teaches more than ten flawless tutorials. Every option in the practice section makes the worst case "start over," which costs a minute.&lt;/p&gt;

&lt;h2&gt;
  
  
  The four-week plan
&lt;/h2&gt;

&lt;p&gt;First, get a machine from the free options below (one minute to one afternoon, depending which you pick). Then follow three rules:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Daily beats big.&lt;/strong&gt; Thirty focused minutes every day builds more skill than four hours on Saturday. Consistency is the entire trick.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type everything yourself.&lt;/strong&gt; Even the commands that look trivial. Especially those.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learn the two magic keys today.&lt;/strong&gt; Press &lt;code&gt;Tab&lt;/code&gt; to autocomplete commands and file names. Press the up arrow to bring back previous commands. These two habits save hours every week.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each week has a small command set, daily reps, and a test. Move on only when you pass the test without notes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Week 1: Move around with pwd, ls, cd, cat
&lt;/h3&gt;

&lt;p&gt;First, one definition: the terminal is the text window where you type commands and Linux types back. That is the entire interface. It looks hostile, and it is not. It is just quiet.&lt;/p&gt;

&lt;p&gt;Your daily reps, in order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;            &lt;span class="c"&gt;# print working directory: "where am I?"&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt;             &lt;span class="c"&gt;# list what is here&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;          &lt;span class="c"&gt;# long view: permissions, owner, size, date&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;          &lt;span class="c"&gt;# also show hidden files (names starting with a dot)&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; /           &lt;span class="c"&gt;# go to the root of the filesystem&lt;/span&gt;
&lt;span class="nb"&gt;ls
cd&lt;/span&gt; /var/log    &lt;span class="c"&gt;# jump to a specific place&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ~           &lt;span class="c"&gt;# jump straight home&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ..          &lt;span class="c"&gt;# go up one level&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; -           &lt;span class="c"&gt;# bounce back to wherever you just were&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/hostname     &lt;span class="c"&gt;# print a file's contents to the screen&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/os-release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The mental model: Linux is one big tree of directories (folders) rooted at &lt;code&gt;/&lt;/code&gt;. A path like &lt;code&gt;/var/log&lt;/code&gt; is an address in that tree. Paths starting with &lt;code&gt;/&lt;/code&gt; are absolute and work from anywhere; paths without it are relative to where you stand.&lt;/p&gt;

&lt;h4&gt;
  
  
  Week 1 pass test
&lt;/h4&gt;

&lt;p&gt;Dropped into any directory, you can figure out where you are, get to &lt;code&gt;/var/log&lt;/code&gt;, print a file that lives there, and get home in one command. No notes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Week 2: Create, copy, protect with mkdir, cp, mv, rm, chmod, chown
&lt;/h3&gt;

&lt;p&gt;Week 1 was looking. Week 2 is changing things, and everything below is safe to get wrong.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;practice             &lt;span class="c"&gt;# make a directory&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;practice
&lt;span class="nb"&gt;touch &lt;/span&gt;empty.txt            &lt;span class="c"&gt;# create an empty file&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; notes.txt   &lt;span class="c"&gt;# create a file with text in it&lt;/span&gt;
&lt;span class="nb"&gt;cp &lt;/span&gt;notes.txt backup.txt    &lt;span class="c"&gt;# copy&lt;/span&gt;
&lt;span class="nb"&gt;mv &lt;/span&gt;backup.txt old.txt      &lt;span class="c"&gt;# move, which is also how you rename&lt;/span&gt;
&lt;span class="nb"&gt;rm &lt;/span&gt;old.txt                 &lt;span class="c"&gt;# remove. There is no trash can. Gone is gone.&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; web/css/img       &lt;span class="c"&gt;# -p builds the whole nested path at once&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; web web-copy         &lt;span class="c"&gt;# -r copies a directory and everything in it&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command line assumes you mean what you say. &lt;code&gt;rm&lt;/code&gt; does not ask twice, and &lt;code&gt;rm -r&lt;/code&gt; on the wrong directory is the classic disaster.&lt;/p&gt;

&lt;p&gt;Now permissions, the biggest source of beginner confusion. Run &lt;code&gt;ls -l&lt;/code&gt; and look at the start of a line, something like &lt;code&gt;-rw-r--r--&lt;/code&gt;. That is three sets of three: owner, group, everyone else. &lt;code&gt;r&lt;/code&gt; is read, &lt;code&gt;w&lt;/code&gt; is write, &lt;code&gt;x&lt;/code&gt; is execute (run as a program).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;600 notes.txt          &lt;span class="c"&gt;# only you can read and write it&lt;/span&gt;
&lt;span class="nb"&gt;chmod &lt;/span&gt;u+x hello.sh           &lt;span class="c"&gt;# let the owner run it as a program&lt;/span&gt;
&lt;span class="nb"&gt;sudo chown &lt;/span&gt;root notes.txt    &lt;span class="c"&gt;# hand the file to the root user&lt;/span&gt;
&lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nv"&gt;$USER&lt;/span&gt; notes.txt   &lt;span class="c"&gt;# take it back&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The numbers: read is 4, write is 2, execute is 1, summed per group. So 600 is "owner reads and writes, everyone else nothing," and 755 is "owner everything, everyone else read and run." Two more definitions: &lt;code&gt;root&lt;/code&gt; is the administrator account that can do anything, and &lt;code&gt;sudo&lt;/code&gt; runs one command with root's power.&lt;/p&gt;

&lt;h4&gt;
  
  
  Week 2 pass test
&lt;/h4&gt;

&lt;p&gt;You can build a small directory tree, write a two-line script and run it, and lock a file so only your user can read it. Here is the script, if you want it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'#!/bin/bash'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; hello.sh                        &lt;span class="c"&gt;# names the program that runs the file&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'echo Hello from my first script'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; hello.sh   &lt;span class="c"&gt;# &amp;gt;&amp;gt; appends instead of overwriting&lt;/span&gt;
&lt;span class="nb"&gt;chmod &lt;/span&gt;u+x hello.sh                                   &lt;span class="c"&gt;# make it runnable&lt;/span&gt;
./hello.sh                                           &lt;span class="c"&gt;# ./ means "in this directory"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Week 3: Processes and software with ps, kill, systemctl, apt
&lt;/h3&gt;

&lt;p&gt;Everything running on a Linux machine is a process, and every process has an ID number called a PID. This week: see them, stop them, and install new software.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ps aux                 &lt;span class="c"&gt;# every process on the machine right now&lt;/span&gt;
ps aux | &lt;span class="nb"&gt;grep &lt;/span&gt;bash     &lt;span class="c"&gt;# the | pipes one command's output into another&lt;/span&gt;
&lt;span class="nb"&gt;sleep &lt;/span&gt;300 &amp;amp;            &lt;span class="c"&gt;# start a five-minute do-nothing process in the background&lt;/span&gt;
ps aux | &lt;span class="nb"&gt;grep sleep&lt;/span&gt;    &lt;span class="c"&gt;# find it and note its PID&lt;/span&gt;
&lt;span class="nb"&gt;kill &lt;/span&gt;12345             &lt;span class="c"&gt;# replace with the real PID: politely ask it to exit&lt;/span&gt;
&lt;span class="nb"&gt;kill&lt;/span&gt; &lt;span class="nt"&gt;-9&lt;/span&gt; 12345          &lt;span class="c"&gt;# force it. Last resort only.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One opinion to adopt early: reaching for &lt;code&gt;kill -9&lt;/code&gt; first is a bad habit. Plain &lt;code&gt;kill&lt;/code&gt; lets a program clean up after itself, and &lt;code&gt;-9&lt;/code&gt; yanks the power cord. Use it only after polite failed.&lt;/p&gt;

&lt;p&gt;Installing software, on Ubuntu and Debian:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update          &lt;span class="c"&gt;# refresh the list of available software&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;htop    &lt;span class="c"&gt;# a friendlier process viewer. Go explore it.&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt remove htop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Services are long-running background processes (web servers, databases) managed by a supervisor called systemd. Try it on &lt;code&gt;cron&lt;/code&gt;, the job scheduler present on virtually every Linux machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl status cron               &lt;span class="c"&gt;# is it running? since when? any recent errors?&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart cron
systemctl list-units &lt;span class="nt"&gt;--type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;service &lt;span class="c"&gt;# every service systemd manages&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read &lt;code&gt;status&lt;/code&gt; output closely: the &lt;code&gt;Active:&lt;/code&gt; line gives the state, and the last lines are the service's own recent logs. The bottom is where answers live.&lt;/p&gt;

&lt;h4&gt;
  
  
  Week 3 pass test
&lt;/h4&gt;

&lt;p&gt;You can start a background process, hunt down its PID, and kill it, install and remove a package, and check whether a service is running, then restart it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Week 4: Networking, logs, and your first web server with ip, ss, journalctl
&lt;/h3&gt;

&lt;p&gt;Two definitions first: an interface is how your machine reaches the network, and a port is the numbered door a program listens on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip a                &lt;span class="c"&gt;# your machine's network interfaces and addresses&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ss &lt;span class="nt"&gt;-tulpn&lt;/span&gt;      &lt;span class="c"&gt;# every port something is listening on, and what&lt;/span&gt;
journalctl &lt;span class="nt"&gt;-u&lt;/span&gt; cron  &lt;span class="c"&gt;# the full log history of one service&lt;/span&gt;
journalctl &lt;span class="nt"&gt;-f&lt;/span&gt;       &lt;span class="c"&gt;# live tail of every log. Ctrl-C stops it.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the project that ties all four weeks together. Budget about an hour.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install a web server: &lt;code&gt;sudo apt install nginx&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Confirm it is running: &lt;code&gt;systemctl status nginx&lt;/code&gt; (week 3 skill)&lt;/li&gt;
&lt;li&gt;Fetch your site: &lt;code&gt;curl localhost&lt;/code&gt; (curl downloads a web page in the terminal). Real HTML comes back. You are running a web server.&lt;/li&gt;
&lt;li&gt;See it holding port 80: &lt;code&gt;sudo ss -tulpn | grep 80&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Make the page yours: &lt;code&gt;echo "&amp;lt;h1&amp;gt;I built this&amp;lt;/h1&amp;gt;" | sudo tee /var/www/html/index.html&lt;/code&gt; then &lt;code&gt;curl localhost&lt;/code&gt; again. The sudo is week 2: that directory belongs to root.&lt;/li&gt;
&lt;li&gt;Now break it on purpose. Open the config with &lt;code&gt;sudo nano /etc/nginx/sites-enabled/default&lt;/code&gt; and delete one semicolon. Run &lt;code&gt;sudo systemctl restart nginx&lt;/code&gt;. It fails.&lt;/li&gt;
&lt;li&gt;Fix it by reading, not guessing: &lt;code&gt;systemctl status nginx&lt;/code&gt; shows the failure, &lt;code&gt;sudo nginx -t&lt;/code&gt; names the exact file and line, &lt;code&gt;journalctl -u nginx -e&lt;/code&gt; shows the history. Repair, restart, and &lt;code&gt;curl&lt;/code&gt; works again.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Steps 6 and 7 are the whole point. Professional Linux work is mostly this exact loop: change something, watch it break, read the logs, fix it, confirm. You just ran a full shift of it somewhere nothing could go wrong.&lt;/p&gt;

&lt;h4&gt;
  
  
  Week 4 pass test
&lt;/h4&gt;

&lt;p&gt;You can serve a page you wrote, break the config on purpose, and bring the service back using only &lt;code&gt;systemctl status&lt;/code&gt;, &lt;code&gt;nginx -t&lt;/code&gt;, and &lt;code&gt;journalctl&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Weeks 5 through 8: from familiar to fluent
&lt;/h3&gt;

&lt;p&gt;If you want fluency instead of familiarity, repeat the whole plan on a fresh machine without notes, then extend it. Add a second user and lock your files away from them. Schedule a job with cron. SSH between two machines. Turn one-off commands into small shell scripts. Fluency is repetition with variation, nothing fancier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to practice for free
&lt;/h2&gt;

&lt;p&gt;You need a machine you can hurt without consequences. In 2026 there are more free options than ever, so pick by temperament. Ubuntu and Debian, which most of these run, are distributions: packaged versions of Linux. Every command in this plan is identical on both.&lt;/p&gt;

&lt;h3&gt;
  
  
  A virtual machine with VirtualBox
&lt;/h3&gt;

&lt;p&gt;Install VirtualBox (free), download an Ubuntu Server ISO (free), and create a virtual machine. You get a complete real system with snapshots: save its state before a risky experiment, roll back after. Cost: an afternoon and a few gigabytes of disk. On an Apple Silicon Mac, use UTM instead, same idea. If you want maximum realism, this is the pick, and the setup is itself a decent first lesson.&lt;/p&gt;

&lt;h3&gt;
  
  
  WSL2 on Windows
&lt;/h3&gt;

&lt;p&gt;Open PowerShell as administrator, run &lt;code&gt;wsl --install&lt;/code&gt;, reboot, and you have Ubuntu running inside Windows. The fastest route to a real shell, and weeks 1 through 3 run on it perfectly. Two caveats: it lives on your daily machine, so reckless experimentation feels riskier, and some service and networking behavior differs from a standalone server.&lt;/p&gt;

&lt;h3&gt;
  
  
  OverTheWire Bandit
&lt;/h3&gt;

&lt;p&gt;A free game played over SSH at &lt;a href="https://overthewire.org/wargames/bandit/" rel="noopener noreferrer"&gt;overthewire.org&lt;/a&gt;. Each level hides the password to the next, and the week 1 and 2 commands dig it out. Start with &lt;code&gt;ssh bandit0@bandit.labs.overthewire.org -p 2220&lt;/code&gt;, password &lt;code&gt;bandit0&lt;/code&gt;. Bandit makes reps addictive, but it is puzzles rather than a structured path, so run it alongside this plan, not instead of it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Linux Journey
&lt;/h3&gt;

&lt;p&gt;Free, well organized reading at &lt;a href="https://linuxjourney.com" rel="noopener noreferrer"&gt;linuxjourney.com&lt;/a&gt; that explains concepts in a friendly order. Reading rather than typing, so treat it as the companion text after a hands-on session, never as the session itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Linux Camp
&lt;/h3&gt;

&lt;p&gt;Full disclosure: I built this one (&lt;a href="https://thelinuxcamp.com" rel="noopener noreferrer"&gt;thelinuxcamp.com&lt;/a&gt;), so weigh my bias accordingly. It runs real Linux VMs in the browser that boot in about one second, with progress verified from the actual commands you type, so there is nothing to install and completion is not on the honor system. A free account gets you the first track, and everything past it is $14.99 a month. You do not need it for this plan, a VirtualBox VM plus discipline is enough, but if setup friction is what killed your previous attempts, it removes all of it.&lt;/p&gt;

&lt;h3&gt;
  
  
  An old laptop
&lt;/h3&gt;

&lt;p&gt;The sleeper option. Install Debian directly onto a machine you no longer care about and it becomes a pure toy with zero stakes, the best learning environment there is.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three errors every beginner hits
&lt;/h2&gt;

&lt;p&gt;Error messages are not the machine being hostile. They are the machine being precise. Read them literally and they usually tell you the fix.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Permission denied&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;You asked for something your user is not allowed to do. Check three things in order. First, &lt;code&gt;ls -l&lt;/code&gt; the file: are you the owner, and does your slot in the &lt;code&gt;rwx&lt;/code&gt; string include what you attempted? Second, a script you cannot run may be missing its execute bit, and &lt;code&gt;chmod u+x script.sh&lt;/code&gt; fixes that. Third, some actions genuinely need root, so &lt;code&gt;sudo&lt;/code&gt; is the answer, but ask why before typing it. Reflexive &lt;code&gt;sudo&lt;/code&gt; on everything is how beginners turn small mistakes into big ones.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;command not found&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The shell searched everywhere it knows and found no program by that name. Cause one, by a mile: a typo. Cause two: the program is not installed, which &lt;code&gt;sudo apt install&lt;/code&gt; fixes. Cause three catches everyone exactly once: you typed &lt;code&gt;script.sh&lt;/code&gt; instead of &lt;code&gt;./script.sh&lt;/code&gt;. The shell searches only its known program directories, never your current one, so you must point at your own script with &lt;code&gt;./&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;No such file or directory&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The path you typed does not exist from where you are standing. Run &lt;code&gt;pwd&lt;/code&gt; to confirm where that actually is. Check the spelling, and remember Linux is case sensitive: &lt;code&gt;Notes.txt&lt;/code&gt; and &lt;code&gt;notes.txt&lt;/code&gt; are two different files. The permanent cure is Tab completion. If you press Tab and the name will not complete, the path is wrong, and the shell just told you so before you even hit Enter.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to know you are actually progressing
&lt;/h2&gt;

&lt;p&gt;Here is the metric I trust more than any quiz: &lt;strong&gt;you stop googling the same command twice.&lt;/strong&gt; Searching for new things is normal and permanent, and every working engineer does it daily. But if you are searching "how to extract tar file" for the fifth time, the reps are not landing. Slow down and type more.&lt;/p&gt;

&lt;p&gt;Other honest signals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Tab&lt;/code&gt; and the up arrow are reflexes, and watching someone type without them feels slow.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ls -l&lt;/code&gt; output reads like a sentence instead of a cipher.&lt;/li&gt;
&lt;li&gt;When something fails, your pulse does not spike. Your fingers are already typing &lt;code&gt;systemctl status&lt;/code&gt;, then heading for the logs.&lt;/li&gt;
&lt;li&gt;You break something, fix it in four minutes, and feel vaguely disappointed that it was that easy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the signals that count for nothing, no matter how productive they feel: hours of video watched, notes taken, tutorials bookmarked. If your fingers did not type, the skill did not move.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start tonight
&lt;/h2&gt;

&lt;p&gt;Not this weekend. Tonight. Pick whichever practice option removes your personal excuse, open the terminal, and type these four commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;             &lt;span class="c"&gt;# where am I?&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt;              &lt;span class="c"&gt;# what is here?&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; /etc         &lt;span class="c"&gt;# move into the system config directory&lt;/span&gt;
&lt;span class="nb"&gt;cat &lt;/span&gt;os-release  &lt;span class="c"&gt;# print the file that names your distribution&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ten minutes and day one is done. Twenty seven to go.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>bash</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
