<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[the sudo files]]></title><description><![CDATA[I write about DevOps, Cloud Computing, Networking, and System Administration in this blog.]]></description><link>https://thesudofiles.com</link><image><url>https://cdn.hashnode.com/uploads/logos/688cf0a4277c02a454bea05e/5b9de540-0281-40bc-b3ac-0e46ee3f59f6.png</url><title>the sudo files</title><link>https://thesudofiles.com</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 12 Apr 2026 14:04:04 GMT</lastBuildDate><atom:link href="https://thesudofiles.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Building a Java Maven CI/CD Pipeline with Jenkins and Docker]]></title><description><![CDATA[As part of my DevOps learning journey, I wanted to build something practical instead of only learning the theory. I decided to create a complete CI/CD pipeline for a Java Spring Boot application using]]></description><link>https://thesudofiles.com/building-a-java-maven-ci-cd-pipeline-with-jenkins-and-docker</link><guid isPermaLink="true">https://thesudofiles.com/building-a-java-maven-ci-cd-pipeline-with-jenkins-and-docker</guid><category><![CDATA[ci-cd]]></category><category><![CDATA[Jenkins]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Pipeline]]></category><category><![CDATA[automation]]></category><category><![CDATA[Docker]]></category><category><![CDATA[deployment automation]]></category><dc:creator><![CDATA[Yushan Dewnuwan Jayaweera]]></dc:creator><pubDate>Mon, 09 Mar 2026 06:24:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/688cf0a4277c02a454bea05e/a4402d15-c045-4f99-bc5a-a3f4e8de564d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As part of my DevOps learning journey, I wanted to build something practical instead of only learning the theory. I decided to create a <strong>complete CI/CD pipeline</strong> for a Java Spring Boot application using <strong>Jenkins, Maven, Docker, GitHub, and Slack</strong>.</p>
<p>My goal was simple: automate everything from <strong>code commit to deployment</strong>.</p>
<p>I wanted a system where every time I pushed code, the application would automatically build, run tests, create a Docker image, deploy to a server, and notify the team.</p>
<p>After putting all the pieces together, I finally had a pipeline that handled the entire workflow without any manual steps.</p>
<hr />
<h1>How the Pipeline Works</h1>
<p>I designed this pipeline to follow a simple workflow.</p>
<img src="https://cdn.hashnode.com/uploads/covers/688cf0a4277c02a454bea05e/0801c3d3-0523-4f42-9702-282187b9532d.png" alt="" style="display:block;margin:0 auto" />

<p>First, a developer pushes code to GitHub. Jenkins server then detects the change and starts the pipeline automatically. The application is built using Maven, tests are executed, and a Docker image is created.</p>
<p>Once the image is built, Jenkins pushes it to Docker Hub private repository. After that, the new image is deployed to a remote production server on Digital Ocean.</p>
<p>Then automatically increment the application version and commits it to the code repository. Finally, Slack notifications are sent to report whether the build succeeded or failed.</p>
<p><a href="https://github.com/dewnuwan7/java-maven-app/">Github Repository</a></p>
<p><strong><mark class="bg-yellow-200 dark:bg-yellow-500/30">See this Pipeline in Action</mark></strong></p>
<p><a class="embed-card" href="https://youtu.be/1jv38kaBVOQ">https://youtu.be/1jv38kaBVOQ</a></p>
* * *

<h1>Jenkins Setup</h1>
<h2>Setting Up Jenkins</h2>
<p>Before creating the pipeline, I first needed to prepare my infrastructure so Jenkins could communicate with all the required services.</p>
<p>For this project, I used two droplets from <strong>DigitalOcean</strong>. One droplet was used to run Jenkins, and the other droplet acted as the <strong>production server</strong> where the application would be deployed.</p>
<img src="https://cdn.hashnode.com/uploads/covers/688cf0a4277c02a454bea05e/1666b854-80ba-4811-8e7d-bcc58adcc6aa.png" alt="" style="display:block;margin:0 auto" />

<p>I decided to run Jenkins inside a Docker container instead of installing it directly on the server. This made the setup easier to manage and allowed me to quickly start Jenkins without worrying about system dependencies.</p>
<p>On the Jenkins droplet, I installed Docker and then started Jenkins using the official Jenkins Docker image. I also mounted a Docker volume (<strong>jenkins_home</strong>) so that Jenkins data would persist even if the container restarted. After starting the container, Jenkins became accessible through the server’s public IP on port <code>8080</code>.</p>
<p>Once Jenkins was running, I logged into the Jenkins dashboard and installed the plugins needed for the pipeline.</p>
<h2>Jenkins Plugins</h2>
<p>I installed the <a href="https://plugins.jenkins.io/git/"><strong>Git plugin</strong></a>, which allows Jenkins to pull code from GitHub repositories. Then I installed the <a href="https://plugins.jenkins.io/publish-over-ssh/">Publish over SSH plugin</a>, which enables Jenkins to connect to the remote server and execute deployment commands through SSH.</p>
<p>And also the <a href="https://plugins.jenkins.io/scmskip/"><strong>SCM Skip plugin</strong></a> for avoid triggering builds from commits containing <strong>[ci-skip]</strong> message.</p>
<p>I also installed the <a href="https://plugins.jenkins.io/slack/"><strong>Slack Notification plugin</strong></a> so Jenkins could send build status updates directly to a Slack channel (#ci-cd).</p>
<p>After installing the plugins, the next step was configuring credentials in Jenkins so it could securely interact with external systems.</p>
<h2>Jenkins Credentials</h2>
<p>First, I added <strong>Docker Hub credentials</strong>. These credentials allow Jenkins to log in to Docker Hub and push the Docker images built during the pipeline into the private repository.</p>
<p>Next, I configured <strong>GitHub credentials</strong>, which Jenkins uses to commit version updates back to the repository as <strong>Jenkins</strong> user after automatically bumping the application version in <code>pom.xml</code></p>
<p>Finally, I set up <strong>SSH credentials</strong> for the production server. I generated an SSH key pair on the Jenkins server and added the public key to the <code>authorized_keys</code> file on the production droplet. This allowed Jenkins to securely connect to the server without needing a password.</p>
<p>With this setup in place, Jenkins was able to communicate with GitHub, push images to Docker Hub, and deploy the application to the remote production server.</p>
<p>Once everything was configured, I was ready to start building the CI/CD pipeline itself.</p>
<hr />
<h1>Jenkins Pipeline</h1>
<img src="https://cdn.hashnode.com/uploads/covers/688cf0a4277c02a454bea05e/7a012f19-0a8a-4315-823a-fa68a2fac245.png" alt="" style="display:block;margin:0 auto" />

<p>I implemented the pipeline using a <strong>Jenkins Declarative Pipeline</strong> defined in a <code>Jenkinsfile</code>. The pipeline is divided into several stages, each responsible for a specific part of the process.</p>
<p>Breaking the workflow into stages made the pipeline easier to understand and manage.</p>
<pre><code class="language-plaintext">

pipeline {
 agent any

 tools{
    maven 'maven-3.9.13'
 }

 stages{

    stage('Checkout Version') {
                    steps {
                        checkout scm
                        scmSkip(deleteBuild: true, skipPattern:'.*\\[ci-skip\\].*')

                        script{

                            //Incrementing Version

                            sh "mvn build-helper:parse-version versions:set \
                            -DnewVersion=\\\\({parsedVersion.majorVersion}.\\\\){parsedVersion.minorVersion}.\\\${parsedVersion.nextIncrementalVersion} versions:commit"
                            def matcher = readFile('pom.xml') =~ '&lt;version&gt;(.+)&lt;/version&gt;'
                            def version = matcher[1][1]
                            env.IMAGE_NAME = "\(version-\){BUILD_NUMBER}"
                            env.IMAGE_TAG= "dewnuwan/java-maven-app:jma-${IMAGE_NAME}"
                        }
                    }
                }

    stage("Build Project"){
        steps{
            script{

                sh 'mvn clean package'

               //commiting to git
                sh """
                   git config user.name "jenkins"
                   git config user.email "jenkins@thesudofiles.com"
                   git add .
                   git commit -m "[ci-skip] version bump"
                   """
                gitPush(gitScm: scm, targetBranch: 'master', targetRepo: 'origin')

            }
        }
    }

    stage("Test"){
        steps {
            script{
                sh 'mvn test'
            }
        }
    }


    stage("Build Image"){
        steps{
            script{
                withCredentials([usernamePassword(credentialsId: 'dockerhub', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
                    sh """
                        docker build --pull --cache-from \({IMAGE_TAG} -t \){IMAGE_TAG} .
                        echo \(PASSWORD | docker login -u \)USERNAME --password-stdin
                        docker push ${IMAGE_TAG}
                        docker rmi ${IMAGE_TAG}
                       """
                }

            }
        }
    }


    stage("Deploy"){
        steps{
            echo 'Deploying to remote server..'
            sshPublisher(publishers: [sshPublisherDesc(configName: 'prod-server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: """docker stop java-maven-app
            docker rm java-maven-app
            docker images dewnuwan/java-maven-app --format "{{.ID}}" | tail -n +2 | xargs -r docker rmi
            docker run -d -p 8080:8080 --name java-maven-app ${IMAGE_TAG}""", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+',
            remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
        }
    }

 }

    post {

        success {
            slackSend(
                channel: '#ci-cd',
                color: 'good',
                message: """
:white_check_mark: *BUILD SUCCESS*

*Job:* ${env.JOB_NAME}
*Build:* #${env.BUILD_NUMBER}
*Branch:* ${env.BRANCH_NAME}
*Docker Image:* ${env.IMAGE_TAG}
*Duration:* ${currentBuild.durationString}

*Deployment:* &lt;http://168.144.23.78:8080|Open Application&gt;

*Build Logs:* ${env.BUILD_URL}
"""
            )
        }

        failure {
            slackSend(
                channel: '#ci-cd',
                color: 'danger',
                message: """
:x: *BUILD FAILED*

*Job:* ${env.JOB_NAME}
*Build:* #${env.BUILD_NUMBER}
*Branch:* ${env.BRANCH_NAME}

Check logs:
${env.BUILD_URL}
"""
            )
        }

        unstable {
            slackSend(
                channel: '#ci-cd',
                color: 'warning',
                message: """
:warning: *BUILD UNSTABLE*

*Job:* ${env.JOB_NAME}
*Build:* #${env.BUILD_NUMBER}
*Branch:* ${env.BRANCH_NAME}

Review test results:
${env.BUILD_URL}
"""
            )
        }
    }

}
</code></pre>
<hr />
<h1>Pipeline Stages</h1>
<h2>Stage 1 - Checkout Code &amp; Version Bump</h2>
<pre><code class="language-plaintext">stage('Checkout Version') {
  steps {
          checkout scm
          scmSkip(deleteBuild: true, skipPattern:'.*\\[ci-skip\\].*')

   script{

     //Incrementing Version
sh "mvn build-helper:parse-version versions:set \
-DnewVersion=\\\\({parsedVersion.majorVersion}.\\\\){parsedVersion.minorVersion}.\\\${parsedVersion.nextIncrementalVersion} versions:commit"

  def matcher = readFile('pom.xml') =~ '&lt;version&gt;(.+)&lt;/version&gt;'
  def version = matcher[1][1]

  env.IMAGE_NAME = "\(version-\){BUILD_NUMBER}"
  env.IMAGE_TAG= "dewnuwan/java-maven-app:jma-${IMAGE_NAME}"

   }
  }
 }
</code></pre>
<p>The first thing the pipeline does is pull the latest code from the Git repository.</p>
<p>After checking out the code, I wanted Jenkins to automatically increment the application version. Instead of manually updating the version every time, I used the Maven versions plugin to automatically increase the patch version in the <code>pom.xml</code> file.</p>
<pre><code class="language-plaintext">mvn build-helper:parse-version versions:set \
-DnewVersion=\({parsedVersion.majorVersion}.\){parsedVersion.minorVersion}.${parsedVersion.nextIncrementalVersion}
</code></pre>
<p>For example, if the version was <code>1.0.0</code>, the pipeline updates it to <code>1.0.1</code>.</p>
<p>Once the version is updated, Jenkins reads the new version from the <code>pom.xml</code> file and uses it to generate a Docker image tag.</p>
<pre><code class="language-plaintext">dewnuwan/java-maven-app:jma-1.0.1-15
</code></pre>
<p>This means every build produces a unique Docker image version that can be traced back to the pipeline run.</p>
<hr />
<h2>Stage 2 - Build the Application</h2>
<pre><code class="language-plaintext">stage("Build Project"){
        steps{
            script{

                sh 'mvn clean package'

               //commiting to git
                sh """
                   git config user.name "jenkins"
                   git config user.email "jenkins@thesudofiles.com"
                   git add .
                   git commit -m "[ci-skip] version bump"
                   """
                gitPush(gitScm: scm, targetBranch: 'master', targetRepo: 'origin')

            }
        }
    }
</code></pre>
<p>After updating the version, Jenkins builds the application using Maven.</p>
<pre><code class="language-plaintext">mvn clean package
</code></pre>
<p>This step compiles the code and generates the JAR file needed to run the Spring Boot application.</p>
<p>Since Jenkins updated the version earlier, I also configured it to commit that change back to the Git repository. To prevent Jenkins from triggering another build from this commit, I added <code>[ci-skip]</code> to the commit message using <strong>SCMSkip</strong> plugin.</p>
<p>This avoids an infinite build loop.</p>
<hr />
<h2>Stage 3 - Running Tests</h2>
<pre><code class="language-plaintext">stage("Test"){
        steps {
            script{
                sh 'mvn test'
            }
        }
    }
</code></pre>
<p>Next, the pipeline runs all unit tests using Maven.</p>
<p>If any test fails, the pipeline stops immediately. This is important because it prevents broken code from reaching production.</p>
<p>Having automated tests as part of the pipeline ensures that every deployment is verified before it goes live.</p>
<hr />
<h2>Stage 4 - Building and Pushing the Docker Image</h2>
<pre><code class="language-plaintext">stage("Build Image"){
        steps{
            script{
                withCredentials([usernamePassword(credentialsId: 'dockerhub', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
                    sh """
                        docker build --pull --cache-from \({IMAGE_TAG} -t \){IMAGE_TAG} .
                        echo \(PASSWORD | docker login -u \)USERNAME --password-stdin
                        docker push ${IMAGE_TAG}
                        docker rmi ${IMAGE_TAG}
                       """
                }

            }
        }
    }
</code></pre>
<p>Once the tests pass, Jenkins builds a Docker image for the application.</p>
<p>The <code>Dockerfile</code> packages the Spring Boot JAR file into a container so the application can run in a consistent environment.</p>
<pre><code class="language-dockerfile">FROM eclipse-temurin:25.0.2_10-jre-ubi10-minimal

RUN mkdir app

WORKDIR /app

COPY target/java-maven-app-*.jar .

EXPOSE 8080

CMD java -jar java-maven-app-*.jar
</code></pre>
<p>After building the image, Jenkins logs into Docker Hub using stored credentials and pushes the image to the dockerhub registry.</p>
<img src="https://cdn.hashnode.com/uploads/covers/688cf0a4277c02a454bea05e/3728e796-b586-49b1-ac71-c6730d579cd1.png" alt="" style="display:block;margin:0 auto" />

<p>Once the image is successfully pushed, the local copy of the image is removed from the Jenkins server to save disk space. This ensures that the server doesn’t accumulate unused Docker images over time.</p>
<hr />
<h2>Stage 5 - Deploying the Application</h2>
<pre><code class="language-plaintext">  stage("Deploy"){
        steps{
            echo 'Deploying to remote server..'
            sshPublisher(publishers: [sshPublisherDesc(configName: 'prod-server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: """docker stop java-maven-app
            docker rm java-maven-app
            docker images dewnuwan/java-maven-app --format "{{.ID}}" | tail -n +2 | xargs -r docker rmi
            docker run -d -p 8080:8080 --name java-maven-app ${IMAGE_TAG}""", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+',
            remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
        }
    }
</code></pre>
<p>After pushing the image to Docker Hub, Jenkins connects to the remote production server using SSH.</p>
<p>The deployment process is simple but effective.</p>
<p>First, Jenkins stops the currently running container. Then it removes the old container and cleans up older Docker images. Finally, it starts a new container using the latest Docker image that was just built.</p>
<p>Within a few seconds, the updated application is running on the server and accessible through port 8080. Everything automated.</p>
<img src="https://cdn.hashnode.com/uploads/covers/688cf0a4277c02a454bea05e/076fd1f1-0124-401c-9c96-94f5a5772492.png" alt="" style="display:block;margin:0 auto" />

<p>Watching the application update automatically without logging into the server manually was very satisfying for me.</p>
<hr />
<h2>Slack Notifications</h2>
<p>To make the pipeline more useful, I added Slack notifications.</p>
<p>Whenever a build finishes, Jenkins sends a message to a Slack channel indicating whether the build was successful, failed, or unstable.</p>
<img src="https://cdn.hashnode.com/uploads/covers/688cf0a4277c02a454bea05e/7314edd1-e6ef-453a-bb5f-7948949aa033.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/688cf0a4277c02a454bea05e/19139048-cf51-4a37-a79b-51653b2b4c83.png" alt="" style="display:block;margin:0 auto" />

<p>The message includes useful information such as the job name, build number, branch, Docker image version, and links to the deployment and build logs.</p>
<p>This makes it easy for the team to quickly see what’s happening with the pipeline.</p>
<hr />
<h1>What I Learned from This Project</h1>
<p>Building this pipeline helped me understand how several DevOps tools work together in a real world workflow.</p>
<p>I learned how continuous integration ensures that every code change is automatically built and tested. I also saw how containerization with Docker helps maintain consistency across environments.</p>
<blockquote>
<p>Automating version updates made deployments easier to track, while automated deployment removed the need for manual server work.</p>
</blockquote>
<p>Most importantly, the pipeline showed me how automation can reduce human error and make the development process much faster.</p>
<hr />
<h1>Final Thoughts</h1>
<p>Creating this CI/CD pipeline was a great learning experience.</p>
<p>It was exciting to see the entire workflow run automatically from code commit to deployment without any manual intervention.</p>
<img src="https://cdn.hashnode.com/uploads/covers/688cf0a4277c02a454bea05e/9620321a-4d03-482f-abe7-c78f340f8c80.png" alt="" style="display:block;margin:0 auto" />

<p>This project gave me practical experience with Jenkins, Maven, Docker, GitHub, and Slack integration, and it helped me better understand how modern DevOps pipelines work.</p>
<p>In the future, I plan to expand this project by exploring container orchestration tools like Kubernetes, infrastructure automation, and more advanced deployment strategies such as blue-green deployments.</p>
<p>There is still a lot to learn, but this project was a big step forward in my DevOps journey.</p>
]]></content:encoded></item><item><title><![CDATA[20 Basic Commands in Linux - Linux Simplified]]></title><description><![CDATA[In this post, we’ll explore 20 basic Linux commands everyone should know.
1. whoami
Displays the currently logged-in user.


2. pwd
pwd stands for Print Working Directory. It displays the current directory the user’s in.


3. ls
ls is used to List fi...]]></description><link>https://thesudofiles.com/20-basic-commands-in-linux-linux-simplified</link><guid isPermaLink="true">https://thesudofiles.com/20-basic-commands-in-linux-linux-simplified</guid><category><![CDATA[Linux]]></category><category><![CDATA[linux-commands]]></category><category><![CDATA[terminal]]></category><category><![CDATA[linux for beginners]]></category><category><![CDATA[fundamentals]]></category><dc:creator><![CDATA[Yushan Dewnuwan Jayaweera]]></dc:creator><pubDate>Sun, 10 Aug 2025 09:58:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1754820131236/d8309dec-03db-44ab-87d0-3fef6cb125ce.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-in-this-post-well-explore-20-basic-linux-commands-everyone-should-know">In this post, we’ll explore 20 basic Linux commands everyone should know.</h2>
<h2 id="heading-1-whoami">1. whoami</h2>
<p>Displays the currently logged-in user.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754529317598/85b16539-c768-416d-b971-9bae1729f969.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-2-pwd">2. pwd</h2>
<p>pwd stands for <strong>Print Working Directory</strong>. It displays the current directory the user’s in.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754529344379/9c0458ef-858e-49ea-836c-4085cbab670b.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-3-ls">3. ls</h2>
<p><code>ls</code> is used to <strong>List</strong> files and directories. This is one of the most fundamental and frequently used commands in the Linux terminal. When used without any options, it shows the contents of the current directory the user’s in.</p>
<p>Here are the options for the <code>ls</code>.</p>
<ul>
<li><p><code>-l</code> Long, detailed list of all information.</p>
</li>
<li><p><code>-a</code> Lists all files, including hidden files (those starting with a <code>.</code>).</p>
</li>
<li><p><code>-h</code> List files with human readable file sizes.</p>
</li>
<li><p><code>-r</code> Reverse order lists files with the oldest date first.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754529398698/362c4dec-66cb-4909-8f24-995e11043125.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754529384382/2ace0345-2622-4b7e-af62-e2914b002dbf.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-4-tree">4. tree</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754634503396/b5a38814-fec1-4043-8b12-e4e79891e09a.png" alt class="image--center mx-auto" /></p>
<p>This command outputs a tree-like view of the specified directory and its content (files, subdirectories). It makes it easier to look up the content inside a directory.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754637018202/a67a9987-db0f-4a2a-8e4c-a90d2d715f48.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-5-cd">5. cd</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754531997265/949f13d0-9970-4f77-b6d5-f783fbc799be.png" alt class="image--center mx-auto" /></p>
<p>The <strong>Change Directory</strong> command is used for navigating between directories.</p>
<p><code>cd ..</code> Moves up a directory</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754529443838/c1fdfdee-6f9c-44d4-a52f-3983c734e014.png" alt class="image--center mx-auto" /></p>
<p><code>cd -</code> Returns to the previous directory</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754529496502/668093d9-fda0-4616-b9a1-72f39fba712f.png" alt class="image--center mx-auto" /></p>
<p><code>cd</code> Goes to the user’s home directory</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754529579135/99804fc7-25c2-46fa-a6a8-b8889dc199f4.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-6-mkdir">6. mkdir</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754531941800/924dcb89-badd-4784-b3c2-b967df96ef21.png" alt class="image--center mx-auto" /></p>
<p><code>mkdir</code> stands for <strong>Make Directory.</strong> This command is used for creating directories.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754529799111/7c0f8050-7daf-45d3-bca4-1e4e8b73e192.png" alt class="image--center mx-auto" /></p>
<p>Creating multiple directories at once.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754529857989/131f6c37-2b84-4ba5-85ed-d54687dececb.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-7-cp">7. cp</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754531825756/fb2328d1-d8ba-4fd0-bf97-fd5d4684bc3e.png" alt class="image--center mx-auto" /></p>
<p><code>cp</code> stands for <strong>Copy.</strong> This commands is used for copying files and directories.</p>
<p>In this example, I want to copy the <strong>linux.txt</strong> file into the <strong>Documents</strong> directory.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754530145735/90282962-ba12-4a61-b6cb-0ef8afc0125a.png" alt class="image--center mx-auto" /></p>
<p>So here’s <code>cp</code> command for that.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754530264329/41b0c95e-1839-4551-b294-8ee5fbe00e37.png" alt class="image--center mx-auto" /></p>
<p>Verifying inside the <strong>Documents</strong> directory.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754530318355/03e9195b-4b59-4c32-b721-f10ac80b6f5b.png" alt class="image--center mx-auto" /></p>
<p>Note using <code>cp</code> with <code>-r</code> allows you to copy a directory with its content.</p>
<hr />
<h2 id="heading-8-mv">8. mv</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754531885577/1908e427-396a-405a-a6e6-278ba0fdb7dd.png" alt class="image--center mx-auto" /></p>
<p><code>mv</code> stands for <strong>Move</strong>. This command is used for moving and renaming the files and directories.</p>
<p>Here I moved the <strong>linux.txt</strong> file from the current directory (<strong><em>/home/dewnuwan/Documents)</em></strong> into the Music directory (<strong><em>/home/dewnuwan/Music).</em></strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754530658753/f59aeb07-40dd-476a-a57b-545c2bb905ca.png" alt class="image--center mx-auto" /></p>
<p>Verifying inside the Music directory.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754530834862/884263ee-40ca-4a80-89aa-d6e23cd0bc68.png" alt class="image--center mx-auto" /></p>
<p>While there’s a <code>rename</code> command in Linux, it’s only being used for batch operations. So most of the time we just use <code>mv</code> to rename the files and directories.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754531453882/09ed472a-6b2d-48cb-92ee-0ebbd2d588b7.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-9-rm">9. rm</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754532421659/e215ef01-6b1a-4812-b14d-e39e28c269a2.png" alt class="image--center mx-auto" /></p>
<p><code>rm</code> stands for <strong>Remove.</strong> This is used for removing files from a directory. You need write access for the folder. Here are the most used options for this command.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754636310566/650e8f33-a793-4013-a38a-54ae6e2c1380.png" alt class="image--center mx-auto" /></p>
<p><code>-r</code> Remove the directory with its subdirectories (alternative to <code>rmdir</code>).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754636371190/85654232-3c0b-4d2d-8925-fa9d1f27e466.png" alt class="image--center mx-auto" /></p>
<p><code>-i</code> Prompt a confirmation message before deleting</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754636440552/ef476e0e-0fe7-4a0e-982b-7ed1c56bcb2b.png" alt class="image--center mx-auto" /></p>
<p><code>-f</code> Force delete (without a confirmation dialogue)</p>
<h3 id="heading-forceful-recursion">Forceful Recursion</h3>
<p>The most common and dangerous combination of options is <code>rm -rf</code>. This command will delete everything in the directory and its subdirectories without any confirmation. So use it carefully.</p>
<p><em>Here</em> <strong>*</strong> <em>stands for all in the current directory.</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754636681073/cadaadae-2c73-4b85-a2e1-a7237edfe244.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-10-rmdir">10. rmdir</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754532529062/ded88d78-7312-4c4f-8e31-099270e9ff2a.png" alt class="image--center mx-auto" /></p>
<p>This is to remove a specified <strong>empty directory</strong>. Use the option <code>-p</code> to force the deletion.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754637745300/59788451-b33c-47b1-9cac-ce37e1e8e29e.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-11-cat">11. cat</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754639011233/01c31bd7-443b-453a-b09f-9939daa7d649.png" alt class="image--center mx-auto" /></p>
<p><code>cat</code> is used for viewing content inside of a file. (text files, scripts..etc)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754639479415/2ffbb2f2-bfe1-41d5-b7b7-1d85b10fb524.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-12-echo">12. echo</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754638171097/cd2886ca-d67d-4451-9d49-7a0cd783c1c9.png" alt class="image--center mx-auto" /></p>
<p><code>echo</code> is useful when we want to get an output of a line of text. This is very useful when creating shell scripts.</p>
<ul>
<li><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754638084749/464f4abe-7a17-4dd0-930b-0ce1231ef102.png" alt class="image--center mx-auto" /></li>
</ul>
<p>Similarly, it can also be used with <code>&gt;</code> , to overwrite a text input to a file.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754650773200/9e536d19-4f92-43a1-bf10-ffa46e76f7f5.png" alt class="image--center mx-auto" /></p>
<p>We can also use <code>echo</code> to append a line of text to a file with <code>»</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754650883630/47a76b49-c021-42c1-b256-25ef30e6a484.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-13-touch">13. touch</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754652635010/ec804e0b-a95a-4e50-9546-36df804dd3ce.png" alt class="image--center mx-auto" /></p>
<p><code>touch</code> is useful for creating new files. Simply enter the file name with the extension.</p>
<p>Here I created a simple Python script called <strong>scripting.py</strong> using <code>touch</code> and added a code using <code>echo</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754652987235/2e96e587-8580-4b6e-b9c5-c3e41fa66a75.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-14-grep">14. grep</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754653080989/143ef34e-e1d3-47fa-8d3d-598c104cf093.png" alt class="image--center mx-auto" /></p>
<p><code>grep</code> stands for <strong>Global Regular Expression Print.</strong> It is used for searching speicifc string or a pattern within a file OR filtering out the results from a command output.</p>
<p>Here I listed the content inside <code>/</code> directory. And I want to see only the results including "“<strong>lib</strong>”.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754653510882/ce70a4df-ba18-4b06-87f5-b0159ccbcba1.png" alt class="image--center mx-auto" /></p>
<p>so I will filter the ls -l command by using what we called pipe. which redirects the output of the <code>ls -l</code> command through the <code>grep</code> command.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754653607668/559dc571-d95c-4507-b2dd-1f88f7d8625c.png" alt class="image--center mx-auto" /></p>
<p>Note that now it’s only showing the results that include the “lib” in their name.</p>
<hr />
<h2 id="heading-15-locate">15. locate</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754675283286/9e2234f2-a1d7-4f89-8c00-9acb7fc6cced.png" alt class="image--center mx-auto" /></p>
<p>This is another simple but very important command. Very useful when it comes to finding the path of a specific file/directory by going through the whole system at once.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754675732285/87287d13-b70e-4f49-b68b-7625231f1f42.png" alt class="image--center mx-auto" /></p>
<p>Note that <code>locate</code> uses a local database to locate anything. And that database is only updated once per day. So we’ll have to use <code>updatedb</code> command once before using locate sometimes with new files/directories.</p>
<hr />
<h2 id="heading-16-find">16. find</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754676394950/065d4baa-de5b-4a6d-8719-64409dee42fe.png" alt class="image--center mx-auto" /></p>
<p><code>find</code> is the top searching utility command that we can use to find anything we want within a specific directory. Unlike the <code>locate</code> command, <code>find</code> looks for files in real time, so there’s no need to wait for the database to be refreshed.</p>
<p><code>-name</code> Search files using name</p>
<p><code>-type</code> Search items using its type (For files use <code>f</code>, for directories use <code>d</code>)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754808995207/cb39f0ce-a86a-4f9d-aaed-24fdf9af4eb2.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-17-sudo">17. sudo</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754809607422/8638789d-2edc-478e-bd0f-f0d8b002aaf6.png" alt class="image--center mx-auto" /></p>
<p><code>sudo</code> stands for <strong>Super User Do.</strong> It allows a regular non-root user (who is in the <strong><em>sudo group</em></strong>) to execute commands as the superuser (administrator). Once entered you need to enter the user’s password. This is a regular command you’ll be using in a Linux system.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754809699147/eecf0cf6-94f1-4fe2-9c47-a7fff53a127b.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-18-history">18. history</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754809882931/fc4cffaf-c84e-4537-b0d3-63a5fa927e36.png" alt class="image--center mx-auto" /></p>
<p><code>history</code> allows us to view the previously entered commands history in the terminal. This is very handy when it comes to troubleshooting.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754809818482/7cbdc9f9-a7cc-467e-96af-7c3a0ec26cc7.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-19-man">19. man</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754810227418/fccb0d31-6377-4f86-a3b8-31069e977ffa.png" alt class="image--center mx-auto" /></p>
<p><code>man</code> stands for <strong>Manual.</strong> This is used to figure out what a certain command is doing. Basically allows us to read the manual written by the devs. Simply adds <code>man</code> before a command name.</p>
<p>This example shows the manual for the <code>rmdir</code> command.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754810092880/222f59a0-cb79-450d-a58b-2c4350c1213a.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-20-nano">20. nano</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754819037379/9b6c1455-114a-4452-9174-e48e9249e52c.png" alt class="image--center mx-auto" /></p>
<p><code>nano</code> is an easy-to-use simple text editor that comes preinstalled with many Linux distros.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754818983914/f78abc33-1e81-4b15-b26f-a551fd377ba1.png" alt class="image--center mx-auto" /></p>
<p>Okay, so this concludes the second post in this <strong>Linux</strong> <strong>Simplified</strong> blog series. Let’s talk about <strong>user and group management in Linux</strong> in the next post!</p>
]]></content:encoded></item><item><title><![CDATA[Understanding the Linux File System Hierarchy - Linux Simplified]]></title><description><![CDATA[Welcome to my Linux Simplified series!
In this post, we're diving into one of the most fundamental concepts of Linux: the Filesystem Hierarchy Standard (FHS).
Filesystem Hierarchy Standard (FHS)
If you are familiar with Windows, you might know that t...]]></description><link>https://thesudofiles.com/understanding-the-linux-file-system-hierarchy-linux-simplified</link><guid isPermaLink="true">https://thesudofiles.com/understanding-the-linux-file-system-hierarchy-linux-simplified</guid><category><![CDATA[Linux]]></category><category><![CDATA[FHS]]></category><category><![CDATA[file system hierarchy]]></category><category><![CDATA[file system]]></category><category><![CDATA[terminal]]></category><category><![CDATA[command line]]></category><category><![CDATA[Open Source]]></category><dc:creator><![CDATA[Yushan Dewnuwan Jayaweera]]></dc:creator><pubDate>Wed, 06 Aug 2025 03:12:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1754495038436/0e5610c2-6157-44a6-8f0c-2336b9663ee2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to my <strong>Linux Simplified</strong> series!</p>
<p>In this post, we're diving into one of the most fundamental concepts of Linux: the <strong>Filesystem Hierarchy Standard (FHS)</strong>.</p>
<h1 id="heading-filesystem-hierarchy-standard-fhs">Filesystem Hierarchy Standard (FHS)</h1>
<p>If you are familiar with Windows, you might know that there are partitions named by letters (C:, D:). But Linux organizes everything into a more unified directory tree system called <strong>FHS</strong>. This tree starts with the root directory (<code>/</code>). Every file, every directory, every device and even the processes are represented as a file under this <code>/</code> directory.</p>
<p>Remember, <strong><mark>everything is a file in Linux!</mark></strong></p>
<p>This may sound intimidating at first, but it’s a pretty simple system, and understanding it is really useful for understanding how things work inside IT and infrastructure in general. Because nowadays almost every system runs on Linux. Also, since this is a standard among Linux distros, no matter what Linux distro you’re in, you’ll find files in roughly the same places. This makes it much easier to learn,troubleshoot and manage Linux systems.</p>
<h2 id="heading-why-is-fhs-important">Why Is FHS Important?</h2>
<ul>
<li><p>Quickly find files</p>
</li>
<li><p>Troubleshoot effectively</p>
</li>
<li><p>Correctly install packages</p>
</li>
<li><p>Maintaining security</p>
</li>
</ul>
<hr />
<p>Here's a diagram of the tree hierarchy.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754434707660/091b38d9-b18d-455c-b26d-5b69ce825e1b.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-key-directories">Key Directories</h2>
<p>These specific subdirectories have their own purpose.</p>
<p><code>/</code> <strong>(Root Directory)</strong></p>
<ul>
<li>This is the top level directory of the hierarchy, and everything belongs under this.</li>
</ul>
<hr />
<p><code>/root</code> <strong>(Root User’s Home)</strong></p>
<ul>
<li>Root user’s personal directory (similar to <code>/home/username</code>)</li>
</ul>
<hr />
<p><code>/bin</code> <strong>(Binaries/Executables)</strong></p>
<ul>
<li><p>Contains essential user command binaries like <code>mv</code>, <code>cp</code>, <code>ls</code>, <code>cat</code>.</p>
</li>
<li><p>Always available to all users.</p>
</li>
</ul>
<hr />
<p><code>/sbin</code> <strong>(System Binaries)</strong></p>
<ul>
<li><p>Contains system binaries that are essential for managing and maintaining the system. (mounting, checking, shutting down disks...etc.)</p>
</li>
<li><p>Important for troubleshooting.</p>
</li>
</ul>
<hr />
<p><code>/lib</code> <strong>(Library Files)</strong></p>
<ul>
<li><p>Similar to DLL files in Windows.</p>
</li>
<li><p>These are the shared libraries and kernel modules primarily required by the essential binaries in <code>/bin</code> and <code>/sbin</code> for system boot and core functions.</p>
</li>
<li><p>Depending on the system, you’ll find <code>/lib32</code> and <code>/lib64</code> directories alongside the <code>/lib</code> directory.</p>
</li>
</ul>
<hr />
<p><code>/dev</code> <strong>(Devices)</strong></p>
<ul>
<li>All the hardware devices(HDD, CD/DVD, USB..etc) are shown as files.</li>
</ul>
<hr />
<p><code>/mnt</code> <strong>(Mount)</strong></p>
<ul>
<li><p>Contains the manually mounted devices.</p>
</li>
<li><p>Useful for system maintenance and recovery situations.</p>
</li>
</ul>
<hr />
<p><code>/media</code> <strong>(Media)</strong></p>
<ul>
<li><p>Contains the removable devices as usable files (HDD, CD/DVD, USB).</p>
</li>
<li><p>Unlike <code>/mnt</code> , Linux automatically mounts these devices here.</p>
</li>
</ul>
<hr />
<p><code>/boot</code> <strong>(Boot)</strong></p>
<ul>
<li><p>Contains all the crucial system files that are required for the system booting.</p>
</li>
<li><p>Examples:</p>
<ul>
<li><p><code>initrd</code></p>
</li>
<li><p><code>initramfs</code></p>
</li>
<li><p><code>GRUB</code></p>
</li>
<li><p><code>grub.cfg</code></p>
</li>
</ul>
</li>
</ul>
<hr />
<p><code>/etc</code> <strong>(Editable Text Configurations)</strong></p>
<ul>
<li><p>Contains the system-wide configurations (network,user accounts, startup scripts,service config..etc).</p>
</li>
<li><p>These are generally static config files, not binaries.</p>
</li>
<li><p>Use cases</p>
<ul>
<li><p><code>ssh/sshd_config</code> SSH Server Config</p>
</li>
<li><p><code>passwd</code> User Password Config</p>
</li>
<li><p><code>fstab</code> File System Table</p>
</li>
</ul>
</li>
</ul>
<hr />
<p>    <code>/proc</code> <strong>(Process Information)</strong></p>
<ul>
<li><p>This is a virtual file system.</p>
</li>
<li><p>Contains the running processes and Linux kernel parameters.</p>
</li>
<li><p>Tools like <code>top</code> and <code>ps</code> get the information from here.</p>
</li>
<li><p>Monitoring, debugging, and interacting with processes.</p>
<ul>
<li><p><code>/proc/meminfo</code></p>
</li>
<li><p><code>/proc/cpuinfo</code></p>
</li>
</ul>
</li>
</ul>
<hr />
<p><code>/sys</code> <strong>(System Information)</strong></p>
<ul>
<li><p>This is a virtual file system.</p>
</li>
<li><p>Shows the drivers, kernel and hardware information.</p>
</li>
<li><p>Used by the system utilities.</p>
</li>
</ul>
<hr />
<p><code>/usr</code> <strong>(Unix System Resource)</strong></p>
<ul>
<li><p>Contains the system's user programs and utilities, libraries and documentation.</p>
</li>
<li><p>These aren’t essential for booting up/repairing the system.</p>
</li>
<li><p>Use cases</p>
<ul>
<li><p><code>/usr/bin</code> Popular user executable programs like <code>python</code>, <code>git</code>, <code>firefox</code>.</p>
</li>
<li><p><code>/usr/sbin</code> Nonessential sysadmin programs.</p>
</li>
<li><p><code>/usr/lib</code> Libraries for <code>/usr/bin/usr/sbin</code></p>
</li>
<li><p><code>/usr/local</code> Reserved for locally installed/compiled programs (To avoid any conflicts with system-managed packages)</p>
</li>
</ul>
</li>
</ul>
<hr />
<p><code>/var</code> <strong>(Variable Data)</strong></p>
<ul>
<li><p>Contains the variable data files.</p>
</li>
<li><p>Use cases</p>
<ul>
<li><p><code>/var/log</code> System log files</p>
</li>
<li><p><code>/var/www</code> Default location for web server files (ex: Apache)</p>
</li>
<li><p><code>/var/mail</code> User mailbox</p>
</li>
<li><p><code>/var/tmp</code> Temp files that are kept between reboots (Unlike <code>/tmp)</code></p>
</li>
</ul>
</li>
</ul>
<hr />
<p><code>/run</code> <strong>(Runtime Data)</strong></p>
<ul>
<li><p>Contains the current running data on RAM</p>
</li>
<li><p>Starts very early in startup process</p>
</li>
<li><p>Replacement for legacy <code>/var/run</code> and <code>/var/lock</code></p>
</li>
</ul>
<hr />
<p><code>/srv</code> <strong>(Services)</strong></p>
<ul>
<li><p>Contains the service related files.</p>
</li>
<li><p>Use cases</p>
<ul>
<li><p><code>/srv/www</code> Web Server (recommended by <strong>FHS</strong> instead to <code>/var/www</code>)</p>
</li>
<li><p>FTP Server</p>
</li>
</ul>
</li>
</ul>
<hr />
<p><code>/home</code> <strong>(User Home Directories)</strong></p>
<ul>
<li><p>Contains the personal directories of regular (non-root) users.</p>
</li>
<li><p>Each user has their own directory</p>
<ul>
<li><p><code>/home/username1</code></p>
</li>
<li><p><code>/home/username2</code></p>
</li>
</ul>
</li>
<li><p>Usually a user’s documents, downloads, personal scripts… etc all belong here.</p>
</li>
</ul>
<hr />
<p><code>/opt</code> <strong>(Optional)</strong></p>
<ul>
<li><p>Used for optional software packages that aren’t part of the standard system.</p>
</li>
<li><p>Most of the time used to install software by third party software vendors.</p>
</li>
</ul>
<hr />
<p><code>/tmp</code> <strong>(Temporary)</strong></p>
<ul>
<li><p>Stores the temporary data used by applications and users.</p>
</li>
<li><p>Automatically erase all the data after a reboot.</p>
</li>
<li><p>Writeable by everyone.</p>
</li>
</ul>
<hr />
<p>As you might understand now, this <strong>FHS</strong> provides a logical, consistent format that makes our lives easy to find configuration files, locate logs for troubleshooting, and manage the system more effectively.</p>
<p>Ok, so this is a wrap-up. See you in the next post where I’ll talk about the basic commands in the Linux terminal.</p>
]]></content:encoded></item></channel></rss>