<?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[Untitled Publication]]></title><description><![CDATA[Karlygash Yakiyayeva
Systems Engineer
DevOps
Cloud Engineer
AWS]]></description><link>https://karlygash-yakiyayeva.dev</link><generator>RSS for Node</generator><lastBuildDate>Sun, 06 Sep 2026 05:44:17 GMT</lastBuildDate><atom:link href="https://karlygash-yakiyayeva.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to view the commit history in Git]]></title><description><![CDATA[The git log command is used to view the commit history of a Git repository. You can customize the output format to show specific details in a more readable or structured way. Below are some useful variations and formatting options for git log:

To sh...]]></description><link>https://karlygash-yakiyayeva.dev/how-to-view-the-commit-history-in-git</link><guid isPermaLink="true">https://karlygash-yakiyayeva.dev/how-to-view-the-commit-history-in-git</guid><category><![CDATA[Git]]></category><category><![CDATA[Devops]]></category><category><![CDATA[SDLC]]></category><dc:creator><![CDATA[Karlygash Yakiyayeva]]></dc:creator><pubDate>Sat, 08 Feb 2025 15:45:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/xUXGHzhIbN4/upload/c74529c853427a8e820d6b3a2eb91660.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The <code>git log</code> command is used to view the commit history of a Git repository. You can customize the output format to show specific details in a more readable or structured way. Below are some useful variations and formatting options for <code>git log</code>:</p>
<ol>
<li><p>To show commit history in reverse chronological order, run:</p>
<pre><code class="lang-bash"> git <span class="hljs-built_in">log</span>
</code></pre>
<p> <img src="https://i.imgur.com/OgsnOAH.png" alt class="image--center mx-auto" /></p>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">If the logs are longer than your screen, it always goes into interactive mode. To escape and come back to the shell,<strong> quit </strong><code>git log</code> with <code>q</code>.</div>
 </div>
</li>
<li><p>To display each commit as a single line with its short SHA-1 hash and commit message, run:</p>
<pre><code class="lang-bash"> git <span class="hljs-built_in">log</span> --oneline
</code></pre>
<p> <img src="https://i.imgur.com/ZQEPyXS.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To show more details about all previous commits, run:</p>
<pre><code class="lang-bash"> git <span class="hljs-built_in">log</span> -p
</code></pre>
<p> <img src="https://i.imgur.com/5E0ZEDJ.png" alt class="image--center mx-auto" /></p>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">To limit output to the last two commits, you can add the <code>-2</code> option: <code>git log -p -2</code></div>
 </div>
</li>
<li><p>To show how many files changed and the number of insertions (+) and deletions (-), run:</p>
<pre><code class="lang-bash"> git <span class="hljs-built_in">log</span> --<span class="hljs-built_in">stat</span>
</code></pre>
<p> <img src="https://i.imgur.com/gMCN6gk.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To group commits by author and display commit messages under each author's name, run:</p>
<pre><code class="lang-bash"> git shortlog
</code></pre>
<p> <img src="https://i.imgur.com/2nQUgYe.png" alt class="image--center mx-auto" /></p>
<p> This command can be used to <strong>quickly see who contributed the most</strong> to a repository, to <strong>get an overview of contributions</strong> instead of a detailed history, and to <strong>prepare contributor statistics</strong> for reports or release notes.</p>
</li>
<li><p>To visualize some work with branches, run the command:</p>
<pre><code class="lang-bash"> git <span class="hljs-built_in">log</span> --graph --oneline
</code></pre>
<ul>
<li><p><code>--graph</code> → Displays a commit graph showing branch relationships.</p>
</li>
<li><p><code>--oneline</code> → Shows each commit in a single line.</p>
</li>
</ul>
</li>
</ol>
<p>    <img src="https://i.imgur.com/CqMy9Vd.png" alt class="image--center mx-auto" /></p>
<p>    We can see that <code>second-branch</code> was created and merged with the <code>master</code> branch.</p>
<ol start="7">
<li><p>To completely change the log output to display a structured and visually enhanced commit history, use the <code>--pretty</code> option:</p>
<pre><code class="lang-bash"> git <span class="hljs-built_in">log</span> --pretty=<span class="hljs-string">"%C(yellow) Commit: %h %C(magenta)Date: %ad %C(red) Message: %s %C(cyan) Author: %an"</span> --date=human
</code></pre>
<ul>
<li><p><code>--pretty="..."</code> → Customizes the format of the log output.</p>
<ul>
<li><p><code>%C(yellow)</code> → Changes <code>Hash:</code> text color to yellow.</p>
</li>
<li><p><code>%h</code> → Displays the short commit hash.</p>
</li>
<li><p><code>%ad</code> → Displays a date of commit.</p>
</li>
<li><p><code>%s</code> → Shows the commit message.</p>
</li>
<li><p><code>%an</code> → Shows who committed the changes.</p>
</li>
</ul>
</li>
<li><p><code>--date=human</code> → Formats the date in a human-readable way (e.g., "2 days ago" instead of a timestamp).</p>
<p>  <img src="https://i.imgur.com/npcjabs.png" alt class="image--center mx-auto" /></p>
  <div data-node-type="callout">
  <div data-node-type="callout-emoji">💡</div>
  <div data-node-type="callout-text">If <code>--pretty=""</code> contains a <strong>custom format string</strong> (using <code>%h</code>, <code>%s</code>, <code>%C</code> for colors, etc.), Git treats it as <code>format:</code> automatically. Therefore, you <strong>don’t need to explicitly write </strong><code>format:</code> when using a custom format.</div>
  </div>
</li>
</ul>
</li>
<li><p>To show commit stats with the <code>pretty</code> option, run:</p>
<pre><code class="lang-bash"> git <span class="hljs-built_in">log</span> --pretty=format:<span class="hljs-string">"%Cred %h - %Cgreen %an: %C(yellow) %s"</span> --<span class="hljs-built_in">stat</span>
</code></pre>
<p> <img src="https://i.imgur.com/n8X2sFb.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To create an alias called <code>lg</code> , we need to change the configuration file (<code>config</code>), on <code>global</code> table (<code>--global</code>) by adding the following entry:</p>
<pre><code class="lang-bash"> git config --global alias.lg <span class="hljs-string">'log --color --graph --pretty="%C(red) %h%Creset - %C(yellow) %s %C(green) (%cr) %C(blue) &lt;%an&gt;"'</span>
</code></pre>
<p> <img src="https://i.imgur.com/oyLAg57.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To check the alias definition, run the command:</p>
<pre><code class="lang-bash">git config --global --get alias.lg
</code></pre>
<p><img src="https://i.imgur.com/O6yXu9f.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<h3 id="heading-querying-through-git-log">Querying through <code>git log</code></h3>
<p>So far we used ALL information from <code>git log</code>. It is possible to narrow the search by querying though the <code>git log</code>. We can query through <code>git log</code> using various filters and options to find specific commits based on author, date, message, file changes, branches, and more.</p>
<ol>
<li><p>To show all commits done by 2 people, we can use regex:</p>
<pre><code class="lang-bash"> git <span class="hljs-built_in">log</span> --author=<span class="hljs-string">"John Doe\|Alice"</span>
</code></pre>
<p> <img src="https://i.imgur.com/jPFSz8f.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To search for commit by date, run:</p>
<pre><code class="lang-bash"> git <span class="hljs-built_in">log</span> --since=<span class="hljs-string">"2024-01-01"</span> --until=<span class="hljs-string">"2024-02-01"</span>
</code></pre>
<p> This will show commits made between Jan 1, 2024, and Feb 1, 2024</p>
</li>
<li><p>To search for commits by message (keyword search) and make the search case-insensitive, run:</p>
<pre><code class="lang-bash"> git <span class="hljs-built_in">log</span> --grep=<span class="hljs-string">"Feature"</span> --grep=<span class="hljs-string">"bug fix"</span> --regexp-ignore-case
</code></pre>
<p> This will find commits where the message contains both "bug fix", ‘'“BUG FIX“, “Bug fix“, “FEATURE“, “Feature“, "feature".</p>
<p> <img src="https://i.imgur.com/MdwVz5P.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To search for commits that modified several files, run:</p>
<pre><code class="lang-bash"> git <span class="hljs-built_in">log</span> -- testfile-01 branchfile-01
</code></pre>
<p> This will show commits affecting <em>testfile-01</em> and <em>branchfile-01</em>.</p>
<p> <img src="https://imgur.com/fKbEBc1.png" alt class="image--center mx-auto" /></p>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">Using the <code>--</code> we inform git that we have files in mind, not branches.</div>
 </div>
</li>
<li><p>To show the last 5 commits, run:</p>
<pre><code class="lang-bash"> git <span class="hljs-built_in">log</span> -5
</code></pre>
<p> <img src="https://i.imgur.com/t7OA3nf.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To list only merge commits, run:</p>
<pre><code class="lang-bash"> git <span class="hljs-built_in">log</span> --merges
 git <span class="hljs-built_in">log</span> --no-merges
</code></pre>
<ul>
<li><code>--no-merges</code> - excludes merge commits from the output, run:</li>
</ul>
</li>
</ol>
<p>    <img src="https://i.imgur.com/t6Cw3cc.png" alt class="image--center mx-auto" /></p>
<ol start="7">
<li><p>To search for commits from a specific branch, run:</p>
<pre><code class="lang-bash"> git <span class="hljs-built_in">log</span> main
 git <span class="hljs-built_in">log</span> master..second-branch
 git <span class="hljs-built_in">log</span> second-branch..master
</code></pre>
<p> <img src="https://i.imgur.com/PKmiB41.png" alt class="image--center mx-auto" /></p>
<p> <code>git log master..second-branch</code> compares the commit history of both branches and shows commits that exist in <code>second-branch</code> but are missing in <code>master</code>. Once the branch <code>second-branch</code> is merged into <code>master</code>, all its commits become part of <code>master</code>’s history. Therefore, Git finds nothing unique in <code>second-branch</code> and the output returns nothing</p>
<p> <code>git log second-branch..master</code> shows commits in <code>master</code> that <code>second-branch</code> doesn’t have.</p>
</li>
<li><p>To get a precise result, we can combine multiple filters:</p>
<pre><code class="lang-bash"> git <span class="hljs-built_in">log</span> --author=<span class="hljs-string">"John Doe"</span> --grep=<span class="hljs-string">"bug-fix"</span> --since=<span class="hljs-string">"10 weeks ago"</span>
</code></pre>
</li>
</ol>
<h2 id="heading-references">References</h2>
<ol>
<li><a target="_blank" href="https://git-scm.com/docs/git-log">git log documentation</a></li>
</ol>
]]></content:encoded></item><item><title><![CDATA[How to Install Ubuntu Server 24.04]]></title><description><![CDATA[Overview
This article will teach us how to:

Install Ubuntu Server 24.04 on a laptop from scratch

Install Ubuntu server by using Vagrant tool with ISO image


Prerequisites:

A laptop without any OS installed;

A virtualization software Virtualbox t...]]></description><link>https://karlygash-yakiyayeva.dev/how-to-install-ubuntu-server-2404</link><guid isPermaLink="true">https://karlygash-yakiyayeva.dev/how-to-install-ubuntu-server-2404</guid><category><![CDATA[ #SystemAdministration ]]></category><category><![CDATA[Ubuntu]]></category><category><![CDATA[Linux]]></category><category><![CDATA[sysops]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Karlygash Yakiyayeva]]></dc:creator><pubDate>Sun, 02 Feb 2025 19:55:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/vIQDv6tUHYk/upload/0e8419753bccff0fd4dc2cfe3352d225.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-overview">Overview</h3>
<p>This article will teach us how to:</p>
<ul>
<li><p>Install Ubuntu Server 24.04 on a laptop from scratch</p>
</li>
<li><p>Install Ubuntu server by using <a target="_blank" href="https://www.vagrantup.com/">Vagrant</a> tool with ISO image</p>
</li>
</ul>
<p>Prerequisites:</p>
<ol>
<li><p>A laptop without any OS installed;</p>
</li>
<li><p>A virtualization software Virtualbox that Vagrant uses to create virtual machines.</p>
</li>
<li><p>Vagrant which automates the setup and provisioning of virtual machines.</p>
</li>
</ol>
<h3 id="heading-installing-ubuntu-server-on-laptop">Installing Ubuntu Server on Laptop</h3>
<p>Installing Ubuntu Server on a laptop is a straightforward process, though it involves several steps:</p>
<ol>
<li><p>Go to the <a target="_blank" href="https://ubuntu.com/download/server">Ubuntu Server Download Page</a> and click the download link to get the ISO file. In this hands-on, Ubuntu Server 24.04.1 LTS version was downloaded and used as a base image.</p>
</li>
<li><p>Download a <a target="_blank" href="https://etcher.balena.io/"><em>balenaEtcher</em></a><em>,</em> a USB creation tool that allows you to create bootable media.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728315509258/3cb320b4-e16b-4d96-93cf-70475cfeab2b.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Now, when <em>balenaEtcher</em> is downloaded as a <code>.zip</code> file, extract it with the <code>unzip</code> command:</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728315718145/018ea82d-96f6-4844-9207-d309da22e60f.png" alt class="image--center mx-auto" /></p>
<p> After extraction, you will find an executable file with <code>.AppImage</code> extension.</p>
</li>
<li><p>Insert your USB drive with at least 4 GB of space into your computer.</p>
</li>
<li><p>Run the balenaEtcher, select the downloaded Ubuntu Server ISO, choose the USB drive, and start the flashing process:</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728316080031/3a34d492-e1eb-4018-90d7-c63f082f72b0.png" alt class="image--center mx-auto" /></p>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">This process will erase all data on the USB drive, so make sure to back up any important files.</div>
 </div>
</li>
<li><p>Insert the bootable USB drive into your laptop, restart your laptop, and enter the boot menu (usually by pressing <code>F12</code> on the Dell laptop).</p>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">If you have any important data on your laptop, back it up as the installation process may erase the entire disk.</div>
 </div>
</li>
<li><p>Select the USB drive from the boot options and press <code>Enter</code>.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728373084387/004d3b8b-2d68-426b-9ad8-1fd3f6681a82.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Choose the language you want to use for the installation process.</p>
</li>
<li><p>Select your preferred keyboard layout.</p>
</li>
<li><p>Choose the type of installation.</p>
</li>
<li><p>Configure Network:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728373347039/4389e80d-ca7b-48a2-b2a1-676cc8c53f34.png" alt class="image--center mx-auto" /></p>
<p>If your network is not found among other networks, you can continue without a network and later configure the network at your own pace.</p>
</li>
<li><p>If your system requires a proxy to connect to the Internet, configure your Proxy.</p>
</li>
<li><p>If you use an alternative mirror for Ubuntu, enter the Mirror address details.</p>
</li>
<li><p>Set Up the Storage:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728373975425/19bb29f1-477d-4911-8d5c-b873cba9fda9.png" alt class="image--center mx-auto" /></p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">In this hands-on, an entire disk was chosen for the Ubuntu Server OS, however choosing the entire disk is not recommended since it will erase all data on the disk, making it unsuitable if you need to preserve existing data or partitions.</div>
</div>
</li>
<li><p>Create a user account by entering your name, the server name, and a username and password for the system.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728378622626/a3d09f9e-f7a2-4870-bfcb-8f2ab9ed87c2.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>If you plan to access your server remotely, choose to install the OpenSSH server.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728378838614/00cf7558-1cd1-4f00-9325-72646dc4ee05.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Confirm the installation details and start the process. The installer will copy the files and configure the system. This may take some time.</p>
</li>
<li><p>Once the installation is complete, remove the installation media and press <code>Enter</code> to reboot.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728378993735/c99dbda0-e63a-4011-9e71-9f2ad9f15e6c.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Log in with the username and password you created during the installation.</p>
<p>Your Ubuntu Server installation is now complete. You can start using it as a server or install additional services as needed.</p>
</li>
</ol>
<h3 id="heading-install-ubuntu-server-via-vagrant">Install Ubuntu Server via Vagrant</h3>
<p>To install Ubuntu Server manually using a Vagrant machine with a downloaded ISO file, follow these steps:</p>
<ol>
<li><p>Edit the <code>Vagrantfile</code> to configure the virtual machine and specify that it should boot from the ISO file:</p>
<pre><code class="lang-bash">  Vagrant.configure(<span class="hljs-string">"2"</span>) <span class="hljs-keyword">do</span> |config|
   config.vm.box = <span class="hljs-string">"bento/ubuntu-20.04"</span>
   config.vm.provider <span class="hljs-string">"virtualbox"</span> <span class="hljs-keyword">do</span> |vb|  
       vb.gui = <span class="hljs-literal">true</span> 
       <span class="hljs-comment"># Ensure the boot order prioritizes booting from the virtual DVD drive</span>
       vb.customize [<span class="hljs-string">"modifyvm"</span>, :id, <span class="hljs-string">"--boot1"</span>, <span class="hljs-string">"dvd"</span>, <span class="hljs-string">"--boot2"</span>, <span class="hljs-string">"disk"</span>]
       <span class="hljs-comment"># Attach the ISO file to the VM as a virtual DVD drive to the existing SATA controller</span>
       vb.customize [<span class="hljs-string">"storageattach"</span>, :id, <span class="hljs-string">"--storagectl"</span>, <span class="hljs-string">"SATA Controller"</span>, <span class="hljs-string">"--port"</span>, <span class="hljs-string">"0"</span>, <span class="hljs-string">"--device"</span>, <span class="hljs-string">"0"</span>, <span class="hljs-string">"--type"</span>, <span class="hljs-string">"dvddrive"</span>, <span class="hljs-string">"--medium"</span>, <span class="hljs-string">"path/to/your/ubuntu-24.04.1-live-server-amd64.iso"</span>]

       <span class="hljs-comment"># Create and attach a virtual hard disk to the SATA controller for installation</span>
      vb.customize [<span class="hljs-string">"createhd"</span>, <span class="hljs-string">"--filename"</span>, <span class="hljs-string">"ubuntu-server-disk.vdi"</span>, <span class="hljs-string">"--size"</span>, 20000]  <span class="hljs-comment"># creates a 20 GB virtual hard disk that the Ubuntu Server can be installed on.</span>
      vb.customize [<span class="hljs-string">"storageattach"</span>, :id, <span class="hljs-string">"--storagectl"</span>, <span class="hljs-string">"SATA Controller"</span>, <span class="hljs-string">"--port"</span>, <span class="hljs-string">"1"</span>, <span class="hljs-string">"--device"</span>, <span class="hljs-string">"0"</span>, <span class="hljs-string">"--type"</span>, <span class="hljs-string">"hdd"</span>, <span class="hljs-string">"--medium"</span>, <span class="hljs-string">"ubuntu-server-disk.vdi"</span>] <span class="hljs-comment">#the new virtual hard disk is attached to the SATA controller</span>

       <span class="hljs-comment"># Optionally increase VM resources (like memory or CPU)</span>
       vb.memory = <span class="hljs-string">"4096"</span>
       vb.cpus = 2
   end
   <span class="hljs-comment"># Configure a bridged network</span>
   config.vm.network <span class="hljs-string">"public_network"</span>, bridge: <span class="hljs-string">"wlo1: Wi-Fi (Home)"</span>
   <span class="hljs-comment">#This configuration forwards requests made to port 2222 on your host machine to port 22 on the Vagrant guest machine</span>
   config.vm.network <span class="hljs-string">"forwarded_port"</span>, guest: 22, host: 2222, auto_correct: <span class="hljs-literal">true</span>
 end
</code></pre>
<p> Replace <code>"path/to/your/ubuntu-server.iso"</code> with the actual path to the Ubuntu Server ISO file on your system.</p>
</li>
<li><p>Once your <code>Vagrantfile</code> is ready, you can boot the machine:</p>
<pre><code class="lang-bash"> vagrant up
</code></pre>
<p> This will start the virtual machine and boot from the ISO file to install Ubuntu Server on the virtual hard disk.</p>
</li>
<li><p>Since the ISO is loaded, the Ubuntu Server installation screen will appear. You should now be able to install Ubuntu Server as if you were on physical hardware. Proceed with the standard Ubuntu Server installation steps within the VM.</p>
</li>
<li><p>After installation is complete, you may see an error “<code>Failed unmounting crdom.mount /cdrom</code>“, which means that the installation medium (ISO image) is still mounted in the virtual machine's virtual CD-ROM drive. Power off the VM to make sure that the ISO file is detached from the virtual machine so that the system can reboot from the newly installed Ubuntu Server operating system on the virtual hard disk.</p>
</li>
<li><p>Now edit the Vagrantfile to change the boot order to boot directly from the virtual hard disk (where the OS was already installed).</p>
<pre><code class="lang-bash"> <span class="hljs-comment"># Ensure the boot order prioritizes booting from the virtual DVD drive</span>
 vb.customize [<span class="hljs-string">"modifyvm"</span>, :id, <span class="hljs-string">"--boot1"</span>, <span class="hljs-string">"dvd"</span>, <span class="hljs-string">"--boot2"</span>, <span class="hljs-string">"disk"</span>]
</code></pre>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">The <strong>default boot order</strong> typically prioritizes the hard disk once an operating system is installed.</div>
 </div>
</li>
<li><p>To access your Ubuntu Server installed via VirtualBox with <code>vagrant ssh</code>, you need to ensure that the VM is configured to allow SSH access. Power on the server through VirtualBox again and install SSH to be able to interact with the Ubuntu Server directly via the terminal:</p>
<pre><code class="lang-bash"> sudo apt install openssh-server 
 sudo systemctl <span class="hljs-built_in">enable</span> ssh <span class="hljs-comment">#to start the service at boot</span>
 sudo systemctl start ssh
 sudo systemctl status ssh
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729555894819/a5bfcb43-6061-49b2-b994-a9cb5b26814c.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Now that SSH is running on your Ubuntu Server, we need to update the <code>Vagrantfile</code> to handle SSH connections correctly:</p>
<pre><code class="lang-bash"> Vagrant.configure(<span class="hljs-string">"2"</span>) <span class="hljs-keyword">do</span> |config|
   <span class="hljs-comment"># Use the existing box or manually installed Ubuntu Server</span>
   config.vm.box = <span class="hljs-string">"bento/ubuntu-20.04"</span>
   config.vm.provider <span class="hljs-string">"virtualbox"</span> <span class="hljs-keyword">do</span> |vb|
     <span class="hljs-comment"># Ensure the boot order prioritizes the hard disk</span>
     vb.customize [<span class="hljs-string">"modifyvm"</span>, :id, <span class="hljs-string">"--boot1"</span>, <span class="hljs-string">"disk"</span>, <span class="hljs-string">"--boot2"</span>, <span class="hljs-string">"dvd"</span>]
     <span class="hljs-comment"># Optionally increase VM resources</span>
     vb.memory = 4096
     vb.cpus = 2
   end
   <span class="hljs-comment"># SSH Configurations</span>
   <span class="hljs-comment">#config.vm.network "public_network", bridge: "wlo1: Wi-Fi (Home)"  # Adjust to your network interface</span>
   config.vm.network <span class="hljs-string">"forwarded_port"</span>, guest: 22, host: 2222, auto_correct: <span class="hljs-literal">true</span>  <span class="hljs-comment"># Forward SSH port</span>
   <span class="hljs-comment"># Use vagrant's default insecure key (no need for password)</span>
   config.ssh.username = <span class="hljs-string">"vagrant"</span>  <span class="hljs-comment"># Ensure this matches the username created during Ubuntu installation</span>
   config.ssh.private_key_path = <span class="hljs-string">"~/.vagrant.d/insecure_private_key"</span> <span class="hljs-comment"># Ensure key matches</span>
 end
</code></pre>
</li>
<li><p>If Ubuntu Server was installed manually and a <code>vagrant</code> user was not created, create one now. Vagrant expects to use a user <code>vagrant</code> with passwordless SSH access.</p>
<pre><code class="lang-bash"> sudo adduser vagrant
 sudo usermod -aG sudo vagrant
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729736127643/3d43ad83-f010-40f3-9188-b8cdc9fd2054.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Add Vagrant’s Public Key</strong>: The <strong>default Vagrant SSH key</strong> needs to be added to the <code>vagrant</code> user’s <code>authorized_keys</code>. Copy Vagrant's default insecure public key to the <code>vagrant</code> user’s SSH directory to allow passwordless SSH access.</p>
<pre><code class="lang-bash"> sudo mkdir /home/vagrant/.ssh
 sudo curl -Lo /home/vagrant/.ssh/authorized_keys https://raw.githubusercontent.com/hashicorp/vagrant/master/keys/vagrant.pub
 sudo chown -R vagrant:vagrant /home/vagrant/.ssh
 sudo chmod 700 /home/vagrant/.ssh
 sudo chmod 600 /home/vagrant/.ssh/authorized_keys
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729823525653/95d5351e-4970-45cf-8146-c97f36b4d56b.png" alt class="image--center mx-auto" /></p>
<ul>
<li>Adding the Vagrant public key ensures Vagrant can authenticate using the default key and configuring <code>authorized_keys</code> and permissions resolves any SSH authentication issues.</li>
</ul>
</li>
<li><p>Now that the <code>Vagrantfile</code> was updated and the <code>vagrant</code> user was set up, reload the Vagrant configuration:</p>
<pre><code class="lang-bash">vagrant reload
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">If you encounter “Warning. Authentication failure. Retrying…“ you can ignore it by pressing Ctrl+C</div>
</div>
</li>
<li><p>At this point, the VM should be up and running. On the host machine, run the following:</p>
<pre><code class="lang-bash">ssh -i ~/.vagrant.d/insecure_private_key -p 2222 vagrant@localhost
</code></pre>
<p>If you can successfully SSH into the server, it confirms that the SSH configuration is correct. Enter the password of your Ubuntu Server if needed.</p>
</li>
<li><p>You can also run the following:</p>
<pre><code class="lang-bash">vagrant ssh
</code></pre>
</li>
</ol>
<h2 id="heading-references">References</h2>
<ol>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=pln-tglFxwg">How to Deploy Ubuntu Server 24.04 LTS: Step-by-Step Installation Overview</a></p>
</li>
<li><p><a target="_blank" href="https://dev.to/vumdao/create-an-ubuntu-20-04-server-using-vagrant-3d2i">Create An Ubuntu 20.04 Server Using Vagrant</a></p>
</li>
<li><p><a target="_blank" href="https://phoenixnap.com/kb/how-to-install-vagrant-on-ubuntu">How to Install, Deploy, and Uninstall Vagrant on Ubuntu 22.04</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Understanding /etc/passwd/ and /etc/shadow/ files in Linux]]></title><description><![CDATA[The /etc/passwd and /etc/shadow files are the backbone of Linux user management. Together, they store user account information and handle authentication securely. This article provides a hands-on guide to understanding these files, their structure, a...]]></description><link>https://karlygash-yakiyayeva.dev/understanding-etcpasswd-and-etcshadow-files-in-linux</link><guid isPermaLink="true">https://karlygash-yakiyayeva.dev/understanding-etcpasswd-and-etcshadow-files-in-linux</guid><category><![CDATA[Linux]]></category><category><![CDATA[Devops]]></category><category><![CDATA[passwords]]></category><category><![CDATA[administration]]></category><category><![CDATA[admin]]></category><dc:creator><![CDATA[Karlygash Yakiyayeva]]></dc:creator><pubDate>Sat, 23 Nov 2024 14:14:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/qC2n6RQU4Vw/upload/0e206c9041425df27bc09880399b8819.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The <code>/etc/passwd</code> and <code>/etc/shadow</code> files are the backbone of Linux user management. Together, they store user account information and handle authentication securely. This article provides a hands-on guide to understanding these files, their structure, and their role in Linux user management.</p>
<h2 id="heading-etcpasswd-explained"><code>/etc/passwd/</code> explained</h2>
<p>The <code>/etc/passwd</code> file stores basic information about user and system accounts. It is a text file that resides in the <code>/etc</code> directory. <code>/etc/passwd</code> has general read permission on all systems because it does not include hashed passwords and many command utilities use it to map user IDs to user names.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732090522229/e38fb492-eb0f-43da-a53b-7d61e58a9e6d.png" alt class="image--center mx-auto" /></p>
<p>Each line within this file corresponds to the user account and each entry is split into columns, separated by a colon (:).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732371123511/508b87b2-f197-4557-bab7-e921a671d944.png" alt class="image--center mx-auto" /></p>
<p>Image credits: <a target="_blank" href="https://www.cyberciti.biz/faq/understanding-etcpasswd-file-format/#google_vignette">Cyberciti.biz</a></p>
<ol>
<li><p>Type the following command to look at the content of the <code>passwd</code> file:</p>
<pre><code class="lang-bash"> cat /etc/passwd | tail -5
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731913742882/375d5e60-651c-4f50-9f4f-5116c7b553fe.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<h4 id="heading-explanation-of-fields"><strong>Explanation of Fields</strong></h4>
<ol>
<li><p><code>username</code>: The user’s login name.</p>
</li>
<li><p><code>x</code>: A placeholder indicating that the password is stored in <code>/etc/shadow</code>.</p>
</li>
<li><p><code>UID</code>: The user's unique numerical ID. To the Linux system, each time when we reference user <code>jdoe</code>, we are actually referencing UID 1002. When a user is created, the system by default automatically assigns the next available UID.</p>
</li>
<li><p><code>GID</code>: The unique numerical ID of the primary group that the user belongs to. Creating groups works in a similar way to creating users, in the sense that the group is assigned the next available GID.</p>
</li>
<li><p><code>gecos-field</code>: The comment field. It allows you to add extra information about the users such as full name, phone number etc.</p>
</li>
<li><p><code>home_directory</code>: Path to the user’s home directory.</p>
</li>
<li><p><code>shell</code>: Default shell for the user (e.g., <code>/bin/bash</code>).</p>
</li>
</ol>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">In case of a security issue and it is required to disable an account quickly, we could change the user’s shell to something invalid (e.g. <code>/sbin/nologin</code>) to prevent the user from logging in at all.</div>
</div>

<h2 id="heading-etcshadow-explained"><code>/etc/shadow/</code> explained</h2>
<p>The <code>/etc/shadow</code> file stores password-related information securely. Unlike the <code>/etc/passwd</code> file, <code>/etc/shadow</code> does not have general read permission.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732172901651/808475c3-f84d-4e68-a124-f6dfe512f567.png" alt class="image--center mx-auto" /></p>
<p>Since the <code>/etc/shadow</code> file contains sensitive hashed password information only the <strong>root user</strong> has full control over the file. Members of the <strong>shadow group</strong> (e.g., system processes or utilities that require access) can read it but not modify it while <strong>others</strong> (regular users) cannot access the file at all.</p>
<p>Type the following command to look at the content of the <code>shadow</code> file:</p>
<pre><code class="lang-bash">sudo cat /etc/shadow | tail -4
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732172181305/934466a6-d1b2-4cf5-b72b-ac8d7b2e6779.png" alt class="image--center mx-auto" /></p>
<p>Each line within this file corresponds to the user and contains password hashes and other security information.</p>
<h4 id="heading-explanation-of-fields-1"><strong>Explanation of Fields</strong></h4>
<ol>
<li><p><code>username</code>: The login name.</p>
</li>
<li><p><code>password</code>: The hashed password. In practice placing <code>!</code>/<code>*</code> signs is one way to lock out an account. The restriction is that we cannot directly log in as <code>root</code> account from the shell or over the network. We have to log in to the system as a normal user account first. Usually, the password format is set to <kbd>$id$salt$hashed</kbd>, The <kbd>$id</kbd> is the algorithm prefix used On GNU/Linux as follows:</p>
<ol>
<li><p><strong><kbd>$1$</kbd></strong> is MD5</p>
</li>
<li><p><strong><kbd>$2a$</kbd></strong> is Blowfish</p>
</li>
<li><p><strong><kbd>$2y$</kbd></strong> is Blowfish</p>
</li>
<li><p><strong><kbd>$5$</kbd></strong> is SHA-256</p>
</li>
<li><p><strong><kbd>$6$</kbd></strong> is SHA-512</p>
</li>
<li><p><strong><kbd>$y$</kbd></strong> is yescrypt</p>
</li>
</ol>
</li>
<li><p><code>lastchanged</code>: Days since Unix Epoch (January 1, 1970) when the password was last changed. 0 means the password <strong>must be changed immediately</strong> upon the user's next login. Empty field means the system treats it as no password change tracking, potentially indicating a misconfigured or unused account.</p>
</li>
<li><p><code>min</code>: Minimum days between password changes. 0 means the password can be changed anytime.</p>
</li>
<li><p><code>max</code>: Maximum days a password is valid. After that, the user is forced to change her password again.</p>
</li>
<li><p><code>warn</code>: Days before expiration to warn the user.</p>
</li>
<li><p><code>inactive</code>: Days after expiration before the account is disabled.</p>
</li>
<li><p><code>expire</code>: Days since Unix Epoch when the account will be disabled.</p>
</li>
</ol>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Use the <code>chage</code> command to setup password aging.</div>
</div>

<p>Unfortunately, this file is neither readable nor writable to regular Linux users. However, a small set of commands allows modifying <code>/etc/shadow</code> files for a standard user account. For example, the <code>passwd</code> command enables users to change their passwords.</p>
<h2 id="heading-references">References</h2>
<ol>
<li><p><a target="_blank" href="https://www.cyberciti.biz/faq/understanding-etcpasswd-file-format/#google_vignette">Understanding /etc/passwd File Format</a></p>
</li>
<li><p><a target="_blank" href="https://www.cyberciti.biz/faq/understanding-etcshadow-file/">Understanding /etc/shadow file format on Linux</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Understanding Symbolic Links and Hard Links in Linux]]></title><description><![CDATA[In Linux, links are powerful tools that allow you to create references to files and directories. There are two main types of links: hard links and soft links (also known as symbolic links or symlinks). Understanding the differences between these two ...]]></description><link>https://karlygash-yakiyayeva.dev/understanding-symbolic-links-and-hard-links-in-linux</link><guid isPermaLink="true">https://karlygash-yakiyayeva.dev/understanding-symbolic-links-and-hard-links-in-linux</guid><category><![CDATA[Devops]]></category><category><![CDATA[Linux]]></category><category><![CDATA[softlink]]></category><category><![CDATA[hardlink]]></category><dc:creator><![CDATA[Karlygash Yakiyayeva]]></dc:creator><pubDate>Sat, 21 Sep 2024 11:39:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Xe7za0JtTeM/upload/8cf6f763cc8bd94ee5ebb1695af433ab.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In Linux, links are powerful tools that allow you to create references to files and directories. There are two main types of links: <strong>hard links</strong> and <strong>soft links</strong> (also known as symbolic links or symlinks). Understanding the differences between these two can help you effectively manage your filesystem.</p>
<h2 id="heading-what-is-link">What is Link?</h2>
<p>Before starting to work with hard and soft links, let's first understand what a link is in Linux.</p>
<p>Every storage device contains files and directories in a collection of blocks.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722007361102/cef2c190-c4fe-4666-a0a5-2c203ff671cb.png" alt class="image--center mx-auto" /></p>
<p>Information about a file or directory is stored in a data structure called <em>inode</em>. Inodes contain metadata such as who is the owner of the file, when it was created and when it was last accessed, its size, permissions, ownership, and pointers to the data blocks where the file's contents are actually stored etc.</p>
<p>Every storage medium, such as hard disks, flash drives, etc., has its own inodes. These inodes are specific to the filesystem, storage device, and partition. So if we move one text file from the local storage device to the flash drive, it will get a different inode.</p>
<p>Every inode has an <em>inode number</em> that is unique and used by the filesystem to locate the inode.</p>
<p>A <em>directory entry</em> is essentially a table maintained by the filesystem that contains a name for a file or directory and a pointer (reference, often an address) to the inode number.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Filename</td><td>Inode number</td></tr>
</thead>
<tbody>
<tr>
<td>report.txt</td><td>43132770</td></tr>
<tr>
<td>image.png</td><td>43132771</td></tr>
</tbody>
</table>
</div><div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">We can not directly view the raw directory entry because the filesystem manages it at a low level. However, we can view information about the files in a directory, including inode numbers, which are part of the directory entries using the commands <code>ls -li</code> or <code>stat</code></div>
</div>

<p>A <em>link</em> is simply an additional directory entry for a file or directory. It is between the filename and the actual data stored on the filesystem. By creating links we can have multiple directory entries (names) for the same file or directory, allowing two or more names for the same thing.</p>
<h2 id="heading-hard-links">Hard Links</h2>
<p>A hard link is a directory entry that points directly to the inode of a file. It acts as a separate file and refers to the exact spot on a hard drive. It is a mirror copy of the original file. Let's look at how to create hard links and find out how they work. To create the hard link, use <code>ln</code> command.</p>
<p><strong>Creating a hard link</strong>:</p>
<ol>
<li><p>Create an original file:</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">echo</span> <span class="hljs-string">"Hello World!"</span> &gt; original.txt
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722515246589/10b8346f-29dd-4255-a86d-2bd244645599.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Create a hard link:</p>
<pre><code class="lang-bash"> ln original.txt hardlink.txt
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722515419279/39ddbedb-a62a-4697-89d3-b3d9e64a6cd5.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Verify the inode numbers of the original and hard link files:</p>
<pre><code class="lang-bash"> ls -i original.txt hardlink.txt
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722515575361/ae792d3d-6a12-4f1d-9933-4f0b15145c29.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<p>As we can see, both <code>original.txt</code> and <code>hardlink.txt</code> share the same inode number, indicating they point to the same file content.</p>
<p><strong>Editing the hard link</strong></p>
<ol start="4">
<li><p>Make changes to the hard link <code>hardlink.txt</code>:</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">echo</span> <span class="hljs-string">"Nice to see you World"</span> &gt;&gt; hardlink.txt
</code></pre>
</li>
<li><p>Check the content of the original file <code>original.txt</code></p>
<pre><code class="lang-bash"> cat original.txt
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722517146640/509eb247-eba0-42c1-8b47-3e8d389da581.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<p>As we can see, changes made to <code>hardlink.txt</code> are reflected in <code>original.txt</code> because they refer to the same inode.</p>
<p><strong>Deleting the original file</strong></p>
<ol start="6">
<li><p>Delete the original file:</p>
<pre><code class="lang-bash"> rm original.txt
</code></pre>
</li>
<li><p>Check the content of the hard link <code>hardlink.txt</code>:</p>
<pre><code class="lang-bash"> cat hardlink.txt
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722518809458/7a2cd0f7-2b91-436a-8a84-0dadc62cabc2.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<p>As we can see, the file content is still accessible through <code>hardlink.txt</code> since the inode and data blocks are preserved until <em>all</em> hard links are removed.</p>
<p><strong>Creating multiple hard links</strong></p>
<ol start="8">
<li><p>Create another hard link:</p>
<pre><code class="lang-bash"> ln hardlink.txt another-hardlink.txt
</code></pre>
</li>
<li><p>Verify Inode numbers:</p>
<pre><code class="lang-bash"> ls -li hardlink.txt another-hardlink.txt
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722519508799/ade1b0e6-5230-406d-abb4-4bf0c3bad95d.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<p>Again, both <code>hardlink.txt</code> and <code>another-hardlink.txt</code> share the same inode number, indicating they point to the same file content.</p>
<h3 id="heading-hard-link-advantages-and-disadvantages">Hard Link Advantages and Disadvantages</h3>
<p>Hard links have the following advantages:</p>
<ol>
<li><p><strong>Efficient Storage:</strong> Hard links share the same inode and data blocks, which means no additional disk space is used for multiple hard links to the same file.</p>
</li>
<li><p><strong>File Availability</strong>: As long as at least one hard link exists, the file's data remains accessible. Deleting one hard link does not delete the file.</p>
</li>
<li><p><strong>Performance</strong>: Hard links are typically faster than symbolic links because they point directly to the inode without the need for path resolution.</p>
</li>
<li><p><strong>Transparency</strong>: Hard links appear and behave like regular files. There is no distinction between the original file and its hard links.</p>
</li>
<li><p><strong>Consistency</strong>: All hard links to a file are always up-to-date. Any changes made to the file through any hard link are immediately reflected in all other hard links.</p>
</li>
</ol>
<p>While useful, there are some limitations to what hard links can do.</p>
<ol>
<li><p><strong>Restrictions on Directories</strong>: Hard links can only be created for regular files (not directories or special files).</p>
</li>
<li><p><strong>Single Filesystem Limitation</strong>: Hard links cannot span multiple filesystems. They only work when the new hard link exists on the same filesystem as the original.</p>
</li>
</ol>
<h2 id="heading-soft-links">Soft Links</h2>
<p>A soft link (symbolic link) is a separate file that contains the path to another file or directory. Unlike hard links, soft links do not reference the inode of the target file directly but instead have their own inodes and contain the path to the target file or directory.</p>
<h4 id="heading-creating-a-soft-link">Creating a Soft Link</h4>
<ol>
<li><p>Create an original file:</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">echo</span> <span class="hljs-string">"Hello World"</span> &gt; original.txt
</code></pre>
</li>
<li><p>Create a soft link using the command <code>ln -s</code>:</p>
<pre><code class="lang-bash"> ln -s original.txt softlink.txt
</code></pre>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">An absolute path should be specified when creating symbolic links since relative paths will not work.</div>
 </div>
</li>
<li><p>Verify the soft link by typing:</p>
<pre><code class="lang-bash"> ls -l original.txt softlink.txt
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722602010721/a3460494-6d9d-48c8-a211-a76bfba3ef1c.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Read the content of the <code>softlink.txt</code> file:</p>
<pre><code class="lang-bash"> cat softlink.txt
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722602238538/f75a30c6-899f-4c72-b280-32c0724a2998.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<h4 id="heading-editing-the-soft-link">Editing the Soft Link</h4>
<ol start="5">
<li><p>Edit the soft link <code>softlink.txt</code>:</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">echo</span> <span class="hljs-string">"Nice to see you World!"</span> &gt;&gt; softlink.txt
</code></pre>
</li>
<li><p>Check the content of the <code>original.txt</code> file:</p>
<pre><code class="lang-bash"> cat original.txt
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722602713909/418162cb-0146-44ce-b440-8b8e55c3ad28.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<p>As we can notice, changes made through <code>softlink.txt</code> are reflected in <code>original.txt</code>.</p>
<p><strong>Moving the target file</strong></p>
<ol start="7">
<li><p>Move (or delete) the <code>original.txt</code> file to another location in the system:</p>
<pre><code class="lang-bash"> mv original.txt ./backup/
</code></pre>
</li>
<li><p>Again, check the content of the <code>softlink.txt</code> file:</p>
<pre><code class="lang-bash"> cat softlink.txt
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722603149631/8f59814f-d8e9-47fd-931d-0e27e4e0e2a3.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<p>As we can see, the soft link becomes a "dangling" link, as its target is moved to another location (or no longer exists in case it is deleted).</p>
<h4 id="heading-linking-to-directories">Linking to Directories</h4>
<p>Because the soft link connection is a logical connection, not a duplication, soft links can point to entire directories or links to files on remote computers. Hard links cannot do this. Let's find out how it works.</p>
<ol start="9">
<li><p>Create a folder and a file:</p>
<pre><code class="lang-bash"> mkdir my-folder
 <span class="hljs-built_in">echo</span> <span class="hljs-string">"Learn how to create soft links to folders"</span> &gt; my-folder/file
</code></pre>
</li>
<li><p>Create a soft link named <code>soft-folder</code> to the directory <code>my-folder</code>:</p>
<pre><code class="lang-bash">ln -s my-folder soft-folder
</code></pre>
</li>
<li><p>Verify the link:</p>
<pre><code class="lang-bash">ls -l
</code></pre>
</li>
<li><p>Access the directory <code>my-folder</code> using soft link <code>soft-folder</code>:</p>
<pre><code class="lang-bash">ls soft-folder
</code></pre>
</li>
<li><p>Delete the original folder <code>my-folder</code> and list the <code>soft-folder</code>:</p>
<pre><code class="lang-bash">rm -r my-folder
ls soft-folder
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722684924949/be97646e-daf4-4984-847f-abed2e1d46cf.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<p>As we can see, since the original folder was removed, listing <code>soft-folder</code> shows nothing in the output. The target was deleted and the link became useless.</p>
<h3 id="heading-soft-link-advantages-and-disadvantages">Soft Link Advantages and Disadvantages</h3>
<p>Soft links have the following advantages:</p>
<ol>
<li><p><strong>Flexibility</strong>: Soft links can link to both files and directories and span across different filesystems or partitions.</p>
</li>
<li><p><strong>Convenience</strong>: It is easy to create shortcuts and organize files with soft links. They can link to non-existent files, which will work once the target is created.</p>
</li>
<li><p><strong>Low Overhead</strong>: The size of soft link files is small since they only store the path to the target.</p>
</li>
</ol>
<p>While useful, there are some drawbacks of soft links.</p>
<ol>
<li><p><strong>Fragility</strong>: They can become "dangling" links if the target is moved, renamed, or deleted.</p>
</li>
<li><p><strong>Performance</strong>: They have slightly slower access than hard links because they require an extra path resolution step.</p>
</li>
<li><p><strong>Security</strong>: They can potentially introduce security risks if not managed properly, as they can point to sensitive files.</p>
</li>
<li><p><strong>Different Inodes</strong>: Soft links have their own inodes, which can add overhead to inode usage.</p>
</li>
</ol>
<h2 id="heading-references">References</h2>
<ol>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=zfSa-PEU3h4&amp;list=PLT98CRl2KxKHKd_tH3ssq0HPrThx2hESW&amp;index=19">Linux Crash Course - Symbolic Links</a></p>
</li>
<li><p><a target="_blank" href="https://www.cbtnuggets.com/blog/certifications/open-source/linux-hard-links-versus-soft-links-explained">Linux Hard Links versus Soft Links Explained</a></p>
</li>
<li><p><a target="_blank" href="https://developer.ibm.com/tutorials/l-lpic1-104-6/">Create and change hard and symbolic links</a></p>
</li>
<li><p><a target="_blank" href="https://www.redhat.com/sysadmin/linking-linux-explained">Hard links and soft links in Linux explained</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Setting the Hostname of Linux Workstation or Server]]></title><description><![CDATA[A hostname is a human-friendly name given to a computer. It is a unique identifier that allows us to identify the machine in various network communications, making it easier to locate and manage devices.
Type:
hostname

To see where it is stored, typ...]]></description><link>https://karlygash-yakiyayeva.dev/setting-the-hostname-of-linux-workstation-or-server</link><guid isPermaLink="true">https://karlygash-yakiyayeva.dev/setting-the-hostname-of-linux-workstation-or-server</guid><category><![CDATA[Linux]]></category><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[hostname]]></category><dc:creator><![CDATA[Karlygash Yakiyayeva]]></dc:creator><pubDate>Tue, 17 Sep 2024 06:58:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/FEuIsXxhzQ0/upload/2db5e041a77d989a13e43122c58b13fc.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A <strong>hostname</strong> is a human-friendly name given to a computer. It is a unique identifier that allows us to identify the machine in various network communications, making it easier to locate and manage devices.</p>
<p>Type:</p>
<pre><code class="lang-bash">hostname
</code></pre>
<p>To see where it is stored, type:</p>
<pre><code class="lang-bash">cat /etc/hostname
</code></pre>
<p>To get the hostname and additional information about your machine:</p>
<pre><code class="lang-bash">hostnamectl
</code></pre>
<p>To change the hostname, login as root user or use the <code>sudo</code> command:</p>
<pre><code class="lang-bash">sudo hostnamectl set-hostname my-private-workstation
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Restart your terminal window since the new settings will not show up.</div>
</div>

<p>If you do not want to restart your terminal, you can force the current terminal to be changed by typing (assuming you use bash):</p>
<pre><code class="lang-bash"><span class="hljs-built_in">exec</span> bash
</code></pre>
<p>Verify the hostname was changed:</p>
<pre><code class="lang-bash">cat /etc/hostname
</code></pre>
<p>Check the content of the <code>/cat/hosts</code> file</p>
<pre><code class="lang-bash">cat /etc/hosts
</code></pre>
<p>Even though the <code>hostnamectl</code> command allows us to set the new hostname, it does not update the <code>/etc/hosts</code> file. This is optional, but highly recommended.</p>
<p>To update the <code>/etc/hosts</code> file, use the <code>vim</code> command:</p>
<pre><code class="lang-bash">sudo vim /etc/hosts/
</code></pre>
<p>To ping this instance, run:</p>
<pre><code class="lang-bash">ping my-private-laptop
</code></pre>
<h2 id="heading-references">References:</h2>
<ol>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=91dNq4C6260&amp;list=PLT98CRl2KxKHKd_tH3ssq0HPrThx2hESW&amp;index=69">Linux Crash Course - Setting the Hostname of your Linux Workstation or Server</a></p>
</li>
<li><p><a target="_blank" href="https://phoenixnap.com/kb/ubuntu-20-04-change-hostname">How to Change Hostname on Ubuntu</a></p>
</li>
<li><p><a target="_blank" href="https://www.redhat.com/sysadmin/configure-hostname-linux">How to configure a hostname on a Linux system</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Understanding File and Directory Permissions]]></title><description><![CDATA[File permissions are core to the security model used by Linux systems. The file permission in Linux specifies how much power each user has over a given file or directory.
Viewing Permissions
There are two ways of viewing file permissions in Linux:

U...]]></description><link>https://karlygash-yakiyayeva.dev/understanding-file-and-directory-permissions</link><guid isPermaLink="true">https://karlygash-yakiyayeva.dev/understanding-file-and-directory-permissions</guid><category><![CDATA[Linux]]></category><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[permissions]]></category><dc:creator><![CDATA[Karlygash Yakiyayeva]]></dc:creator><pubDate>Mon, 05 Aug 2024 10:14:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/05HLFQu8bFw/upload/cea2d41d17884c8482fb91145793a808.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>File permissions are core to the security model used by Linux systems. The file permission in Linux specifies how much power each user has over a given file or directory.</p>
<h2 id="heading-viewing-permissions">Viewing Permissions</h2>
<p>There are two ways of viewing file permissions in Linux:</p>
<ol>
<li><p>Using a graphical user interface (GUI) by <strong><em>right-clicking the file/directory -&gt; Properties -&gt; Permissions</em></strong></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720481106296/0c75ec59-d3ca-4fac-8c5b-1b642b32fc73.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Using a command-line interface (CLI) by typing <code>ls -l</code> command.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720563921328/c7437843-2787-4982-8cc6-f4cc2678a2db.png" alt class="image--center mx-auto" /></p>
<p> The output of this command is explained further.</p>
</li>
</ol>
<h3 id="heading-permission-groups">Permission Groups</h3>
<p>Each file and directory in Linux can be accessed or modified by three different classes of users.</p>
<ol>
<li><p><strong>User (u)</strong>: The user who owns the file.</p>
</li>
<li><p><strong>Group</strong> : The group that the file belongs to.</p>
</li>
<li><p><strong>Others</strong>: All other users.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720453483726/3eedc979-58e7-4b91-873a-a600d0f0649e.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-permissions-types">/Permissions Types</h2>
<p>Each file or directory has three basic permission types:</p>
<ol>
<li><p><strong>Read</strong> (r) - allows to read the contents of the file.</p>
</li>
<li><p><strong>Write</strong> (w) - allows to write or modify a file or directory.</p>
</li>
<li><p><strong>Execute</strong> (x) - allows to execute a file or view the contents of a directory.</p>
</li>
</ol>
<h2 id="heading-how-to-read-file-permissions">How to Read File Permissions</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720481597854/3c9284b3-38dd-4887-8461-2b14d28a4d02.png" alt class="image--center mx-auto" /></p>
<p>The permissions are represented as a string of 10 characters, like <code>-rw-rw-r--</code>.</p>
<p>These characters can be broken down as follows:</p>
<ul>
<li><p>The first character indicates the type of file</p>
<ul>
<li><p><code>-</code> for regular files,</p>
</li>
<li><p><code>d</code> for directories,</p>
</li>
<li><p><code>l</code> for symbolic links,</p>
</li>
</ul>
</li>
<li><p>The next three characters indicate the permissions for the user/owner of the file/directory (<code>rw-</code> read, write).</p>
</li>
<li><p>The following three characters indicate the permissions for the group the file/directory belongs to (<code>rw-</code> read, write).</p>
</li>
<li><p>The last three characters indicate the permissions for others (<code>r--</code> read).</p>
</li>
</ul>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Permission string</td><td>directory</td><td>file</td></tr>
</thead>
<tbody>
<tr>
<td><strong>read (r)</strong></td><td>The user can read the contents of the directory. In other words, he can view the listing of the directory.</td><td>The user can read the contents of the file.</td></tr>
<tr>
<td><strong>write (w)</strong></td><td>The user can add/remove files to/from the directory.</td><td>The user can write content to the file.</td></tr>
<tr>
<td><strong>execute (x)</strong></td><td>The user can go inside the directory. The user cannot read the directory's contents if it is not set.</td><td>The user can execute the file as if it were a program/script.</td></tr>
</tbody>
</table>
</div><p>So, the file above <code>weather-report.service</code> is owned by the user <code>vagrant</code> and belongs to the group <code>vagrant</code> . Its owner <code>vagrant</code> and all group members <code>vagrant</code> can read and write to the file while all others can only read the file.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Many distributions in Linux create a group when a user is created and by default, all the folders and files created inside the home directory will be owned by the user and the group.</div>
</div>

<h2 id="heading-changing-permissions">Changing Permissions</h2>
<p>Changing permissions in Linux can be done using the <code>chmod</code> command in 2 ways:</p>
<ol>
<li><p>Symbolic mode;</p>
</li>
<li><p>Numeric (Octal) Mode:</p>
</li>
</ol>
<h3 id="heading-symbolic-mode">Symbolic Mode</h3>
<p>Symbolic mode allows to change file and directory permissions using symbolic representations of the</p>
<ul>
<li><p>User classes</p>
<ul>
<li><p>User <strong>(u)</strong>,</p>
</li>
<li><p>Group <strong>(g)</strong>,</p>
</li>
<li><p>Others <strong>(o)</strong></p>
</li>
<li><p>All (user, group, and others) <strong>(a)</strong></p>
</li>
</ul>
</li>
<li><p>Permissions types</p>
<ul>
<li><p>Read <strong>(r)</strong>,</p>
</li>
<li><p>Write <strong>(w)</strong>,</p>
</li>
<li><p>Execute <strong>(x)</strong>.</p>
</li>
</ul>
</li>
<li><p>Operators</p>
<ul>
<li><p><code>+</code>: Adds the specified permissions to the existing ones without altering other permissions.</p>
</li>
<li><p><code>-</code>: Removes the specified permissions.</p>
</li>
<li><p><code>=</code>: Sets the specified permissions and removes any permissions not listed.</p>
</li>
</ul>
</li>
</ul>
<p>To add read, write, and execute permissions for the user:</p>
<pre><code class="lang-bash">chmod u+rwx file
</code></pre>
<p>To set read and write permissions for the group:</p>
<pre><code class="lang-bash">chmod g=rw file
</code></pre>
<p>To remove execute permission for others:</p>
<pre><code class="lang-bash">chmod o-x file
</code></pre>
<h3 id="heading-numeric-mode">Numeric Mode</h3>
<p>When <code>chmod</code> command is used with numerical values three digits are specified. The first digit is for the user, the second is for the group and the third is for others. Each digit represents a different set of permissions. The digits are calculated by adding up the values of:</p>
<ul>
<li><p>r (read) = <code>4</code>,</p>
</li>
<li><p>w (write) = <code>2</code>,</p>
</li>
<li><p>x (execute) = <code>1</code>,</p>
</li>
<li><p>no permission = <code>0</code></p>
</li>
</ul>
<p>The numbers are summed up and depicted by one number. Therefore, the possibilities are:</p>
<ul>
<li><p><code>7</code> - for read, write, and execute permission.</p>
</li>
<li><p><code>6</code> - for read and write privileges.</p>
</li>
<li><p><code>5</code> - for read and execute privileges.</p>
</li>
<li><p><code>4</code> - for read privileges.</p>
</li>
</ul>
<p>To give the owner read and write permissions, the group read permissions, and no rights for all others, type.</p>
<pre><code class="lang-bash">chmod 640 filename
</code></pre>
<p>To change the permission for every file all in one shot:</p>
<pre><code class="lang-bash">chmod 640 Download/*
</code></pre>
<h2 id="heading-changing-ownership">Changing Ownership</h2>
<p>Aside from changing file and directory permissions, we can also change <strong>user ownership</strong> and <strong>group ownership</strong> of the file and directory. Both of these tasks require superuser privileges.</p>
<h3 id="heading-changing-the-owner">Changing the Owner</h3>
<p>To change the owner of a file or directory:</p>
<pre><code class="lang-bash">sudo chown username /Downloads/
</code></pre>
<h3 id="heading-changing-the-owner-and-group">Changing the Owner and Group</h3>
<p>To change both the owner and the group:</p>
<pre><code class="lang-bash">sudo chown username:groupname filename
</code></pre>
<h3 id="heading-changing-only-the-group">Changing Only the Group</h3>
<p>To change only the group:</p>
<pre><code class="lang-bash">sudo chown :groupname filename
</code></pre>
<h2 id="heading-special-permissions">Special Permissions</h2>
<p>In addition to the standard read, write, and execute permissions, Linux also supports special permissions that provide additional security and functionality features for files and directories.</p>
<ol>
<li><p><strong>Setuid (Set User ID)</strong> - When set on an executable file, the file runs with the permissions of the file's owner, not the person running it.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720567131692/97b5a6fc-3793-438e-a365-3f0d8dc4b960.png" alt class="image--center mx-auto" /></p>
<p> In order <code>setuid</code> to work, the file should be <strong><em>executable</em></strong> and owned by <code>root</code> in order to grant temporary elevated privileges to the person running it.</p>
</li>
<li><p><strong>Setgid (Set Group ID)</strong> - Similar to <code>setuid</code>, the <code>setgid</code> permission allows a user to execute a file with the permissions of the file's group, rather than the permissions of the user executing the file. <code>setgid</code> is often used for directories to ensure that files created within the directory inherit the group ownership of the directory.</p>
</li>
<li><p><strong>Sticky Bit</strong>: When the sticky bit is set on a directory, it restricts the deletion or renaming of files within that directory to only the file owner, the directory owner, or the root user, even if other users have write permissions on the directory. This is commonly used on directories like <code>/tmp</code>, where many users have write access, to prevent users from deleting or renaming each other's files. The sticky bit is more useful in shared directories where multiple users have write access.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720568463953/ad9360c0-2f48-4f5f-8659-4e2bbae32d75.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<h2 id="heading-references">References:</h2>
<ol>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=4e669hSjaX8&amp;list=PLT98CRl2KxKHKd_tH3ssq0HPrThx2hESW&amp;index=21">Linux Crash Course - Understanding File &amp; Directory Permissions</a></p>
</li>
<li><p><a target="_blank" href="https://www.redhat.com/sysadmin/linux-file-permissions-explained">Linux file permissions explained</a></p>
</li>
<li><p><a target="_blank" href="https://www.linuxfoundation.org/blog/blog/classic-sysadmin-understanding-linux-file-permissions">Classic SysAdmin: Understanding Linux File Permissions</a></p>
</li>
<li><p><a target="_blank" href="https://phoenixnap.com/kb/linux-file-permissions">Linux Permissions Explained</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Unix and Linux Guide: How to Use the Find Command]]></title><description><![CDATA[The find command in Unix is a powerful utility used for searching files and directories based on various criteria such as name, type, size, permissions, modification time, and more. It recursively descends into directory trees and matches conditions ...]]></description><link>https://karlygash-yakiyayeva.dev/unix-and-linux-guide-how-to-use-the-find-command</link><guid isPermaLink="true">https://karlygash-yakiyayeva.dev/unix-and-linux-guide-how-to-use-the-find-command</guid><category><![CDATA[Devops]]></category><category><![CDATA[Linux]]></category><category><![CDATA[unix]]></category><category><![CDATA[FIND]]></category><dc:creator><![CDATA[Karlygash Yakiyayeva]]></dc:creator><pubDate>Thu, 04 Jul 2024 10:54:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/GnY_mW1Q6Xc/upload/b96f51a7ca14b0f7b55909dd813cd84f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The <code>find</code> command in Unix is a powerful utility used for searching files and directories based on various criteria such as name, type, size, permissions, modification time, and more. It recursively descends into directory trees and matches conditions specified by the user. The basic syntax is:</p>
<pre><code class="lang-bash">find [path] [expression]
</code></pre>
<ul>
<li><p><strong>[path]</strong>: The directory where the search begins. If omitted, it defaults to the current directory (<code>.</code>).</p>
</li>
<li><p><strong>[expression]</strong>: Criteria for searching (e.g., name, type, size, etc.).</p>
</li>
</ul>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">The default path of the find command is the current directory. The default expression is the print</div>
</div>

<h2 id="heading-hands-on-exercise-overview"><strong>Hands-on Exercise Overview</strong></h2>
<p>This hands-on exercise shows how to use <code>find</code> command and its different options to search for files and directories on Ubuntu 22.04. It focuses on basic file searching, advanced searching techniques, and executing commands on found files.</p>
<h2 id="heading-hands-on-exercise"><strong>Hands-on Exercise</strong></h2>
<ol>
<li><p>To search for a file with a specific <strong><em>name</em></strong>, use the <code>-name</code> option:</p>
<pre><code class="lang-bash"> sudo find / -name <span class="hljs-string">"*fish*"</span>
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719702961139/da4e652d-bb32-44d4-afe6-3408eef551d9.png" alt class="image--center mx-auto" /></p>
<p> This command searches the entire filesystem (<code>/</code>) for files and directories whose names contain the substring "fish".</p>
<p> <code>sudo</code> provides root access, ensuring no permission issues, and produces a clean output stream of matching file names. <code>head</code> receives a continuous and uninterrupted stream of matching filenames correctly displaying the first 5 lines from this stream.</p>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">The search with <code>-name</code> option is case-sensitive. To make the search case-insensitive, use the <code>-iname</code> option instead.</div>
 </div>
</li>
<li><p>To search for files of a specific <strong><em>type</em></strong>, use the <code>-type</code> option:</p>
<pre><code class="lang-bash"> sudo find /snap name <span class="hljs-string">"cat"</span> -<span class="hljs-built_in">type</span> f
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719730540096/f19122af-1c3f-4852-a486-fbc0f02535ed.png" alt class="image--center mx-auto" /></p>
<p> To search for <em>both</em> files and directories simultaneously, use <code>-o</code> operator which stands for OR operator:</p>
<pre><code class="lang-bash"> sudo find / -name <span class="hljs-string">"vagrant"</span> \( -<span class="hljs-built_in">type</span> f -o -<span class="hljs-built_in">type</span> d\) -<span class="hljs-built_in">exec</span> ls -ld {} \;
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719732504912/825182d9-7e74-4c0a-b613-579dffa7bab5.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To find files of a specific <strong><em>size</em></strong>, use the <code>-size</code> option:</p>
<pre><code class="lang-bash"> sudo find /var/<span class="hljs-built_in">log</span> -size 100c
 sudo find /var/<span class="hljs-built_in">log</span> -size -1K
 sudo find /var/<span class="hljs-built_in">log</span> -size +100M
 sudo find /var/<span class="hljs-built_in">log</span> -size 2G
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719842107986/a3877318-6d3d-478b-9123-a59170ee229f.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To search for files based on their modification, access, and change times use <code>-mtime</code>, <code>-atime</code>, and <code>-ctime</code> options:</p>
<pre><code class="lang-bash"> find /path/to/search -mtime +n
 find /path/to/search -atime -n
 find /path/to/search -ctime n
</code></pre>
<ul>
<li><p><code>-mtime</code> - Modification time, when the file content was last modified;</p>
</li>
<li><p><code>-atime</code> - Access time, when the file was last accessed;</p>
</li>
<li><p><code>-ctime</code> - Change time, when the file's metadata or content was last changed;</p>
</li>
<li><p><code>+n</code> - more than <code>n</code> days ago;</p>
</li>
<li><p><code>-n</code> - in the last <code>n</code> days;</p>
</li>
<li><p><code>n</code> - exactly <code>n</code> days ago;</p>
</li>
</ul>
</li>
</ol>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719845638270/5f257499-d141-4158-81a4-2f2e6fdffa3b.png" alt class="image--center mx-auto" /></p>
<ol start="5">
<li><p>To find all <code>.conf</code> files in <code>/etc</code> and copy them to <code>~/backup/etc</code>, use a new option <code>-exec</code> which executes a command against all files found in the result.</p>
<pre><code class="lang-bash"> sudo find /etc -<span class="hljs-built_in">type</span> f -name <span class="hljs-string">"*.conf"</span> -<span class="hljs-built_in">exec</span> cp {} ~/backup/etc/ \;
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719848187060/e45aa2e9-2042-488d-9cd1-9c61a8e4740a.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<ul>
<li><p><code>-exec</code> executes the <code>cp</code> command against every item in the result;</p>
</li>
<li><p><code>{}</code> - a placeholder for the actual item itself. So every time a <code>find</code> command finds something, it puts the result here;</p>
</li>
<li><p><code>\;</code> terminates the <code>find</code> command. You can also use <code>+</code> instead of <code>\;</code> sign as a terminator. You should terminate the <code>find</code> command anytime you use the <code>-exec</code> option.</p>
</li>
</ul>
<ol start="6">
<li><p>To change the permissions of several files to be readable and writable simultaneously, type:</p>
<pre><code class="lang-bash"> find ~ -<span class="hljs-built_in">type</span> f -name <span class="hljs-string">"*.txt"</span> -<span class="hljs-built_in">exec</span> chmod 600 {} \;
 find ~ -name <span class="hljs-string">"*.txt"</span> -<span class="hljs-built_in">exec</span> ls -ld {} +
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719852048206/6c0c5810-bd9f-407f-b41a-71235dcec0f1.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<h2 id="heading-best-practices">Best Practices</h2>
<ol>
<li><p><strong>Use Quotes for Patterns</strong>: Always use quotes around patterns to avoid shell interpretation.</p>
</li>
<li><p><strong>Combine Expressions</strong>: Use multiple expressions to narrow down your search.</p>
</li>
<li><p><strong>Test Before Executing</strong>: Use <code>-print</code> to test your <code>find</code> command before adding <code>-exec</code>.</p>
</li>
</ol>
<h2 id="heading-references">References:</h2>
<ol>
<li><p><a target="_blank" href="https://opensource.com/article/18/4/how-use-find-linux">How to use FIND in Linux</a></p>
</li>
<li><p><a target="_blank" href="https://www.man7.org/linux/man-pages/man1/find.1.html">find(1) — Linux manual page</a></p>
</li>
<li><p><a target="_blank" href="https://www.redhat.com/sysadmin/linux-find-command">10 ways to use the Linux find command</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=skTiK_6DdqU">Linux Crash Course - The find command</a>-</p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[The /etc/fstab file in Linux]]></title><description><![CDATA[The fstab file in Linux stands for "filesystem table" and is commonly found in the /etc directory. It typically lists all available disk partitions and other types of file systems, their mountpoints and mount options. fstab is meant to be only read b...]]></description><link>https://karlygash-yakiyayeva.dev/the-etcfstab-file-in-linux</link><guid isPermaLink="true">https://karlygash-yakiyayeva.dev/the-etcfstab-file-in-linux</guid><category><![CDATA[Linux]]></category><category><![CDATA[Devops]]></category><category><![CDATA[System administration]]></category><category><![CDATA[sysops]]></category><category><![CDATA[mount]]></category><dc:creator><![CDATA[Karlygash Yakiyayeva]]></dc:creator><pubDate>Fri, 03 May 2024 07:53:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/lRoX0shwjUQ/upload/ae5c7404236054d11380b27f690aa80c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a target="_blank" href="https://man7.org/linux/man-pages/man5/fstab.5.html">The <code>fstab</code> file</a> in Linux stands for "filesystem table" and is commonly found in the <code>/etc</code> directory. It typically lists all available disk partitions and other types of file systems, their mountpoints and mount options. <code>fstab</code> is meant to be only read by programs and never written except by the system administrator. It is read by the <code>mount</code> command, which happens automatically at boot time to determine the overall file system structure, and thereafter when a user executes the <code>mount</code> command to modify that structure. The system administrator has to properly create and maintain this file.</p>
<h2 id="heading-how-fstab-is-structured">How fstab is Structured</h2>
<p>The table itself is a 6-column structure, where each column designates a specific parameter and must be set up in the correct order. The fields of the table are as follows from left to right:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713380783208/3074ceca-b84b-497e-acb5-8f1c4adc6f26.png" alt class="image--center mx-auto" /></p>
<ol>
<li><p><strong>Block device</strong> - the device that should be mounted. The most typical way to reference a block device is by using its location <code>/dev/sda1</code> or by using its <code>LABEL</code> or <code>UUID</code> (Universal Unique IDentifier). The latter is the preferred method since it guarantees to univocally reference a filesystem. On <code>GPT</code> partitioned disks it’s also possible to reference a filesystem by using <code>PARTUUID</code> or <code>PARTLABEL</code>.</p>
</li>
<li><p><strong>Mount point</strong> - specifies the <code>mountpoint</code> for the filesystem. It is a directory in the system that should be used to access its content. This should always be provided except if the block device is used as a swap. In that case <code>"none"</code> should be used.</p>
</li>
<li><p><strong>Filesystem type</strong> - the type of filesystem in use on the raw block device or partition. Linux supports many filesystem types: <code>ext4</code>, <code>xfs</code>, <code>btrfs</code>, <code>f2fs</code>, <code>vfat</code>, <code>ntfs</code>, <code>hfsplus</code>, <code>tmpfs</code>, <code>sysfs</code>, <code>proc</code>, <code>iso9660</code>, <code>udf</code>, <code>squashfs</code>, <code>nfs</code>, <code>cifs</code>, and many more.</p>
</li>
<li><p><strong>Mount options -</strong> a list of options when mounting the filesystem. To use the default set of mount options we specify <code>defaults</code> as a value. The kernel default is usually <code>rw, suid, dev, exec, auto, nouser, async</code>.</p>
<ul>
<li><p><strong>suid</strong> - respect SETUID and SETGID bits<a target="_blank" href="https://linuxconfig.org/how-to-use-special-permissions-the-setuid-setgid-and-sticky-bits">;</a></p>
</li>
<li><p><strong>exec</strong> - allow executing binaries and scripts;</p>
</li>
<li><p><strong>noauto</strong> - do not mount when <code>mount -a</code> is given (e.g., at boot time);</p>
</li>
<li><p><strong>user</strong> - allow a user to mount;</p>
</li>
<li><p><strong>nouser</strong> - make the filesystem not mountable by a standard user;</p>
</li>
<li><p><strong>async</strong> - perform I/O operations on the filesystem asynchronously;</p>
</li>
<li><p><strong>owner</strong> - allow a device owner to mount;</p>
</li>
<li><p><strong>nofail</strong> - do not report errors for this device if it does not exist.</p>
</li>
</ul>
</li>
<li><p><strong>Dump</strong> - enable (1) or disable (0) the backing up of the device/partition. The value is used by the dump backup program (if installed) to know what filesystem should be dumped. Usually, this field is set to 0, which disables it.</p>
</li>
<li><p><strong>Pass</strong> - establishes the order by which another utility, <code>fsck</code> should check filesystems on boot. <code>0</code> means that <code>fsck</code> will not check the filesystem. Numbers higher than this represent the check order. The root filesystem should be set to <code>1</code> and other partitions set to <code>2</code>.</p>
</li>
</ol>
<p>An example of <code>fstab</code> table on a Vagrant Ubuntu virtual machine.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714214333121/55d465cb-3a6d-4cfe-81d9-5b13c887bb6d.png" alt class="image--center mx-auto" /></p>
<p>Each filesystem is described on a separate line. Lines starting with '#' are comments. Blank lines are ignored. Fields on each line are separated by tabs or spaces.</p>
<h2 id="heading-hands-on-exercise-overview">Hands-on Exercise Overview</h2>
<p>The main purpose of this hands-on exercise is to gain practical experience in configuring filesystem mounts using the <code>/etc/fstab</code> file. This hands-on shows how to add a new entry to the <code>/etc/fstab</code> file to mount a filesystem and tests the configuration by mounting and unmounting the filesystem.</p>
<h2 id="heading-hands-on-exercise">Hands-on Exercise</h2>
<ol>
<li><p>Run the command that allows us to find out whether there are storage volumes that are not mounted:</p>
<pre><code class="lang-bash"> lsblk
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714215121280/64a8af7b-3283-404d-a494-5fca7964afc3.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To get a listing of mounted devices and find out whether our disk device is mounted or not, run:</p>
<pre><code class="lang-bash"> mount | grep sdc
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714215431838/18ed3963-335b-4a36-94fe-eac1ed3a6d1a.png" alt class="image--center mx-auto" /></p>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">Choose <code>/mnt</code> directory for permanent storage to mount the disk.</div>
 </div>
</li>
<li><p>To add a new entry to the end of the <code>/etc/fstab</code> file:</p>
<pre><code class="lang-bash"> sudo vim /etc/fstab
 /dev/sdc /mnt/mydisk ext4 defaults 0 0
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714215652182/33abc3b5-8582-4002-831a-45ad63aab8da.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To create the directory for the storage volume to be mounted:</p>
<pre><code class="lang-bash"> sudo mkdir /mnt/mydisk
</code></pre>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">Without this directory exists, the <code>fstab</code> file would not be able to find it and it will cause the problem.</div>
 </div>
</li>
<li><p>To mount the device <em>manually</em>, run:</p>
<pre><code class="lang-bash"> sudo mount /mnt/mydisk
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714217170807/8afb03b6-7095-4bb6-9c3e-cc9cac543777.png" alt class="image--center mx-auto" /></p>
<p> This command assumes that the details of what to mount (like the device or remote filesystem) are already specified in the <code>/etc/fstab</code> file. The target directory <code>/mnt/mydisk</code> was found in the <code>fstab</code> file and the system knows that this directory is associated with the device <code>/dev/sdc</code>. Thus, the <code>mount</code> command was simplified.</p>
</li>
<li><p>To unmount the device, run:</p>
<pre><code class="lang-bash"> sudo unmount /mnt/mydisk
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714217040023/04351818-9295-47ac-a19a-b8303dd03f62.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To ensure the new entry mounts correctly by simulating the boot-time mounting process, run:</p>
<pre><code class="lang-bash"> sudo mount -a
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714216100289/39b60397-8e86-42d0-b283-ca81eb103a14.png" alt class="image--center mx-auto" /></p>
<p> This command <em>automatically</em> mounts all filesystems specified in the <code>/etc/fstab</code> file without requiring further human interaction. By running this command, you instruct the system to read <code>/etc/fstab</code> and mount all listed filesystems according to the defined parameters, making it useful for ensuring all necessary filesystems are mounted, especially after a system reboot.</p>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">The option <code>noauto</code> in the mount options field of the <code>fstab</code> file does not mount when <code>mount -a</code> is given (e.g., at boot time). There are several reasons to use this option. 1. It allows you to control when these filesystems are mounted. 2. It simplifies the mount command since there is no need for the device name, and only the target directory can be referred to.</div>
 </div>
</li>
<li><p>To find out the UUID of the storage volume, run:</p>
<pre><code class="lang-bash"> sudo blkid
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714218549826/c4ecda5b-3cc1-4630-82b7-4c3b10c45481.png" alt class="image--center mx-auto" /></p>
<p> It is recommended to use the UUID (Universally Unique Identifier) of a storage volume instead of the device path (like <code>/dev/sdc</code>) in the <code>/etc/fstab</code> file, because UUIDs are unique and remain constant while device paths can change depending on the order in which devices are detected by the system.</p>
</li>
</ol>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">It is highly recommended to use the option <code>ro</code> since it prohibits writing or deleting the storage volume.</div>
</div>

<h2 id="heading-references">References:</h2>
<ol>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=A7xH74o6kY0">Linux Crash Course - The /etc/fstab file</a></p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Fstab">fstab</a></p>
</li>
<li><p><a target="_blank" href="https://man7.org/linux/man-pages/man5/fstab.5.html">fstab(5) — Linux manual page</a></p>
</li>
<li><p><a target="_blank" href="https://www.redhat.com/sysadmin/etc-fstab">An introduction to the Linux /etc/fstab file</a></p>
</li>
<li><p><a target="_blank" href="https://linuxconfig.org/how-fstab-works-introduction-to-the-etc-fstab-file-on-linux">How fstab works – introduction to the /etc/fstab file on Linux</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Understanding Systemd Timers]]></title><description><![CDATA[Systemd is a software suite that provides a standard process for controlling what programs run when a Linux system boots up. It starts the core programs running and a journal of system activity, the network stack, a cron-style job scheduler, user log...]]></description><link>https://karlygash-yakiyayeva.dev/understanding-systemd-timers</link><guid isPermaLink="true">https://karlygash-yakiyayeva.dev/understanding-systemd-timers</guid><category><![CDATA[timers]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Devops]]></category><category><![CDATA[systemd]]></category><category><![CDATA[cronjob]]></category><dc:creator><![CDATA[Karlygash Yakiyayeva]]></dc:creator><pubDate>Tue, 16 Apr 2024 09:58:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/KYxXMTpTzek/upload/6eac3211f34f90d024c9a5f14b20e0bb.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a target="_blank" href="https://karlygash-yakiyayeva.dev/understanding-systemd-services">Systemd</a> is a software suite that provides a standard process for controlling what programs run when a Linux system boots up. It starts the core programs running and a journal of system activity, the network stack, a cron-style job scheduler, user logins, and many other jobs.</p>
<p><a target="_blank" href="https://silentlad.com/how-to-use-systemd-timers-(cronjob-alternative)">Systemd timers</a> are a part of this <code>systmed</code> suite and they enable us to schedule tasks to be executed at specified times or intervals, similar to <a target="_blank" href="https://karlygash-yakiyayeva.dev/scheduling-tasks-with-cron">cron jobs</a> but with more features and tight integration with the rest of the <code>systemd</code> ecosystem.</p>
<h2 id="heading-systemd-timers-or-cron-jobs">Systemd Timers or Cron Jobs</h2>
<ol>
<li><p>Cron is more of a stand-alone thing whereas <code>systemd</code> timers are part of <code>systemd</code>. Therefore <code>systemd</code> timers can be used only on distributions with <code>systemd</code> systems while cron jobs can be used on distributions either with <code>systemd</code> systems or <code>non-systemd</code> systems.</p>
</li>
<li><p>Systemd timers have additional features such as support for complex calendar-based events, built-in support for catching up on missed jobs, a built-in mechanism for dependency management or condition checks before job execution, and integration with <code>systemd’s</code> journal which provides centralized and unified logging etc.</p>
</li>
<li><p>Additional features of <code>systemd</code> timers come with added complexity. Therefore, <code>systemd</code> timers are a bit more involved meaning more to learn while cron jobs are much simpler to understand and implement.</p>
</li>
</ol>
<p>Which one to use depends on the complexity of the task and which of the two solutions is a better fit for your project on a case-by-case basis.</p>
<h2 id="heading-components-of-systemd-timers">Components of Systemd Timers</h2>
<p>To create a <code>systemd</code> timer two files are required: a <code>.timer</code> file to schedule the task and a <code>.service</code> file for the task.</p>
<ul>
<li><p><strong>Timer units</strong> are the actual timer definitions. They define when and how often a task should be executed. The timer units have a <code>.timer</code> extension and are typically stored in the <code>/etc/systemd/system</code> directory. An example of <code>weather-report.timer</code> unit file is given below.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713041691854/74cd540c-7718-4ae9-b061-7ec9ca8ac7ac.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Service units</strong> are the tasks that are executed when the timer is triggered. Service units have a <code>.service</code> extension and are typically stored in the <code>/etc/systemd/system</code> directory. An example of <code>weather-report.service</code> unit file is provided below.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713041306173/4127918f-ae0e-42f0-a7b7-5c8208c87380.png" alt class="image--center mx-auto" /></p>
</li>
</ul>
<p>When you have a <code>.service</code> file with the same name as the <code>.timer</code> file in the directory, with the only difference being the file extension, <code>systemd</code> automatically considers them to be related. Usually, for each timer, there is a corresponding service file that gets executed when the timer triggers.</p>
<h2 id="heading-types-of-timers">Types of Timers</h2>
<ul>
<li><p><strong>Real-time timers</strong> are based on the actual real-world clock time. They can be set to trigger at specific times, such as "every day at 2:00 AM".</p>
</li>
<li><p><strong>Monotonic timers</strong> are based on a timer relative to a certain point, such as "15 minutes after boot".</p>
</li>
</ul>
<h2 id="heading-hands-on-exercise-overview">Hands-on Exercise Overview</h2>
<p>Understanding <code>systemd</code> timers involve knowing how to create and manage them. This hands-on exercise shows how to create a <code>systemd</code> timer that will run the <code>wall</code> command automatically on a specific schedule.</p>
<h2 id="heading-hands-on-exercise">Hands-on Exercise</h2>
<ol>
<li><p>Create a new <code>weather-report.service</code> unit file:</p>
<pre><code class="lang-bash"> sudo vim /etc/systemd/system/weather-report.service
</code></pre>
</li>
<li><p>Copy and paste the following code into the file and save it:</p>
<pre><code class="lang-bash"> [Unit]
 Description=Weather Report Service
 After=network-online.target
 Wants=network-online.target

 [Service]
 ExecStart=/bin/sh -c <span class="hljs-string">'sudo wall $(curl wttr.in?format=3)'</span>

 [Install]
 WantedBy=default.target
</code></pre>
<p> This simple file executes the <code>wall</code> command, which stands for "write to all". The <code>wall</code> command sends a message to all users currently logged into the system and the message is supposed to be the output of <code>curl wttr.in?format=3</code>, which queries the <code>wttr.in</code> service for weather information in a brief format. This can be particularly useful for system administrators who need to notify users about system maintenance, reboots, or other important events.</p>
</li>
<li><p>Refresh <code>systemd</code> so that it’s aware of the fact we added a new service file:</p>
<pre><code class="lang-bash"> sudo systemctl daemon-reload
</code></pre>
</li>
<li><p>Now, when we want to send a weather report to every user on the system, all we need to do is start the <code>systemd</code> service for it:</p>
<pre><code class="lang-bash"> sudo systemctl start weather-report.service
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713256851445/83d0ff87-2a36-4225-a647-849b9905c812.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Create a new <code>weather-report.timer</code> unit file the type of which will be a timer:</p>
<pre><code class="lang-bash"> sudo vim /etc/systemd/system/weather-report.timer
</code></pre>
</li>
<li><p>Copy and paste the following code into the file and save it:</p>
<pre><code class="lang-bash"> [Unit]
 Description=Weather Report Service

 [Timer]
 OnCalendar=Mon..Fri 08:32
 Persistent=<span class="hljs-literal">true</span>

 [Install]
 WantedBy=timers.target
</code></pre>
<p> Under the timer section, we have <code>OnCalendar</code> here. We’re giving it a range starting with Monday and ending with Friday. Also, we’re setting it for 08:32 am, which means the timer will trigger <code>weather-report.service</code> file every weekday at 08:32 am.</p>
<p> If the server is down for any reason the timer won’t trigger. Enabling the <code>Persistent=true</code> option, allows the task to run once the server starts up next in case the <code>OnCalendar</code> time is missed.</p>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">The timer will look for a file name that’s the same as its own but with a <code>.service</code> extension instead of a <code>.timer</code> extension. Therefore we don’t tell the timer which service file to start, it already knows what it is looking for. All we have to do is match the naming scheme.</div>
 </div>

<p> In the install section, targets are another type of unit file, and when you link them like this, the current file will inherit specific characteristics from the target.</p>
</li>
<li><p>Refresh <code>systemd</code> once more so that it knows we added a new timer unit file:</p>
<pre><code class="lang-bash"> sudo systemctl daemon-reload
</code></pre>
</li>
<li><p>Finally, start and enable the timer with one single command:</p>
<pre><code class="lang-bash"> sudo systemctl <span class="hljs-built_in">enable</span> --now weather-report.timer
</code></pre>
</li>
<li><p>Check the status of your timer:</p>
<pre><code class="lang-bash"> systemctl status weather-report.timer
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713257695924/6860f5d7-0d8a-462f-ada0-b2c2388bd025.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<h2 id="heading-references">References:</h2>
<ol>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=n6BuUgkZ5T0">Automate Your Tasks with systemd Timers: A Step-by-Step Guide</a></p>
</li>
<li><p><a target="_blank" href="https://silentlad.com/how-to-use-systemd-timers-(cronjob-alternative)">How to use systemd timers (cronjob alternative)</a></p>
</li>
<li><p><a target="_blank" href="https://karlygash-yakiyayeva.dev/understanding-systemd-services">Understanding Systemd Services</a></p>
</li>
<li><p><a target="_blank" href="https://www.freedesktop.org/software/systemd/man/latest/systemd.time.html">systemd.time format</a></p>
</li>
<li><p><a target="_blank" href="https://silentlad.com/systemd-timers-oncalendar-(cron)-format-explained">Systemd timers onCalendar (cron) format explained</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Understanding Systemd Services]]></title><description><![CDATA[The init system is the very first process that starts on the system and its job is to schedule and manage all other processes on the system. It is also referred to as PID 1 short for process id 1. When a process such as Apache or Nginx is started on ...]]></description><link>https://karlygash-yakiyayeva.dev/understanding-systemd-services</link><guid isPermaLink="true">https://karlygash-yakiyayeva.dev/understanding-systemd-services</guid><category><![CDATA[Linux]]></category><category><![CDATA[Devops]]></category><category><![CDATA[systemd]]></category><category><![CDATA[init]]></category><category><![CDATA[#LinuxAdministrator]]></category><category><![CDATA[sysops]]></category><dc:creator><![CDATA[Karlygash Yakiyayeva]]></dc:creator><pubDate>Mon, 15 Apr 2024 06:12:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/mVPkezDvRy8/upload/3629a4a893d9f1d3796834dd7f7df0b6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The <code>init</code> system is the very first process that starts on the system and its job is to schedule and manage all other processes on the system. It is also referred to as PID 1 short for process id 1. When a process such as Apache or Nginx is started on a Linux server, the request to start that process is sent to the <code>init</code> system which then starts it up.</p>
<p><code>systemd</code> is a newer init system with a more modern approach to process management. It can enable the administrator to schedule tasks to run when specific criteria are met and also to ensure that a process is always running. It allows you to configure logging, how DNS is resolved, and much more.</p>
<p>Units in <code>systemd</code> are resources that <code>systemd</code> can manage for you. These include services, timers, mounts, automounts, and more. <code>systemd</code> runs in the background and is completely self-sufficient.</p>
<h2 id="heading-how-systemd-is-structured">How <code>systemd</code> is Structured</h2>
<p><code>systemd</code> looks at unit files to understand how to interact with the processes. Service files are just text files that contain instructions that tell <code>systemd</code> how it needs to manage that particular service. Service files can be found in any of several directories and they will have a file extension of <code>.service</code> . Service unit files are typically located in:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Location</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td><code>/etc/systemd/system</code></td><td>This directory is for custom or overridden service files. Anything inside this directory will have the ultimate priority. If we want a configuration or custom unit file to take effect, then we should make sure that the changes are added to this directory with a higher priority.</td></tr>
<tr>
<td><code>/run/systemd/system</code></td><td>This directory is for runtime-generated files. It stores runtime <code>systemd</code> units and it is the least looked directory.</td></tr>
<tr>
<td><code>/lib/systemd/system</code></td><td>This directory is for default service files provided by installed packages. When we install a package, a service file of that package will be installed for us and it will go inside the 3rd directory with the lowest priority. The reason is that the user has an opportunity to override the settings. It is not recommended to store custom unit files inside the 3rd directory, because if a package is updated, the custom unit files will be overwritten.</td></tr>
</tbody>
</table>
</div><p>When the Linux system starts, it will start the <code>systemd</code> and <code>systemd</code> will go into these directories looking for unit files. If it finds any, it is going to load those into memory.</p>
<p>A service unit file structure is divided into 3 sections (<code>[Unit]</code>, <code>[Service]</code>, <code>[Install]</code>), each containing key-value pairs that configure the behavior of the service. Each section name must be started with a capital letter since the file is case-sensitive. For example:</p>
<ul>
<li><p><code>[Unit]</code> section: Describes the unit and its relationships to other units. Common options include <code>Description</code>, <code>After</code>, <code>Requires</code>, and <code>Wants</code>.</p>
</li>
<li><p><code>[Service]</code> section: Specifies how the service should be started, the command to use, and its behavior. Options include <code>Type</code>, <code>ExecStart</code>, <code>Restart</code>, and <code>User</code>.</p>
</li>
<li><p><code>[Install]</code> section: Defines how the service should be enabled or started as part of the system startup sequence. The most common option is <code>WantedBy</code>.</p>
</li>
</ul>
<p>Dependencies between services are managed with directives like <code>After=</code>, <code>Before=</code>, <code>Wants=</code>, and <code>Requires=</code>. These directives help ensure services start in the correct order and that prerequisite services are running.</p>
<p>As an example, let's look at the <code>apache2.service</code> unit file which can be found in <code>/lib/systemd/system</code> directory:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712825039266/be461fa2-82c1-4144-ae2a-3e1f44994dd4.png" alt class="image--center mx-auto" /></p>
<p>Editing a <code>systemd</code> service unit file allows you to customize how a service starts, behaves, or stops on your system. To safely edit a service unit file, run:</p>
<pre><code class="lang-bash">sudo systemctl edit SERVICE_NAME.service
</code></pre>
<p>This command opens the service's override file in the default text editor. If the override file doesn’t exist, <code>systemctl</code> will create a new one. The override file allows you to specify only the changes or additions you want to apply to the service unit, without needing to copy and edit the entire original service file. It is stored in a directory named after the service within <code>/etc/systemd/system/example.service.d/override.conf</code><strong>.</strong> This directory can contain multiple <code>.conf</code> files for granular overrides.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712857232737/b377af3d-e822-4e9c-bfee-cdf8667d943b.png" alt class="image--center mx-auto" /></p>
<p>When <code>systemd</code> loads the service's configuration, it reads the original service file first and then applies the settings from the override file. If there are conflicting directives, the settings in the override file take precedence over those in the original service file. This merge happens in memory, leaving the original service file unchanged on disk.</p>
<p>To edit the entire service file, run:</p>
<pre><code class="lang-bash">sudo systemctl edit --full SERVICE_NAME.service
</code></pre>
<p>This command makes a copy of the entire service file and save it in <code>/etc/systemd/system</code> directory. This copy file will be in priority than the original service file.</p>
<h2 id="heading-hands-on-exercise-overview">Hands-on Exercise Overview</h2>
<p><code>systemctl</code> is the primary command-line utility for interacting with <code>systemd</code>. While it's used for managing various aspects of <code>systemd</code>, it's particularly focused on service management. This hands-on exercise shows how to use the six most important commands related to <code>systemctl</code> and <code>systemd</code> in general. It shows how to start, stop, restart, check the status, and enable, and disable the process using <code>systemctl</code> command. These are the bare minimum we should know when it comes to <code>systemd</code>.</p>
<h2 id="heading-hands-on-exercise">Hands-on Exercise</h2>
<ol>
<li><p>Let's install a web server service for serving a web page.</p>
<pre><code class="lang-bash"> sudo apt install apache2
</code></pre>
</li>
<li><p>To check the status of the web service, run:</p>
<pre><code class="lang-bash"> systemctl status apache2.service
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712409091813/e3b11900-4833-4c16-8318-a08e2a635b4f.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To confirm that Apache2 is serving its default page by accessing it from within the Vagrant box, run <code>curl http://localhost</code> in the command line. This should show the HTML content of the default Apache2 Ubuntu default page.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712599815995/e3a0211e-a50d-4fd1-a11b-32e91fd93815.png" alt class="image--center mx-auto" /></p>
<p> or, enter <a target="_blank" href="http://localhost:8080/">http://localhost:8080/</a> on the web browser of your host machine:</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712599509549/6b497ec0-2a88-404f-9063-df70e641370c.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Since this hands-on exercise is run via Vagrant Ubuntu 20.04, we need to modify the <a target="_blank" href="https://github.com/karlakz/vagrant-templates/tree/main/host-to-vm-port-forwarding">Vagrantfile</a> to configure port forwarding for forwarding requests made to port 8080 on the host machine to port 80 on the Vagrant guest machine (where Apache2 listens by default).</div>
</div>

<ol start="4">
<li><p>To stop the web service with <code>systemd</code> immediately, run:</p>
<pre><code class="lang-bash"> sudo systemctl stop apache2.service
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712600574527/7a03f3a7-a0a8-498a-b1cb-47b543264cde.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To start the service immediately:</p>
<pre><code class="lang-bash"> sudo systemctl start apache2.service
</code></pre>
</li>
<li><p>To restart the service, run:</p>
<pre><code class="lang-bash"> sudo systemctl restart apache2.service
</code></pre>
<p> This command stops the service and then starts it again. This is useful for applying changes that require a complete stop and start to take effect. Restarting is more disruptive but ensures that the service runs with the latest configuration and code.</p>
</li>
<li><p>To reload the service, run:</p>
<pre><code class="lang-bash"> sudo systemctl reload apache2.service
</code></pre>
<p> This command tells a service to reload its configuration files without interrupting ongoing operations. It is useful for applying non-disruptive changes. Not all services support reloading; it depends on whether the service can dynamically read new configurations without needing to stop and start again.</p>
</li>
<li><p>To enable a service to start at boot:</p>
<pre><code class="lang-bash"> sudo systemctl <span class="hljs-built_in">enable</span> apache2.service
 sudo systemctl <span class="hljs-built_in">enable</span> --now apache2.service
</code></pre>
<p> <code>--now</code> option allows to start the service immediately and enable it in one shot.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712602357009/911dd470-ee58-4b59-a25a-f97e95eecac4.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To disable a service from starting at boot:</p>
<pre><code class="lang-bash"> sudo systemctl <span class="hljs-built_in">disable</span> apache2.service
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712602798091/419c7ef0-2a13-4845-8dd0-b31459e962a6.png" alt class="image--center mx-auto" /></p>
<p> <code>preset: enabled</code> means that the distribution has configured <code>systemd</code> such that new services will be enabled by default on boot. The vendor preset only indicates the initial recommended state. Debian and Ubuntu typically enable a newly started service for the user whereas Red Hat-based distributions such as Fedora, and CentOS disable it.</p>
</li>
<li><p>To list unit files that are of type service, run:</p>
<pre><code class="lang-bash">systemctl list-unit-files --<span class="hljs-built_in">type</span>=service
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712864080818/f685d1f0-cbdf-4ada-92b1-af4565ca4bd9.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<h2 id="heading-references">References:</h2>
<ol>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=Kzpm-rGAXos&amp;t=309s">Systemd Deep-Dive: A Complete, Easy to Understand Guide for Everyone</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=5JVBpXiYMKo">Linux Crash Course - systemd: Using the systemctl command</a></p>
</li>
<li><p><a target="_blank" href="https://www.digitalocean.com/community/tutorials/how-to-use-systemctl-to-manage-systemd-services-and-units">How To Use Systemctl to Manage Systemd Services and Units</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Formatting & Mounting Storage Volumes in Linux]]></title><description><![CDATA[Physical storage devices (hard disk, SSD, floppy disk, etc.) are the actual hardware components that store data. A single physical storage device can be divided into multiple smaller usable sections, each acting as a separate volume.


Hard Disk 1 an...]]></description><link>https://karlygash-yakiyayeva.dev/formatting-mounting-storage-volumes-in-linux</link><guid isPermaLink="true">https://karlygash-yakiyayeva.dev/formatting-mounting-storage-volumes-in-linux</guid><category><![CDATA[disks]]></category><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[Linux]]></category><category><![CDATA[disk]]></category><category><![CDATA[formatting]]></category><dc:creator><![CDATA[Karlygash Yakiyayeva]]></dc:creator><pubDate>Mon, 08 Apr 2024 06:59:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/JwMGy1h-JsY/upload/33ee89a633be4e02f5bf7f657b9df223.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Physical storage devices (hard disk, SSD, floppy disk, etc.) are the actual hardware components that store data. A single physical storage device can be divided into multiple smaller usable sections, each acting as a separate <a target="_blank" href="https://en.wikipedia.org/wiki/Volume_(computing)">volume</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711830293744/2f28342b-57cf-41a0-b5f3-485d5f10385a.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p><strong>Hard Disk 1</strong> and <strong>Hard Disk 2</strong> are physical disks;</p>
</li>
<li><p>"<strong>/dev/sda1</strong>", "<strong>/dev/sda2</strong>", and "<strong>/dev/sdb</strong>" are volumes or partitions;</p>
</li>
<li><p>Any of these can be called a "<em>drive</em>".</p>
</li>
</ul>
<p>In Linux, storage devices are typically represented as files in the <code>/dev</code> directory. Typically, files representing storage devices start with <code>sd</code> or <code>hd</code> followed by a letter.</p>
<p>For example, the first physical drive we attach to the system will be <code>/dev/sda</code>. For the subsequent physical storage drive we attach to the system, they’ll get the identifier in the form of <em>sd{alphabet}</em>, where the <em>alphabet</em> is the next letter in the line.</p>
<p>The kernel provides a name to every storage device plugged in or added to the computer or server on Linux.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711887781153/f0cac026-3ff2-4abf-a536-0ddda167db87.png" alt class="image--center mx-auto" /></p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Desktop Linux and Server Linux handle storage a bit differently. On Desktop Linux, when you insert a flash drive, it will be automatically mounted and accessible through the file manager. On Server Linux, you typically don't have a graphical user interface (GUI) available, so the command line should be used to manage storage devices.</div>
</div>

<h2 id="heading-partitioning">Partitioning</h2>
<p>Partitioning is the process of dividing the storage device into segments. To partition the disk in Linux utilities such as <code>fdisk</code>, <code>gdisk</code>, <code>parted</code> and the partitioning schemes such as <strong>MBR</strong> (Master Boot Record), <strong>GPT</strong> (GUID Partition Table) are used.</p>
<ul>
<li><p><strong>MBR</strong> is over 30 years old. Because of its age, it has some serious limitations. For instance, it cannot be used for disks over <strong>2TB</strong>, and can only have a maximum of <strong>four primary partitions</strong>.</p>
</li>
<li><p><strong>GPT</strong> is a more <strong>modern partitioning scheme</strong> that resolves some of the issues inherent in MBR. Systems running GPT can have many more partitions per disk. This is usually only limited by the restrictions imposed by the operating system itself. Additionally, the disk size limitation does not exist with GPT and the partition table information is available in multiple locations to guard against corruption. GPT can also write a “protective MBR” for compatibility with MBR-only tools. In most cases, GPT is the better choice unless your operating system prevents you from using it.</p>
</li>
</ul>
<p>Each partition can be used for a different purpose, This gives a user more flexibility, allowing them to potentially segment a single disk for multiple operating systems, swap space, or specialized filesystems.</p>
<p>As a next step after partitioning, formatting and mounting of the storage volume should be done to prepare the disk for use.</p>
<h2 id="heading-formatting">Formatting</h2>
<p>While the Linux kernel can recognize a raw disk, it must be formatted to be used. <strong>Formatting</strong> is the process of writing a filesystem to the disk and preparing it for file operations. A <strong>filesystem</strong> is a system that structures data and controls how information is written to and retrieved from the underlying disk. The storage device can not be used for standard filesystem operations without a filesystem. Common Linux filesystems include <code>ext4</code>, <code>XFS</code>, <code>BTRFS</code>, and <code>NTFS</code> (for Windows compatibility).</p>
<p>The general syntax for formatting disk partitions in Linux is:</p>
<pre><code class="lang-bash">sudo mkfs [options] [-t <span class="hljs-built_in">type</span> ] [fs-options] device [size]
</code></pre>
<ul>
<li><p><code>mkfs</code> - used to build a Linux filesystem on a device, usually a hard disk partition;</p>
</li>
<li><p><code>-t</code>, <code>--type</code> - Specify the type of filesystem to be built. If not specified, the default filesystem type (currently <code>ext2</code>) is used.</p>
</li>
<li><p><code>device</code> argument is either the device name (e.g. <code>/dev/hda1</code>, <code>/dev/sdb2</code>) or a regular file that shall contain the filesystem.</p>
</li>
<li><p><code>size</code> argument is the number of blocks to be used for the filesystem.</p>
</li>
</ul>
<h2 id="heading-mounting">Mounting</h2>
<p><strong>Mounting</strong> is the process of attaching a formatted partition or drive to a directory within the Linux filesystem. In Linux and other Unix-like operating systems, the entire system, regardless of how many physical devices are involved, is represented by a single unified file tree. When a filesystem on a drive or partition is to be used, it must be attached to the existing tree. The drive’s contents can then be accessed from that directory.</p>
<p>Drives are almost always mounted on dedicated empty directories – mounting on a <em>non-empty</em> directory means that the directory’s usual contents will be inaccessible until the drive is unmounted. Many different mounting options can be set to alter the behavior of a mounted device. For example, the drive can be mounted in read-only (RO) mode to ensure its contents won’t be changed.</p>
<p>The standard form of the mount command is:</p>
<pre><code class="lang-bash">sudo mount -t <span class="hljs-built_in">type</span> device dir
</code></pre>
<p>This tells the kernel to attach the filesystem found on device (which is of type <code>type</code>) at the directory <code>dir</code>. The option <code>-t</code> type is optional. The <code>mount</code> command is usually able to detect a filesystem. The root permissions are necessary to mount a filesystem by default.</p>
<h2 id="heading-hands-on-exercise-overview">Hands-on Exercise Overview</h2>
<p>A disk partition must be formatted and mounted before use. The formatting process can also be done for several other reasons, such as changing the file system, fixing errors, or deleting all data.</p>
<p>This hands-on exercise shows how to format and mount disk partitions in Linux using <code>ext4</code> file system.</p>
<h2 id="heading-hands-on-exercise">Hands-on Exercise</h2>
<ol>
<li><p>To list all block devices attached to the local computer or server, use:</p>
<pre><code class="lang-bash"> lsblk
</code></pre>
<p> The terminal prints out a list of all block devices which are files that represent devices such as hard drives, RAM disks, USB drives, and CD/ROM drives as well as information about them:</p>
<ul>
<li><p><strong>NAME</strong> – Device names</p>
</li>
<li><p><strong>MAJ:MIN</strong> – Major or minor device numbers. These are the major and minor device numbers used by the Linux kernel to uniquely identify the type of device (major) and the specific instance of that device type (minor).</p>
</li>
<li><p><strong>RM</strong> – Whether the device is removable (1 if yes, 0 if no)</p>
</li>
<li><p><strong>SIZE</strong> – The size of the device</p>
</li>
<li><p><strong>RO</strong> – Whether the device is read-only (1 if yes, 0 if no)</p>
</li>
<li><p><strong>TYPE</strong> – The type of the device</p>
</li>
<li><p><strong>MOUNTPOINT</strong> – Device’s mount point</p>
</li>
</ul>
</li>
</ol>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712124652898/7469319a-0fdc-4fd1-8266-7cd66254ceb6.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p><strong>loop0</strong> - Loop devices are a special block device that maps a normal file onto a virtual block device. This allows the file to be treated as if it were a physical disk, making it possible to mount a filesystem within a file onto the Linux file system hierarchy. Linux names these devices <code>loop0</code>, <code>loop1</code>, etc., based on their order of creation or mapping.</p>
</li>
<li><p><strong>sda</strong> - The name is derived from "SCSI Disk A," where "SCSI" stands for Small Computer System Interface, a set of standards for physically connecting and transferring data between computers and peripheral devices. Despite its origins, the naming convention is used broadly for devices using various interfaces, including SATA, which is very common in HDDs and SSDs. The letter <code>a</code> indicates that this is the first device recognized by the system. Additional partitions on this device would be listed as <code>sda1</code>, <code>sda2</code>, etc., representing different storage segments that were allocated for different purposes, such as system files, user data, or swap space. Subsequent devices would be named <code>sdb</code>, <code>sdc</code>, and so on.</p>
</li>
<li><p><strong>xvda</strong> - This naming convention suggests that this block device is a virtual disk, typically seen in environments using Xen or KVM virtualization, or cloud platforms like AWS EC2.</p>
</li>
</ul>
<ol start="2">
<li><p>To display a list of all block devices containing file system information, add the <code>-f</code> option:</p>
<pre><code class="lang-bash">  lsblk -f
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712125856779/029dc200-686f-4778-8f81-f7d721f12261.png" alt class="image--center mx-auto" /></p>
<p> This allows us to locate a partition for formatting and mounting. In this case, we can see that <code>sdc</code> partition is empty and not allocated for any specific purpose by the system or cloud provider. Therefore, it can be used for formatting and mounting.</p>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">When working with block devices, if we target a device name without a number, we are targeting the entire disk. But if we add a number at the end of the device name, then we are targeting the partition.</div>
 </div>
</li>
<li><p>To view what partitions are available on a storage device:</p>
<pre><code class="lang-bash"> sudo fdisk -l
</code></pre>
<ul>
<li><p><code>fdisk</code> - a dialog-driven program for the creation and manipulation of partition tables. It understands GPT and MBR partition tables.</p>
</li>
<li><p><code>-l, --list</code> - lists the partition tables for the specified devices and then exit.</p>
</li>
</ul>
</li>
</ol>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712126736623/06b1794b-520a-4878-b6a9-ad17949aca40.png" alt class="image--center mx-auto" /></p>
<ol start="4">
<li><p>To format a disk or disk partition with the file system, use the following command:</p>
<pre><code class="lang-bash"> sudo mkfs -t ext4 /dev/sdc
</code></pre>
<p> Make sure the correct disk is targeted. Then, verify the file system change using the command, <code>lsblk -f</code></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712129891745/86b23477-18a6-459e-aae2-ea27bfe1c5af.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Create a new folder under the <code>/mnt</code> to mount the formatted storage device before using the disk:</p>
<pre><code class="lang-bash"> sudo mkdir /mnt/mountpoint
 ls -l /mnt
</code></pre>
<p> This command creates a directory that will serve as the mount point for the new filesystem.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712144660524/8903edee-a53a-446f-a788-836ba5b77de9.png" alt class="image--center mx-auto" /></p>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">It is recommended to use <code>/media</code> for temporary storage volumes and <code>/mnt</code> for permanent storage volumes</div>
 </div>
</li>
<li><p>To mount the disk, use the following command and verify if the disk is mounted:</p>
<pre><code class="lang-bash"> sudo mount /dev/sdc /mnt/disk3
 df -h
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712144951527/5ff86141-8581-4317-b14a-19a4ae445267.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To get a list of all mounted storage devices on the system:</p>
<pre><code class="lang-bash"> mount
 mount | grep sdc
</code></pre>
</li>
<li><p>To remove a filesystem from the directory hierarchy, unmount it with the <code>umount</code> command:</p>
<pre><code class="lang-bash"> sudo umount /mnt/mydisk
 lsblk -f
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712146090061/b7c20b4c-ea74-4e1a-a4d6-60bec330fd6b.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<p>Once a disk is successfully formatted and mounted on the Linux system, it's ready for use! This new storage space can serve various purposes depending on your needs such as storing personal or application data, backing up storage, storing Virtual Machine (VM) disks etc;</p>
<h2 id="heading-references">References</h2>
<ol>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=2Z6ouBYfZr8">Linux Crash Course - Formatting &amp; Mounting Storage Volumes</a></p>
</li>
<li><p><a target="_blank" href="https://www.baeldung.com/linux/drive-partition-volumes#drive">Differences Between Drive, Partition, and Volumes in Linux</a></p>
</li>
<li><p><a target="_blank" href="https://www.digitalocean.com/community/tutorials/an-introduction-to-storage-terminology-and-concepts-in-linux#what-is-block-storage">An Introduction to Storage Terminology and Concepts in Linux</a></p>
</li>
<li><p><a target="_blank" href="https://phoenixnap.com/kb/linux-format-disk">How to Format Disk Partitions in Linux</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[The sed Command in Linux]]></title><description><![CDATA[The sed command in Linux stands for Stream Editor. It is a powerful utility that parses and transforms text, using a simple, compact programming language. sed is particularly useful for editing large files or streams without opening them in a traditi...]]></description><link>https://karlygash-yakiyayeva.dev/the-sed-command-in-linux</link><guid isPermaLink="true">https://karlygash-yakiyayeva.dev/the-sed-command-in-linux</guid><category><![CDATA[Devops]]></category><category><![CDATA[sed]]></category><category><![CDATA[Linux]]></category><category><![CDATA[sysops]]></category><category><![CDATA[sysadmin]]></category><dc:creator><![CDATA[Karlygash Yakiyayeva]]></dc:creator><pubDate>Thu, 04 Apr 2024 06:01:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/5IHz5WhosQE/upload/a3bb7c5eca9aebe1ed48b2d4c8be4154.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a target="_blank" href="https://en.wikipedia.org/wiki/Sed">The <code>sed</code> command</a> in Linux stands for <strong>Stream Editor</strong>. It is a powerful utility that parses and transforms text, using a simple, compact programming language. <code>sed</code> is particularly useful for editing large files or streams without opening them in a traditional text editor. It operates line by line, applies operations specified by the user, and outputs the result to the standard output.</p>
<h2 id="heading-how-sed-works">How <code>sed</code> Works</h2>
<p>The workflow of <code>sed</code> (Stream Editor) involves reading, executing commands, and displaying the output, operating in a cycle over the input stream.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711202161645/a4344814-e043-4a29-84c8-4f8fbc212faa.png" alt class="image--center mx-auto" /></p>
<p>Here's a step-by-step explanation of how <code>sed</code> works:</p>
<ol>
<li><p><strong>Reading</strong>: <code>sed</code> reads one line at a time from the input stream. This can be a file or input piped from another command.</p>
</li>
<li><p><strong>Placing:</strong> Each line read into <code>sed</code> is placed into a space called the "pattern space," where the operations are performed. The end-of-line newline character is temporarily removed during this step.</p>
</li>
<li><p><strong>Executing Commands</strong>: Once a line is in the pattern space, <code>sed</code> executes all the commands you've specified in the order they were given. These commands can modify the contents of the pattern space (like replacing text, deleting the line, etc.), and they can be conditioned to only run if the line matches a specified pattern. <code>sed</code> commands are powerful and can include:</p>
<ul>
<li><p>Substitution (e.g., <code>s/pattern/replacement/</code>): Search for a pattern and replace it with the specified text.</p>
</li>
<li><p>Deletion (e.g., <code>d</code>): Delete lines that match a specified pattern or line number.</p>
</li>
<li><p>Insertion and Appending (e.g., <code>i\text</code>, <code>a\text</code>): Insert or append text before or after a matching pattern or line number.</p>
</li>
<li><p>Reading and Writing (e.g., <code>r filename</code>, <code>w filename</code>): Read content from a file into the pattern space, or write content from the pattern space to a file.</p>
</li>
<li><p>Line Addressing: Apply commands to specific lines or ranges of lines, either specified by line numbers or patterns.</p>
</li>
</ul>
</li>
<li><p><strong>Printing</strong>: After executing all commands on the line in the pattern space, <code>sed</code> by default prints the contents of the pattern space to the standard output. It can be redirected to a file or piped to another command for further processing.This behavior can be modified with options like <code>-n</code>, which suppresses automatic printing unless explicitly told to print (e.g., with the <code>p</code> command).</p>
</li>
<li><p><strong>Cycle Continues</strong>: The pattern space is then cleared, and <code>sed</code> reads the next line of input, continuing the cycle until all lines from the input have been processed.</p>
</li>
</ol>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">The <strong>sed</strong> command uses two workspaces for holding the line being modified: 1. <em>The pattern space</em>, where the selected line is held; 2. <em>The hold space</em>, where a line can be stored temporarily.</div>
</div>

<h2 id="heading-linux-sed-syntax">Linux <code>sed</code> Syntax</h2>
<p>The main syntax for using Linux <code>sed</code> command is:</p>
<pre><code class="lang-bash">sed [OPTIONS]... [SCRIPT] [INPUTFILE...]
</code></pre>
<ul>
<li><p><code>[OPTIONS]</code>: These are command-line options that modify how <code>sed</code> operates. Some of the most commonly used options include:</p>
<ul>
<li><p><code>-e script</code>: Allows you to specify a script containing one or more <code>sed</code> commands. This option is useful when chaining multiple commands.</p>
</li>
<li><p><code>-i</code>: Enables in-place editing of files. When used, <code>sed</code> modifies the input file directly.</p>
</li>
<li><p><code>-n</code>: Suppresses automatic printing of the pattern space. Typically used with the <code>p</code> command to print specific lines.</p>
</li>
</ul>
</li>
<li><p><code>[script]</code>: This is where you specify the <code>sed</code> commands to be executed. The script usually contains one or more commands that tell <code>sed</code> how to process the input text.</p>
</li>
<li><p><code>[input-file]</code>: This is the source of input data for <code>sed</code> to process. It can be one or more filenames. If no input file is specified, <code>sed</code> reads from the standard input, which allows it to be used in pipelines with other commands.</p>
</li>
</ul>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><code>sed</code> does not affect the source file unless instructed. To overwrite the original file, use the <code>-i</code> option to save the modifications. However, such practice is not recommended before testing out the command output. Alternatively, save the edits to a different (or new) file. Redirect the output by adding <code>&gt; newfilename.txt</code> at the end of the command.</div>
</div>

<h2 id="heading-hands-on-exercise-overview">Hands-on Exercise Overview</h2>
<p>This hands-on exercise shows ten commonly used <code>sed</code> commands and a <em>foxinbox.txt</em> file with the following content was taken as a sample file:</p>
<p><img src="https://i.imgur.com/Sekuqxe.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-hands-on-exercise">Hands-on Exercise</h2>
<ol>
<li><p>To replace text, use the substitute command <code>s</code> and delimiters (in most cases, slashes - <code>/</code>) for separating text fields.</p>
<pre><code class="lang-bash"> sed <span class="hljs-string">'s/old_string/new_string/'</span> filename.txt
</code></pre>
<p> For example, to replace instances of <code>box</code> with the word <code>bin</code>, run:</p>
<p> <img src="https://i.imgur.com/zhIWlro.png" alt class="image--center mx-auto" /></p>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">It does not matter what is used as the delimiter. Use any other delimiter instead of the forward slash ( <code>/</code> ) if the forward slash must be searched for.</div>
 </div>
</li>
<li><p>To replace multiple instances of the same word within a single line, add the <code>g</code> flag to the command to change all of them:</p>
<pre><code class="lang-bash"> sed <span class="hljs-string">'s/old_string/new_string/g'</span> filename.txt
</code></pre>
<p> For example, to replace the word <code>box</code> with the word <code>bin</code> in the file <em>foxinbox.txt</em> every time, type:</p>
<p> <img src="https://i.imgur.com/iStoKfK.png" alt class="image--center mx-auto" /></p>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">By default, <code>sed</code> only replaces the first occurrence of the specified string in each line. It searches for the first instance of the specified word in a line, replaces it, and moves on to the next line.</div>
 </div>
</li>
<li><p>To replace a specific occurrence of the string in a line, add a number flag such as <strong>1, 2</strong> etc:</p>
<pre><code class="lang-bash"> sed <span class="hljs-string">'s/old_string/new_string/#'</span> filename.txt
</code></pre>
<p> For example, to substitute the second occurrence of the word <code>box</code> in each line of the file with the word <code>bin</code>, use this command:</p>
<p> <img src="https://i.imgur.com/AJ1YcIp.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To print out just the lines that have substitution under the given conditions, use the syntax:</p>
<pre><code class="lang-bash"> sed -n <span class="hljs-string">'s/old_string/new_string/p'</span> filename.txt
</code></pre>
<ul>
<li><p><code>-n</code> option disables automatic printing.</p>
</li>
<li><p><code>-p</code> instructs <code>sed</code> to print lines where substitution occurs.</p>
</li>
</ul>
</li>
</ol>
<p>    For example, to replace the second instance of the word <code>box</code> in a line and print the line where the change took place:</p>
<p>    <img src="https://i.imgur.com/cGCdIzb.png" alt class="image--center mx-auto" /></p>
    <div data-node-type="callout">
    <div data-node-type="callout-emoji">💡</div>
    <div data-node-type="callout-text">By default, the <code>sed</code> command prints out the entire file content, along with the substitute text in its output. If you have a lot of text and want to focus on the lines with the applied changes, add the needed attributes to the command.</div>
    </div>

<ol start="5">
<li><p>To ignore case while substituting text, add the <code>i</code> subcommand at the end of the command:</p>
<pre><code class="lang-bash"> sed <span class="hljs-string">'s/old_string/new_string/i'</span> filename.txt
</code></pre>
<p> For example, the command for changing upper and lowercase instances of the word <strong>fox</strong> in the <em>foxinbox.txt</em> file is:</p>
<p> <img src="https://i.imgur.com/Fb7gf57.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To substitute a string in a specific line, add the line number as a prefix to the <code>s</code> subcommand:</p>
<pre><code class="lang-bash"> sed <span class="hljs-string">'# s/old_string/new_string/'</span> filename.txt
</code></pre>
<p> For example, to replace the word <code>socks</code> with <code>sandals</code> only in the fourth line (<code>4</code>) of the text use the command:</p>
<p> <img src="https://i.imgur.com/rxz7zet.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To replace multiple instances of a string within a line range, but not the entire text, specify the range where you want <code>sed</code> to substitute. The syntax is:</p>
<pre><code class="lang-bash"> sed <span class="hljs-string">'#,# s/old_string/new_string/'</span> filename.txt
</code></pre>
<p> Replace the first <code>#</code> with the initial line number and the second <code>#</code> with the last line number you want to include.</p>
<p> For instance, to replace the last two instances of the word <strong>socks</strong> in the file <em>foxinbox.txt</em> (located in the fourth and sixth line) with the word <code>sandals</code>, run:</p>
<p> <img src="https://i.imgur.com/7jkYvfs.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To delete a line from a file with the <code>sed</code> command, use the <code>d</code> subcommand and the syntax:</p>
<pre><code class="lang-bash"> sed <span class="hljs-string">'#d'</span> filename.txt
</code></pre>
<p> Specify the line number you want to remove instead of the hash (<code>#</code>) symbol and run the command.</p>
<p> For instance, to remove the second line from the <em>foxinbox.txt</em> file, type:</p>
<p> <img src="https://i.imgur.com/NQigAGw.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To <a target="_blank" href="https://phoenixnap.com/kb/sed-delete-line">use sed to delete lines</a> <a target="_blank" href="https://phoenixnap.com/kb/sed-delete-line">within a line range,</a> follow the syntax:</p>
<pre><code class="lang-bash"> sed <span class="hljs-string">'#,#d'</span> filename.txt
</code></pre>
<p> Replace the hash symbols with the beginning and end of the line range.</p>
<p> For example, to delete lines 2, 3, and 4 from the <em>foxinbox.txt</em> file, run the command:</p>
<p> <img src="https://i.imgur.com/m1aP4ZB.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To delete empty lines (that contain no characters), run:</p>
<pre><code class="lang-bash">sed <span class="hljs-string">'/^$/d'</span> filename.txt
</code></pre>
<p>The command uses a regular expression pattern <code>^$</code> to match empty lines. The <code>^</code> represents the start of a line, and <code>$</code> represents the end of a line.</p>
<p>For instance, to remove empty lines from the <em>foxinbox.txt</em>, run this command:</p>
<p><img src="https://i.imgur.com/NQ3euzH.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<h2 id="heading-references">References:</h2>
<ol>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=nXLnx8ncZyE&amp;list=PLT98CRl2KxKHKd_tH3ssq0HPrThx2hESW&amp;index=13">Linux Crash Course - The sed Command</a></p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Sed">sed - wikipedia</a></p>
</li>
<li><p><a target="_blank" href="https://www.gnu.org/software/sed/manual/sed.html#The-_0022s_0022-Command">sed, a stream editor - gnu</a></p>
</li>
<li><p><a target="_blank" href="https://www.ibm.com/docs/en/aix/7.2?topic=s-sed-command">sed Command by IBM</a></p>
</li>
<li><p><a target="_blank" href="https://phoenixnap.com/kb/linux-sed#ftoc-heading-1">Linux sed Command: How To Use the Stream Editor by phoenixNAP</a></p>
</li>
<li><p><a target="_blank" href="https://phoenixnap.com/kb/sed-delete-line#ftoc-heading-7">How to Use sed Command to Delete a Line by phoenixNAP</a></p>
</li>
<li><p><a target="_blank" href="https://phoenixnap.com/kb/sed-replace">How to Use Sed to Find and Replace a String in a File by phoenixNAP</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[The awk Command in Linux]]></title><description><![CDATA[awk is a powerful programming language used for text processing and manipulation in Unix/Linux environments. It's particularly well-suited for tasks involving structured text files, especially when those files are data files or CSV files. It gets its...]]></description><link>https://karlygash-yakiyayeva.dev/the-awk-command-in-linux</link><guid isPermaLink="true">https://karlygash-yakiyayeva.dev/the-awk-command-in-linux</guid><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[Linux]]></category><category><![CDATA[admin]]></category><category><![CDATA[administration]]></category><category><![CDATA[awk]]></category><dc:creator><![CDATA[Karlygash Yakiyayeva]]></dc:creator><pubDate>Wed, 03 Apr 2024 05:22:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/lBsvzgYnzPU/upload/46f602ac546292f3ff57dc5a4223a4ef.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a target="_blank" href="https://en.wikipedia.org/wiki/AWK"><code>awk</code></a> is a powerful programming language used for text processing and manipulation in Unix/Linux environments. It's particularly well-suited for tasks involving structured text files, especially when those files are data files or CSV files. It gets its name from the initials of its creators: Aho, Weinberger, and Kernighan.</p>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/Awk-example-usage-gimp.gif/600px-Awk-example-usage-gimp.gif" alt class="image--center mx-auto" /></p>
<p>Image source: <a target="_blank" href="https://en.wikipedia.org/wiki/AWK">Wikipedia</a></p>
<h2 id="heading-how-awk-works">How <code>awk</code> Works</h2>
<p>When you run <code>awk</code>, you specify an <code>awk</code> program that tells <code>awk</code> what to do. The program consists of a series of <em>rules.</em> Each rule specifies one pattern to search for and one action to perform upon finding the pattern.</p>
<p>Syntactically, a rule consists of a <em>pattern</em> followed by an <em>action</em>. The action is enclosed in braces to separate it from the pattern. Newlines usually separate rules. Therefore, a <code>awk</code> program looks like this:</p>
<pre><code class="lang-bash">awk [options] <span class="hljs-string">'program'</span> input-file(s)
</code></pre>
<p>OR</p>
<pre><code class="lang-bash">awk [options] <span class="hljs-string">'pattern { action }'</span> input-file(s)
</code></pre>
<ul>
<li><p><strong>pattern:</strong> Specifies when the action should be performed. If omitted, the action is applied to every line.</p>
</li>
<li><p><strong>action:</strong> What to do when a line matches the pattern. Actions are enclosed in braces <code>{}</code>.</p>
</li>
</ul>
<p>Single quotes around <code>program</code> makes the shell not to interpret any <code>awk</code> characters as special shell characters. The quotes also cause the shell to treat all of <code>program</code> as a single argument for <code>awk</code>, and allow <code>program</code> to be more than one line long.</p>
<h2 id="heading-benefits-of-awk"><strong>Benefits of AWK</strong></h2>
<ol>
<li><p>Supports complex pattern-matching and processing.</p>
</li>
<li><p>Designed for efficient text processing on both small and large files.</p>
</li>
<li><p>Easy to write and understand one-liners for basic tasks.</p>
</li>
<li><p>Changing data files.</p>
</li>
<li><p>Producing formatted reports.</p>
</li>
<li><p>Available on all Unix-like systems without the need for installation or setup.</p>
</li>
</ol>
<h2 id="heading-variables-in-awk">Variables in AWK</h2>
<p>Variables in AWK play a crucial role in processing text and data. They are used to store temporary data, manipulate fields, control the flow of the program, and customize output. AWK variables can be <em>user-defined</em> or <em>built-in</em>, with the latter providing access to various useful pieces of information or functionality. Some of the most commonly used built-in variables are:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Variable</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td><strong>FS</strong> (Field Separator)</td><td>Controls how fields in a record (line) are separated. The default is whitespace. You can change it to parse CSV or other formats.</td></tr>
<tr>
<td><strong>OFS</strong> (Output Field Separator)</td><td>Specifies the separator to use when printing multiple fields with <code>print</code>.</td></tr>
<tr>
<td><strong>RS</strong> (Record Separator)</td><td>Determines how records are separated in the input data. By default, it's a newline character.So if you do not change it, a record is one line of the input file.</td></tr>
<tr>
<td><strong>ORS</strong> (Output Record Separator)</td><td>The separator used when printing output records. By default, it's a newline.</td></tr>
<tr>
<td><strong>NF</strong> (Number of Fields)</td><td>Contains the number of fields in the current record.</td></tr>
<tr>
<td><strong>NR</strong>*(Number of Records)*</td><td>The total number of input records processed so far. Working with Text Files.</td></tr>
<tr>
<td><strong>FILENAME</strong></td><td>The name of the current input file.</td></tr>
<tr>
<td><strong>$0</strong></td><td>Represents the entire current record.</td></tr>
<tr>
<td><strong>$1, $2, ..., $n</strong></td><td>Represents the first, second, ..., nth field in the current record.</td></tr>
</tbody>
</table>
</div><ul>
<li><p><strong>BEGIN</strong> and <strong>END</strong> - are not variables but special pattern blocks. The <code>BEGIN</code> block is executed before any input is read, and the <code>END</code> block is executed after all input has been processed. These blocks are useful for initialization and summary tasks, respectively.</p>
</li>
<li><p><strong>Arrays</strong> - AWK supports associative arrays, which can be indexed by string or number. Arrays are useful for collecting and organizing data dynamically during execution.</p>
</li>
</ul>
<h2 id="heading-hands-on-exercise-overview">Hands-on Exercise Overview</h2>
<p>The main goal of this hands-on exercise is to learn how to use <code>awk</code> utility to manipulate data.</p>
<p>The input file for the examples provided below is the <em>mail-list.txt</em> file, which represents a list of peoples’ names together with their email addresses and information about those people. Each record contains the name of a person, his/her phone number, his/her email address, and a code for his/her relationship with the author of the list. The columns are aligned using spaces. An ‘A’ in the last column means the person is an acquaintance. An ‘F’ in the last column means the person is a friend. An ‘R’ means that the person is a relative:</p>
<p><img src="https://i.imgur.com/uHIMDIw.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-hands-on-exercise">Hands-on Exercise</h2>
<ol>
<li><p>Print the 1st and 3rd columns:</p>
<pre><code class="lang-bash"> awk <span class="hljs-string">'{ print $1 "\t" $3}'</span> mail-list.txt
</code></pre>
<p> <img src="https://i.imgur.com/oFH3axr.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Print lines that match a certain pattern. Search the input file <em>mail-list.txt</em> for the character string <em>li</em>:</p>
<pre><code class="lang-bash"> awk <span class="hljs-string">'/li/ { print $0 }'</span> mail-list
</code></pre>
<p> <img src="https://i.imgur.com/xskkeH1.png" alt class="image--center mx-auto" /></p>
<p> When lines containing ‘li’ are found, they are printed because <code>print $0</code> means print the current line.</p>
<p> The slashes indicate that ‘li’ is the pattern to search for. This type of pattern is called a <em>regular expression</em>. The pattern is allowed to match parts of words.</p>
</li>
<li><p>Print columns that match a specific pattern:</p>
<pre><code class="lang-bash"> awk <span class="hljs-string">'/.edu/ { print $3 }'</span> mail-list.txt
</code></pre>
<p> <img src="https://i.imgur.com/bWnBQEK.png" alt class="image--center mx-auto" /></p>
<p> When <code>awk</code> locates a pattern match, the command will execute the whole record. You can change the default by issuing an instruction to display only certain fields.</p>
</li>
<li><p>Print every line that is longer than 55 characters:</p>
<pre><code class="lang-bash"> awk <span class="hljs-string">'length($0) &gt; 55'</span> file
</code></pre>
<p> <code>awk</code> has a <em>built-in length function</em> that returns the length of the string. From the command <code>$0</code> variable stores the entire line and in the absence of a body block, the default action is taken, i.e., the print action. Therefore, in our <em>mail-list.txt</em> file, if a line has more than 55 characters, the comparison results to true, and the line is printed as shown below.</p>
<p> <img src="https://i.imgur.com/gTz3zDX.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Print the total number of bytes used by <em>mail-list.txt</em>:</p>
<pre><code class="lang-bash"> ls -l mail-list | awk <span class="hljs-string">'{ x += $5 }
                    END { print "total bytes: " x }'</span>
</code></pre>
<p> <img src="https://i.imgur.com/j5SHTWY.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Count the lines in <em>mail-list.txt</em>:</p>
<pre><code class="lang-bash"> awk <span class="hljs-string">'END { print NR }'</span> mail-list.txt
</code></pre>
<ul>
<li><p><code>END</code> specifies that the action should be performed after all lines are processed.</p>
</li>
<li><p><code>NR</code> is a built-in variable that keeps track of the number of records (lines) read.</p>
</li>
</ul>
</li>
<li><p>Print the even-numbered lines in the <em>mail-list.txt</em> file:</p>
<pre><code class="lang-bash"> awk <span class="hljs-string">'NR % 2 == 0'</span> mail-list.txt
</code></pre>
<p> <img src="https://i.imgur.com/w5g61Ax.png" alt class="image--center mx-auto" /></p>
<ul>
<li>If you used the expression ‘NR % 2 == 1’ instead, the program would print the odd-numbered lines.</li>
</ul>
</li>
</ol>
<h2 id="heading-references">References:</h2>
<ol>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=oPEnvuj9QrI">Linux Crash Course - awk</a></p>
</li>
<li><p><a target="_blank" href="https://www.gnu.org/software/gawk/manual/gawk.html">A User’s Guide for GNU Awk</a></p>
</li>
<li><p><a target="_blank" href="https://www.oreilly.com/library/view/effective-awk-programming/9781491904930/ch01.html">Getting Started with awk - O'REILLY</a></p>
</li>
<li><p><a target="_blank" href="https://phoenixnap.com/kb/awk-command-in-linux">AWK Command in Linux with Examples (phoenixNAP)</a></p>
</li>
<li><p><a target="_blank" href="https://linuxhandbook.com/awk-command-tutorial/">Getting Started With AWK Command [Beginner's Guide - Linux Handbook]</a></p>
</li>
<li><p><a target="_blank" href="https://www.digitalocean.com/community/tutorials/awk-command-linux-unix#programming-concepts-for-awk-command">AWK command in Linux/Unix - Digital Ocean</a></p>
</li>
<li><p><a target="_blank" href="https://opensource.com/article/19/10/advanced-awk">Advance your awk skills with two easy tutorials - opensource.com</a></p>
</li>
<li><p><a target="_blank" href="https://opensource.com/article/20/9/awk-ebook">A practical guide to learning awk - opensource.com</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Managing Groups in Linux]]></title><description><![CDATA[Linux group management is an essential part of Linux system administration, allowing us to organize users into groups with pre-set permissions for easier management of file permissions and system resources.
Types of Groups
There are 2 categories of g...]]></description><link>https://karlygash-yakiyayeva.dev/managing-groups-in-linux</link><guid isPermaLink="true">https://karlygash-yakiyayeva.dev/managing-groups-in-linux</guid><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[Linux]]></category><category><![CDATA[groups]]></category><category><![CDATA[admin]]></category><dc:creator><![CDATA[Karlygash Yakiyayeva]]></dc:creator><pubDate>Mon, 01 Apr 2024 12:37:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/yAGNjU4rtss/upload/9946deac8076417cf7aca82aba3eb44d.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Linux group management is an essential part of Linux system administration, allowing us to organize users into groups with pre-set permissions for easier management of file permissions and system resources.</p>
<h2 id="heading-types-of-groups">Types of Groups</h2>
<p>There are 2 categories of groups in the Linux operating system:</p>
<ul>
<li><p><strong>Primary group</strong> - When a new user is created on Linux using the <a target="_blank" href="https://karlygash-yakiyayeva.dev/managing-users-in-linux"><code>useradd</code></a> command, a group with the same name as the username is also created, and the user is added as the group's sole member. This group is the user's primary group. A user has only one primary group at any given time.</p>
</li>
<li><p><strong>Secondary (supplementary) groups</strong> - Additional groups are used to extend permissions and access rights of a user beyond what is provided by the primary group. For example, if users need access to a shared directory or need to execute tasks that require different group permissions, they can be added to the relevant secondary groups. Users can be members of multiple secondary groups.</p>
</li>
</ul>
<h3 id="heading-key-files-for-group-management"><strong>Key Files for Group Management</strong></h3>
<ul>
<li><p><code>/etc/group</code>: This file is a critical configuration file that defines the groups to which users belong. It's a text file that contains one entry per line, each describing a group.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711701408298/3b1b8be9-7c45-4e73-b9c9-fa868dbf28c1.png" alt class="image--center mx-auto" /></p>
  <div data-node-type="callout">
  <div data-node-type="callout-emoji">💡</div>
  <div data-node-type="callout-text">The password field stores a password for the group. It is usually empty (represented by an <code>x</code> or <code>*</code>), indicating that the group password is not used. Group passwords are a deprecated feature for managing group membership and access.</div>
  </div>
</li>
<li><p><code>/etc/gshadow</code>: This file complements the <code>/etc/group</code> file by providing a secure way to store group passwords and manage group membership. Similar to <code>/etc/group</code>, it contains one entry per line for each group, but with a focus on security-sensitive information.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711702503796/f68c1311-7d45-4226-a63d-f80b5439a942.png" alt class="image--center mx-auto" /></p>
</li>
</ul>
<h2 id="heading-other-common-groups">Other Common Groups</h2>
<p>There are several common group names you might encounter in Linux:</p>
<ul>
<li><p><strong>sudo</strong> – A member of this group can use the <a target="_blank" href="https://karlygash-yakiyayeva.dev/linux-sudo-command-explained">sudo command</a> to elevate their privileges</p>
</li>
<li><p><strong>cdrom</strong> – Allows the user to mount the optical drive</p>
</li>
<li><p><strong>adm</strong> – Allows the user to monitor Linux system logs</p>
</li>
<li><p><strong>lpadmin</strong> – Allows the user to configure printers</p>
</li>
<li><p><strong>plugdev</strong> – Allows the user to access external storage devices</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711733578679/1f6d51db-ab5d-47ac-ac29-774d9105bee6.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-hands-on-exercise-overview">Hands-on Exercise Overview</h2>
<p>This hands-on shows:</p>
<ul>
<li><p>how to add, delete, and modify groups;</p>
</li>
<li><p>how to add users to and remove from the existing groups.</p>
</li>
</ul>
<h2 id="heading-hands-on-exercise">Hands-on Exercise</h2>
<ol>
<li><p>To find out which groups a user is a member of, run:</p>
<pre><code class="lang-bash"> groups
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711707354813/856afb5a-19c7-4b93-93b6-cab356855cfb.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To find out which groups another user is a member of, run:</p>
<pre><code class="lang-bash"> groups username
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711707421699/1099476c-6589-4b41-9fe5-667b49f2baa2.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To create a new group in Linux, run:</p>
<pre><code class="lang-bash"> sudo groupadd groupname
</code></pre>
</li>
<li><p>To confirm the new group is in the Linux <em>/etc/group</em> file:</p>
<pre><code class="lang-bash"> getent group groupname
</code></pre>
<ul>
<li><p><code>getent</code>: The command used to retrieve entries from databases configured in the system.</p>
</li>
<li><p><code>group</code>: This specifies the database to query. In this case, <code>group</code> refers to the group database, which contains information about the groups on the system.</p>
</li>
<li><p><code>groupname</code>: This is the name of the group you want to query.</p>
</li>
</ul>
</li>
</ol>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711707955816/20369651-a79a-42ae-86bb-61cb09334161.png" alt class="image--center mx-auto" /></p>
    <div data-node-type="callout">
    <div data-node-type="callout-emoji">💡</div>
    <div data-node-type="callout-text">When you create a new group, it’s a normal group with GID higher than 1000. You can also create a system group that automatically takes a group ID between SYS_GID_MIN and SYS_GID_MAX as defined in <code>/etc/login.defs</code>.</div>
    </div>

<ol start="5">
<li><p>To create a system group, run</p>
<pre><code class="lang-bash"> sudo groupadd -r groupname
</code></pre>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">System groups are created for system purposes, such as running system services or daemon processes. They help in managing permissions and access rights for system processes and files.</div>
 </div>

<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711731547747/401b29aa-2ba1-4299-8a8c-d84c981a89f8.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To modify a group name, use the <code>groupmod</code> command:</p>
<pre><code class="lang-bash"> sudo groupmod -n new-name old-name
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711732423406/ff1248b7-16e6-41c7-a94e-b7934a1e237a.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To add a user to an existing group while keeping them in their current groups, use the <code>usermod</code> command with the <code>-a</code> (append) and <code>-G</code> (groups) options:</p>
<pre><code class="lang-bash"> sudo usermod -aG groupname username
</code></pre>
<p> Confirm if the user has been added by using the <code>groups</code> command.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711708450883/4b5c80e5-5932-42bf-9608-62d68aa7a1b2.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>An alternative for adding the user to an existing group is using the <code>gpasswd</code> command:</p>
<pre><code class="lang-bash"> sudo gpasswd -a username groupname
</code></pre>
<ul>
<li><p><code>gpasswd</code> - a command used for managing <code>/etc/group</code> and <code>/etc/gshadow</code> group files. It allows administrators to modify group passwords and memberships, including adding or removing users from groups and setting or changing group passwords.</p>
</li>
<li><p><code>-a</code>: Option that stands for "add", indicating that you want to add a user to a group.</p>
</li>
</ul>
</li>
</ol>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711709272134/7773ff2d-5335-4634-8dc2-0489e7f59c06.png" alt class="image--center mx-auto" /></p>
    <div data-node-type="callout">
    <div data-node-type="callout-emoji">💡</div>
    <div data-node-type="callout-text">After adding the current user to the specific group, that user must log in and log out for the changes to take effect.</div>
    </div>

<ol start="9">
<li><p>To remove a user from a specific group, use <code>gpasswd</code> command with <code>-d</code> option:</p>
<pre><code class="lang-bash"> sudo gpasswd -d username groupname
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711710387371/95db6966-6a6c-4442-b7e4-5214d27fed5c.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To delete a group, use the <code>groupdel</code> command:</p>
<pre><code class="lang-bash">sudo groupdel groupname
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711710687686/2aedbe60-21e4-44c2-b99d-fafedb093bc6.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">When a new file is created, the file will be created with the permissions that will include ownership of the primary group.</div>
</div>

<h2 id="heading-references">References</h2>
<ol>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=GnlgAD8-GhE&amp;t=977s">Linux Crash Course - Managing Groups</a></p>
</li>
<li><p><a target="_blank" href="https://phoenixnap.com/kb/user-management-linux#ftoc-heading-9">User Management in Linux by phoenixNAP</a></p>
</li>
<li><p><a target="_blank" href="https://linuxhandbook.com/groupadd-command/">Create New Groups in Linux With Groupadd Command</a></p>
</li>
<li><p><a target="_blank" href="https://karlygash-yakiyayeva.dev/linux-sudo-command-explained">Linux sudo command explained</a></p>
</li>
<li><p><a target="_blank" href="https://phoenixnap.com/kb/add-user-to-linux-group#ftoc-heading-13">How to Add a User to a Linux Group</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Managing Users in Linux]]></title><description><![CDATA[In a Linux system, users refer to individuals or entities that interact with the operating system by logging in and performing various tasks. Managing users in Linux is a fundamental aspect of system administration, allowing you to control access to ...]]></description><link>https://karlygash-yakiyayeva.dev/managing-users-in-linux</link><guid isPermaLink="true">https://karlygash-yakiyayeva.dev/managing-users-in-linux</guid><category><![CDATA[Linux]]></category><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[ #SystemAdministration ]]></category><category><![CDATA[users]]></category><category><![CDATA[user management]]></category><dc:creator><![CDATA[Karlygash Yakiyayeva]]></dc:creator><pubDate>Fri, 29 Mar 2024 06:41:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/SYTO3xs06fU/upload/7d0197bc377f9930da53e9eb3b9800bb.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In a Linux system, users refer to individuals or entities that interact with the operating system by logging in and performing various tasks. Managing users in Linux is a fundamental aspect of system administration, allowing you to control access to the system and its resources. Incorrectly set user permissions are a security vulnerability and, in some cases, may render the Linux system inoperable.</p>
<p>A user in Linux is associated with a user account, which consists of several properties defining their identity and privileges within the system. These properties are a username, UID (User ID), GID (Group ID), home directory, default shell, and password.</p>
<h2 id="heading-types-of-users-in-linux">Types of Users in Linux</h2>
<p>In Linux, users are categorized based on their roles, permissions, and the kind of access they have to the system's files and resources. Understanding the types of users is crucial for managing security and permissions on a Linux system. Here are the primary types of users found in Linux:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Account Type</td><td>Access Level</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Root User</strong></td><td>The root user, also known as the superuser, has <em>unrestricted</em> access to the system. This user can perform any operation, including tasks that can affect the system's operation and security. Because of the extensive capabilities, it's advised to use the root account only when necessary.</td></tr>
<tr>
<td><strong>System User</strong></td><td>System users are created to run specific system services and automated services. For example, a web server service might run as a <code>www-data</code> user, and a database service might run as a <code>mysql</code> user. These users <em>do not have login access</em> to the system and are used to isolate service permissions for security reasons. UID range is typically from 1 to 999 (but this can vary based on the distribution)</td></tr>
<tr>
<td><strong>Sudo User</strong></td><td>A standard user who has been granted permission to execute certain commands as the root user. Every command that requires root privileges must be preceded with the <a target="_blank" href="https://karlygash-yakiyayeva.dev/linux-sudo-command-explained">sudo command.</a></td></tr>
<tr>
<td><strong>Standard User</strong></td><td>Regular users are the standard accounts used by people to interact with the system. They have permissions to run programs, read files they own, and modify their home directories. They cannot perform actions that affect core system settings or other user accounts. The system administrator can elevate their permissions temporarily using <code>sudo</code> or <code>su</code> for specific tasks. Users with interactive login accounts are given a UID of 1000 and above;</td></tr>
<tr>
<td><strong>Guest User</strong></td><td>Guest users are temporary accounts with very limited access rights. They are typically used for single sessions and might have access only to basic applications and the internet. Their permissions are severely restricted to protect the system's integrity. They do not require personal files and settings.</td></tr>
</tbody>
</table>
</div><h2 id="heading-understanding-user-management-files">Understanding User Management Files</h2>
<p>In Linux, user management revolves around several key files that store information about users, their passwords, groups, and group passwords. These files are critical for system security and user management tasks. Here's an overview of these essential files:</p>
<ul>
<li><p><code>/etc/passwd</code> - The <em>passwd</em> file contains a list of user accounts and the corresponding user ID, group ID, home directory, and the default shell. It is readable by most users, but only root and sudo accounts can add new users or remove and modify existing user data.</p>
<p>  <img src="https://i.imgur.com/vO32IAD.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><code>/etc/shadow</code> - This file stores encrypted user password information and other password-related data such as the password expiration date, last change date, and account expiration date. It is only accessible by the root user or users with appropriate privileges. The restricted access and encryption add another security layer compared to the /<em>etc/passwd</em> file.</p>
<p>  <img src="https://i.imgur.com/1uOc43t.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><code>/etc/sudoers</code>- This file specifies which users have elevated permissions, on which machines, and for which directories. Admins can use this file to configure permissions for users and groups to use the sudo command.</p>
</li>
<li><p><code>/etc/skel</code>-The <em>skel</em> directory contains default configuration scripts and templates such as <em>.bashrc</em> and <em>bash_profile</em>. The templates are copied to the user's home directory when a new user is created, streamlining the provisioning of new user accounts.</p>
<p>  <img src="https://i.imgur.com/Er2NbJ3.png" alt class="image--center mx-auto" /></p>
</li>
</ul>
<h2 id="heading-best-practices-for-user-management-in-linux">Best Practices for User Management in Linux</h2>
<p>Effective user management in Linux is essential for maintaining system security, performance, and user accessibility. Here are some best practices in short:</p>
<ol>
<li><p>Avoid using the root account for daily tasks. Grant administrative privileges to trusted users via the <code>sudo</code> mechanism.</p>
</li>
<li><p>Follow the principle of least privilege (PoLP). Users should have only the permissions necessary for their roles.</p>
</li>
<li><p>Periodically review user accounts and remove or disable those that are no longer in use or are temporary.</p>
</li>
<li><p>Use strong password policies.</p>
</li>
<li><p>For temporary users or employees, set account expiration dates.</p>
</li>
<li><p>Keep track of user activities, especially for users with <code>sudo</code> privileges. Tools like <code>auditd</code> can be configured to monitor and report on specific user actions.</p>
</li>
<li><p>As users change roles within an organization, regularly update their group memberships and permissions to reflect their current needs.</p>
</li>
<li><p>Educate users about security best practices, including password security, phishing awareness, and safe internet usage.</p>
</li>
<li><p>Regularly backup user data and configuration files. This includes home directories and critical system files like <code>/etc/passwd</code> and <code>/etc/shadow</code>.</p>
</li>
<li><p>For environments with multiple Linux systems, consider centralizing user management using LDAP, Active Directory integration, or other directory services to streamline the process.</p>
</li>
</ol>
<h2 id="heading-hands-on-exercise-overview">Hands-on Exercise Overview</h2>
<p>Linux, being a multi-user system, provides a comprehensive set of tools and commands for user management. This hands-on shows how to add, modify, and remove a user on Ubuntu 20.04.</p>
<h2 id="heading-hands-on-exercise">Hands-on Exercise</h2>
<ol>
<li><p>To find out which users and how many users you have on the server, run:</p>
<pre><code class="lang-bash"> cat /etc/passwd | wc -l
</code></pre>
</li>
<li><p>To determine which users are currently logged in a Linux system, use:</p>
<pre><code class="lang-bash"> who -H
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711476904464/27899413-5bff-4bb3-b27e-0b5e4fbb5887.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To create a new user, run:</p>
<pre><code class="lang-bash"> sudo useradd username
</code></pre>
<p> Root privileges are required when adding a new user to the system because system-wide changes happen. The command does not provide any output.</p>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">By default, <code>useradd</code> command adds normal user accounts.</div>
 </div>
</li>
<li><p>To verify if the new user is visible, run:</p>
<pre><code class="lang-bash"> cat /etc/passwd | grep username
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711477369986/6fec2c49-f137-4c63-a596-05207b422d31.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To add a <em>system</em> user, add the <code>-r</code> option:</p>
<pre><code class="lang-bash"> sudo useradd -r sysuser
</code></pre>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">The system user is useful when you automate any tasks. It does not log in interactively and is used for running in the background and scheduling tasks and processes. Desktop distributions will not show a system user on the login screen because if it did show, there would be a mess.</div>
 </div>
</li>
<li><p>To add a user with a home directory, use the <code>-m</code> option:</p>
<pre><code class="lang-bash"> sudo useradd -m username
 ls -l /home/
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711479323207/af8dc505-53be-423e-a8e5-5f75d3af19fc.png" alt class="image--center mx-auto" /></p>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">Always use the <code>-m</code> option with <code>useradd</code> if you want the home directory to be created automatically. Some distributions might have defaults that automatically create the home directory, but it's good practice to explicitly use the <code>-m</code> option to ensure consistency across different environments.</div>
 </div>
</li>
<li><p>Each Linux distribution can set its own default values for the <code>useradd</code> command. These defaults are typically configured in the:</p>
<pre><code class="lang-bash"> cat /etc/default/useradd
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711478610661/6da42b34-813e-470b-9618-b2c85249b91a.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To modify various attributes of an existing user account in Linux, use <code>usermod</code> command. Visit for more information: <a target="_blank" href="https://karlygash-yakiyayeva.dev/linux-usermod-command-explained">Linux usermod Command Explained</a></p>
</li>
<li><p>To remove a user account, use:</p>
<pre><code class="lang-bash"> sudo userdel username
</code></pre>
<p> When a user is deleted from the system, its home directory is not deleted by default.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711480138407/cf0ffe36-006a-4e23-a643-41feeca2eccc.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To remove a user account with its home directory, use <code>-r</code> option:</p>
<pre><code class="lang-bash">sudo userdel -r username
</code></pre>
</li>
</ol>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Comply with the company policy about user data retention when the user leaves the company.</div>
</div>

<ol start="12">
<li><p>To change the password for another user, run:</p>
<pre><code class="lang-bash">sudo passwd username
</code></pre>
<p>Since root privileges are accessed, the current password of the user is not asked.</p>
</li>
</ol>
<h2 id="heading-references">References</h2>
<ol>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=19WOD84JFxA">Linux Crash Course - Managing Users</a></p>
</li>
<li><p><a target="_blank" href="https://phoenixnap.com/kb/user-management-linux#ftoc-heading-3">Linux sudo command explained</a></p>
</li>
<li><p><a target="_blank" href="https://phoenixnap.com/kb/user-management-linux">User Management in Linux</a></p>
</li>
<li><p><a target="_blank" href="https://karlygash-yakiyayeva.dev/linux-usermod-command-explained">Linux usermod Command Explained</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Scheduling Tasks with Cron]]></title><description><![CDATA[Cron is a time-based job scheduling daemon found in Unix-like operating systems, including Linux. It enables users to schedule jobs (commands or scripts) to run periodically at fixed times, dates, or intervals. These scheduled jobs are known as cron ...]]></description><link>https://karlygash-yakiyayeva.dev/scheduling-tasks-with-cron</link><guid isPermaLink="true">https://karlygash-yakiyayeva.dev/scheduling-tasks-with-cron</guid><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[Linux]]></category><category><![CDATA[cronjob]]></category><category><![CDATA[System administration]]></category><dc:creator><![CDATA[Karlygash Yakiyayeva]]></dc:creator><pubDate>Wed, 20 Mar 2024 09:48:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/zni0zgb3bkQ/upload/ece2b9b28ccd867534ad1f440d68f508.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a target="_blank" href="https://en.wikipedia.org/wiki/Cron">Cron</a> is a time-based job scheduling daemon found in Unix-like operating systems, including Linux. It enables users to schedule jobs (commands or scripts) to run periodically at fixed times, dates, or intervals. These scheduled jobs are known as cron jobs.</p>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Cron#:~:text=source%C2%A0needed%5D-,Overview,-%5Bedit%5D">Crontab</a> (Cron Table) is a configuration file that specifies the schedule of cron jobs. It contains commands to be executed along with their scheduled times. Each user on a system can have their crontab file, typically at <strong>/var/spool/cron/crontabs/</strong>, and there is also a system-wide crontab at <strong>/etc/crontab</strong>.</p>
<h2 id="heading-how-cron-works">How 'cron' Works</h2>
<p>Under the hood, the cron system is relatively simple yet powerful, and it operates by regularly checking for scheduled tasks and executing them at the specified times.</p>
<p>The <a target="_blank" href="https://en.wikipedia.org/wiki/Cron#:~:text=Multi%2Duser%20capability">algorithm</a> used by cron is as follows:</p>
<ol>
<li><p>On start-up, the cron daemon (<code>crond</code>) looks for the crontab files.</p>
</li>
<li><p>For each crontab file found, determine the next time in the future that each command must run.</p>
</li>
<li><p>Place those commands on the event list with their corresponding time and their "five field" time specifier.</p>
</li>
<li><p>Enter main loop:</p>
<ol>
<li><p>Examine the task entry at the head of the queue, and compute how far in the future it must run.</p>
</li>
<li><p>Sleep for that period of time.</p>
</li>
<li><p>On awakening and after verifying the correct time, execute the task at the head of the queue (in the background) with the privileges of the user who created it.</p>
</li>
<li><p>Determine the next time in the future to run this command and place it back on the event list at that time value.</p>
</li>
</ol>
</li>
</ol>
<h3 id="heading-understanding-crontab-format"><strong>Understanding Crontab Format</strong></h3>
<p>The crontab file is composed of lines of comments and cron jobs and looks as follows:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710750377148/ef8aa402-fd89-454b-a9e8-972059aaf76e.png" alt class="image--center mx-auto" /></p>
<p>Comments begin with a comment mark <code>#</code>, and must be on a line by themselves.</p>
<p>The syntax of a cron job line in a crontab file must use the following format:</p>
<blockquote>
<p>MIN HOUR DOM MON DOW CMD</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710751957394/90913bff-69bc-462d-8016-8a33459ddd52.png" alt class="image--center mx-auto" /></p>
<p>The first five fields, each separated by a single space, represent time intervals and tell Cron when to initiate the cron job. These fields are followed by the command (<strong>CMD</strong>), which is usually a path to a script or a system command.</p>
<p><strong>Cron expression examples:</strong></p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Syntax</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td><code>7 * * * *</code></td><td>The cron job is initiated every time the system clock shows 7 in the minute's position.</td></tr>
<tr>
<td><code>0 7 * * *</code></td><td>The cron job runs any time the system clock shows 7 AM (7 PM would be coded as 19).</td></tr>
<tr>
<td><code>0 0 7 * *</code></td><td>The <em>Day of the Month</em> is 7, which means that the job runs every 7<sup>th</sup> day of the month.</td></tr>
<tr>
<td><code>0 0 0 7 *</code></td><td>The numerical <em>Month</em> is 7, which determines that the job runs only in July. The <em>Month</em> field value can be a number or a month abbreviation.</td></tr>
<tr>
<td><code>0 0 * * 7</code></td><td>7 in the current position means that the job would only run on Sundays. The <em>Day of the Week</em> field can be a number or the day abbreviation.</td></tr>
<tr>
<td><code>0 9-17 * * 1-5</code></td><td>Hyphens are used to define ranges. For example, place <code>9-17</code> in the Minutes field and <code>1-5</code> in the <em>Day of the Week</em> field for a job to run from Monday to Friday - Every Hour 9 AM to 5 PM.</td></tr>
<tr>
<td><code>0 4 * * 2,4</code></td><td>Commas are used to separate items of a list. For example, to run a job at 4 AM on Tuesdays and Thursdays, place <code>2,4</code> in the <em>Days of the Week</em> column.</td></tr>
<tr>
<td><code>* /20 * * *</code></td><td>Slashes can be combined with ranges to specify step values. For example, <code>*/20</code> in the <em>Minutes</em> field runs a job every twenty minutes.</td></tr>
</tbody>
</table>
</div><p><strong>Nonstandard predefined scheduling definitions:</strong></p>
<p>Some cron implementations support the following non-standard macros:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Syntax</td><td>Entry</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td><code>0 0 1 1 *</code></td><td><code>@yearly</code> (or <code>@annually</code>)</td><td>Run once a year at midnight of 1 January</td></tr>
<tr>
<td><code>0 0 1 * *</code></td><td><code>@monthly</code></td><td>Run once a month at midnight of the first day of the month</td></tr>
<tr>
<td><code>0 0 * * 0</code></td><td><code>@weekly</code></td><td>Run once a week at midnight on Sunday</td></tr>
<tr>
<td><code>0 0 * * *</code></td><td><code>@daily</code> (or <code>@midnight</code>)</td><td>Run once a day at midnight</td></tr>
<tr>
<td><code>0 * * * *</code></td><td><code>@hourly</code></td><td>Run once an hour at the beginning of the hour</td></tr>
<tr>
<td></td><td><code>@reboot</code></td><td>Run at startup</td></tr>
</tbody>
</table>
</div><h3 id="heading-crontab-commands"><strong>Crontab Commands</strong></h3>
<ol>
<li><p>To edit your crontab file, run:</p>
<pre><code class="lang-bash"> crontab -e
</code></pre>
</li>
<li><p>To list your current cron jobs, run:</p>
<pre><code class="lang-bash"> crontab -l
</code></pre>
</li>
<li><p>To remove your crontab file, run:</p>
<pre><code class="lang-bash"> crontab -r
</code></pre>
</li>
<li><p>To edit another user's crontab (requires superuser privileges), run:</p>
<pre><code class="lang-bash"> sudo crontab -u username -e
</code></pre>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">The direct editing of user crontab files in <code>/var/spool/cron/crontabs/</code> is typically restricted to the system's cron service and should not be edited manually. Permissions are set to prevent unauthorized access. For managing cron jobs, the <code>crontab</code> utility provides a safe and standardized way for users to edit their cron schedules.</div>
 </div>


</li>
</ol>
<h3 id="heading-examples-of-cron-jobs"><strong>Examples of Cron Jobs</strong></h3>
<ol>
<li><p>To run a script every Monday at 6:30 AM:</p>
<pre><code class="lang-bash"> 30 6 * * 1 /path/to/script.sh
</code></pre>
</li>
<li><p>To delete temporary files every hour:</p>
<pre><code class="lang-bash"> 0 * * * * /bin/rm -rf /tmp/*
</code></pre>
</li>
<li><p>To check disk space usage and email the results every Sunday at 7 PM:</p>
<pre><code class="lang-bash"> 0 19 * * 0 df -h | mail -s <span class="hljs-string">"Disk Space Report"</span> user@example.com
</code></pre>
</li>
</ol>
<h3 id="heading-tips-for-writing-cron-jobs"><strong>Tips for Writing Cron Jobs</strong></h3>
<ol>
<li><p>Specify full paths to files and programs because cron jobs run in a limited environment, meaning that many of the environmental variables available in a full-user session might not be present. Also, it helps to prevent accidental or malicious execution of the wrong program.</p>
</li>
<li><p>By default, cron sends the output of jobs via email to the user's account. If you don't want this, redirect the output to a file or <code>/dev/null</code>.</p>
</li>
<li><p>Before setting up a <code>cron</code> task, run your script or command to see if you have any problems with permissions or paths.</p>
</li>
<li><p>If too many jobs run at the same time — especially the backups and compiles —the system would run out of RAM and nearly fill the swap file. As a result, the system thrashes and the performance decreases, so nothing gets done. In such a case, add more memory and improve how tasks are scheduled.</p>
</li>
<li><p>Remove a task that is poorly written and use large amounts of memory.</p>
</li>
</ol>
<p>The <code>crond</code> service assumes that the host computer runs all the time. That means that if the computer is turned off during a period when cron jobs were scheduled to run, they will not run until the next time they are scheduled. This might cause problems if they are critical cron jobs. Fortunately, there is another option for running jobs at regular intervals: <strong>anacron</strong>.</p>
<h2 id="heading-anacron"><strong>anacron</strong></h2>
<p>The <a target="_blank" href="https://en.wikipedia.org/wiki/Anacron">anacron</a> program performs the same function as <code>crond</code>, but it adds the ability to run skipped jobs, such as if the computer was off or otherwise unable to run the job for one or more cycles. This is very useful for laptops and other computers that are turned off or put into sleep mode.</p>
<p>As soon as the computer is turned on and booted, anacron checks to see whether configured jobs missed their last scheduled run. If they have, those jobs run immediately, but only once (no matter how many cycles have been missed). For example, if a weekly job did not run for three weeks because the system was shut down while you were on vacation, it would be run soon after you turn the computer on, but only once, not three times.</p>
<h2 id="heading-references">References:</h2>
<ol>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=7cbP7fzn0D8&amp;t=161s">Linux Crash Course - Scheduling Tasks with Cron</a></p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Cron">Wikipedia: cron</a></p>
</li>
<li><p><a target="_blank" href="https://opensource.com/article/17/11/how-use-cron-linux#comments">How I use cron in Linux</a></p>
</li>
<li><p><a target="_blank" href="https://www.redhat.com/sysadmin/linux-cron-command">How to schedule jobs using the Linux 'cron' utilit</a>y</p>
</li>
<li><p><a target="_blank" href="https://phoenixnap.com/kb/set-up-cron-job-linux">How to Create and Set Up a Cron Job in Linux</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Public Key Authentication in Linux]]></title><description><![CDATA[The motivation for using public key authentication over simple passwords is security. Public key authentication provides cryptographic strength that even extremely long passwords can not offer. With SSH, public key authentication improves security co...]]></description><link>https://karlygash-yakiyayeva.dev/public-key-authentication-in-linux</link><guid isPermaLink="true">https://karlygash-yakiyayeva.dev/public-key-authentication-in-linux</guid><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[ssh]]></category><category><![CDATA[Cryptography]]></category><category><![CDATA[Linux]]></category><dc:creator><![CDATA[Karlygash Yakiyayeva]]></dc:creator><pubDate>Mon, 18 Mar 2024 11:57:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/0TORZQnU0aI/upload/f00e19ebba6ac4910b13e0e9935433d8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The motivation for using public key <a target="_blank" href="https://kb.iu.edu/d/alqk">authentication</a> over simple passwords is security. <a target="_blank" href="https://www.ssh.com/academy/ssh/public-key-authentication">Public key authentication</a> provides cryptographic strength that even extremely long passwords can not offer. With <a target="_blank" href="https://www.ssh.com/ssh/"><strong>SSH</strong></a>, public key authentication improves security considerably as it frees the users from remembering complicated passwords (or worse yet, writing them down).</p>
<p>SSH public key authentication relies on asymmetric cryptographic algorithms that generate a pair of separate keys (a key pair), one "<strong><em>private</em></strong>" and the other "<strong><em>public</em></strong>". Keep the private key secret and store it on your local computer to connect to the remote system. Conceivably, share the public key with anyone without compromising the private key; you store it on the remote system in a <code>.ssh/authorized_keys</code> directory.</p>
<h2 id="heading-hands-on-exercise-overview">Hands-on Exercise Overview</h2>
<p>This hands-on exercise uses public key authentication to connect to the Ubuntu 20.04/Vagrant server by generating an SSH key pair on the local Ubuntu 22.04 machine. The connection between the local machine and the Ubuntu/Vagrant server is established using the <a target="_blank" href="https://github.com/karlakz/vagrant-templates/tree/main/ubuntu-in-bridge-mode">bridged mode</a> that allows the two machines to be in the same network.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710590978860/956e97f3-b238-49bf-b139-b65a105e1ca5.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-prerequisites">Prerequisites:</h2>
<p>To use SSH public key authentication:</p>
<ul>
<li><p>The remote and local systems must have OpenSSH installed.</p>
</li>
<li><p>You need to be able to transfer your public key to the remote system. Therefore, you must either be able to log into the remote system with an established account username and password/passphrase, or have an administrator on the remote system add the public key to the <code>~/.ssh/authorized_keys</code> file in your account.</p>
</li>
</ul>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">In Linux, it does not matter which distribution is used, every distribution comes preinstalled with SSH.</div>
</div>

<h2 id="heading-steps"><strong>Steps:</strong></h2>
<ol>
<li><p>Open the terminal (<strong>CTRL</strong>+<strong>ALT</strong>+<strong>T</strong>).</p>
</li>
<li><p>Verify that the ssh client is installed on the local machine:</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">which</span> ssh
</code></pre>
<p> OR</p>
<pre><code class="lang-bash"> ssh -V
</code></pre>
</li>
<li><p>Check for existing keys by listing the <code>ssh</code> directory with on the local machine:</p>
<pre><code class="lang-bash"> ls -l ~/.ssh
</code></pre>
<p> Generating new keys overwrites the current ones by default. However, indicating a new name for the keys saves them to different files.</p>
<p> If there are no existing keys, the output indicates the directory does not exist.</p>
<p> If some keys are found, they should be backed up before continuing.</p>
</li>
<li><p>Generate a key pair with <code>ssh-keygen</code>:</p>
<pre><code class="lang-bash"> ssh-keygen -b 4096
</code></pre>
<ul>
<li><p><code>ssh-keygen</code> is the tool used to create SSH keys, which are used for secure communication between machines.</p>
</li>
<li><p><code>-b</code> specifies the number of bits in the key to create. More bits generally mean better security.</p>
</li>
<li><p><code>4096</code> is the number of bits in the key. This is considered a good balance between security and performance for most SSH applications.</p>
</li>
</ul>
</li>
</ol>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710502786551/43eb8981-20da-4764-90c4-f5c49910fbe6.png" alt class="image--center mx-auto" /></p>
<ol start="5">
<li><p>Verify the key pair exists:</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710503010782/521d45f7-2825-4d59-b264-693e780c5497.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>View the public key:</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710503992549/c312fff7-ee1f-490c-a033-73a6077d963b.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Check whether the server works by connecting to it first:</p>
<pre><code class="lang-bash"> ssh username@ip_address
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710505402017/de006138-77eb-47f4-a55d-96adfba288a9.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Add the public key to the server by copying it manually or using the <code>ssh-copy-id</code> tool:</p>
<pre><code class="lang-bash"> ssh-copy-id username@ip_address
</code></pre>
</li>
<li><p>Public keys are in the <code>~/.ssh/authorized_keys</code> file and every time a new public is added, it appears as a new one line.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710504234970/9c12372d-7526-45f4-910f-e5cf4b78ab6d.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Now, connect to the server from the local machine by using the SSH private key and check whether the public key authentication works:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710505492184/5a3590c0-b0c9-4472-a40b-0d86190d1261.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<h2 id="heading-references">References:</h2>
<ol>
<li><p><a target="_blank" href="https://kb.iu.edu/d/aews"><strong>Set up SSH public key authentication to connect to a remote system</strong></a></p>
</li>
<li><p><a target="_blank" href="https://kb.iu.edu/d/alqk"><strong>About authentication</strong></a></p>
</li>
<li><p><a target="_blank" href="https://www.ssh.com/academy/ssh/public-key-authentication"><strong>What is SSH Public Key Authentication?</strong></a></p>
</li>
<li><p><a target="_blank" href="https://www.digitalocean.com/community/tutorials/how-to-configure-ssh-key-based-authentication-on-a-linux-server">How To Configure SSH Key-Based Authentication on a Linux Server</a></p>
</li>
<li><p><a target="_blank" href="https://www.ibm.com/docs/en/db2/11.1?topic=profile-setting-up-public-key-authentication-over-ssh">Setting up public key authentication over SSH</a></p>
</li>
<li><p><a target="_blank" href="https://www.linode.com/docs/guides/use-public-key-authentication-with-ssh/">Use SSH Public Key Authentication on Linux, macOS, and Windows</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[User Account and Password Expiration in Linux]]></title><description><![CDATA[The chage command, an abbreviation for “change age,” in Linux is used to view and modify user password expiry information. This command is particularly useful for system administrators who need to manage password policies across users in a Linux envi...]]></description><link>https://karlygash-yakiyayeva.dev/user-account-and-password-expiration-in-linux</link><guid isPermaLink="true">https://karlygash-yakiyayeva.dev/user-account-and-password-expiration-in-linux</guid><category><![CDATA[passwd]]></category><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[Linux]]></category><category><![CDATA[#LinuxAdministrator]]></category><category><![CDATA[chage Command]]></category><dc:creator><![CDATA[Karlygash Yakiyayeva]]></dc:creator><pubDate>Wed, 13 Mar 2024 12:23:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/dk4en2rFOIE/upload/5103311ba55e0141717a7da8f4f594b8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a target="_blank" href="https://man7.org/linux/man-pages/man1/chage.1.html">The <code>chage</code> command</a>, an abbreviation for “change age,” in Linux is used to view and modify user password expiry information. This command is particularly useful for system administrators who need to manage password policies across users in a Linux environment. It is important to keep an eye on the people who are using the servers and make sure that any accounts that are not needed are closed down or locked and passwords expire. By using <code>chage</code>, administrators can enforce security policies requiring users to change their passwords after a certain period, thus enhancing the overall system security.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">The <code>chage</code> command is restricted to the <strong>root</strong> user, except for the <code>-l</code> option, which may be used by an unprivileged user to determine when their password or account is due to expire.</div>
</div>

<h2 id="heading-hands-on-exercise">Hands-on Exercise</h2>
<ol>
<li><p>To view the current password expiry information for a user, use:</p>
<pre><code class="lang-bash"> sudo chage -l username
</code></pre>
<p> <img src="https://i.imgur.com/mPPt0sK.png" alt class="image--center mx-auto" /></p>
<ul>
<li><code>-l, --list</code> - shows account aging information. This will display various information like the last password change date, password expiry date, password inactive period, account expiry date, etc.</li>
</ul>
</li>
<li><p>To set the maximum number of days during which a password is valid:</p>
<pre><code class="lang-bash"> sudo chage -M days username
</code></pre>
<p> <img src="https://i.imgur.com/FuW9xNX.png" alt class="image--center mx-auto" /></p>
<p> This allows to ensure that a user must change their password every 30 days.</p>
</li>
<li><p>To set a minimum number of days between password changes:</p>
<pre><code class="lang-bash"> sudo chage -m days username
</code></pre>
<p> <img src="https://i.imgur.com/C9W0lyO.png" alt class="image--center mx-auto" /></p>
<p> Following this command, once the user ‘karla’ changes its password, she will have to wait for a minimum of 20 days before they are allowed to change it again.</p>
</li>
<li><p>To start warning a user N days before their password expires, use:</p>
<pre><code class="lang-bash"> sudo chage -W days username
</code></pre>
<p> <img src="https://i.imgur.com/eUjHcfu.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To ensure an account is automatically disabled after a certain date, for example, at the end of a contract or project, set:</p>
<pre><code class="lang-bash"> sudo chage -E YYYY-MM-DD username
</code></pre>
<p> <img src="https://i.imgur.com/p37CLqF.png" alt class="image--center mx-auto" /></p>
<p> After the specified date, the user ‘karla’ will not be able to access her account.</p>
</li>
<li><p>To set the number of days of inactivity after a password has expired before the account is locked, use the <code>-I</code> option. For example, to lock the ‘karla’ account if its password is not changed within 10 days after its expiry, use:</p>
<pre><code class="lang-bash"> sudo chage -I 10 karla
</code></pre>
<p> <img src="https://i.imgur.com/3TifW30.png" alt class="image--center mx-auto" /></p>
<p> This policy ensures that inactive accounts are locked after a certain period, providing an additional layer of security.</p>
</li>
<li><p>The <code>chage</code> command also has an <em>interactive mode</em>, which can be used by not specifying any options. In this mode, the command will prompt you for all the information it needs. To enter the interactive mode, use:</p>
<pre><code class="lang-bash"> sudo chage karla
</code></pre>
<p> <img src="https://i.imgur.com/D5wvRi2.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To remove the password expiry for a certain user, use the <code>-M</code> option with a value of <code>-1</code>:</p>
<pre><code class="lang-bash"> sudo chage -M -1 username
</code></pre>
<p> <img src="https://i.imgur.com/HmTi4py.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To remove account expiration for a certain user, similar to password expiration, use the <code>-E</code> option and passing <code>-1</code> as the value:</p>
<pre><code class="lang-bash"> sudo chage -E -1 username
</code></pre>
<p> <img src="https://i.imgur.com/rvByLsA.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<h2 id="heading-exit-codes">Exit Codes</h2>
<p><a target="_blank" href="https://man7.org/linux/man-pages/man1/chage.1.html#:~:text=EXIT%20VALUES%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20top">The <code>chage</code> command</a> exits with the following values:</p>
<ul>
<li><p>0 - success;</p>
<p>  <img src="https://i.imgur.com/OUxiq1i.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>1 - permission denied;</p>
<p>  <img src="https://i.imgur.com/S7f8wK3.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>2 - invalid command syntax;</p>
<p>  <img src="https://i.imgur.com/oJb5Cyf.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>15 - cannot find the shadow password file</p>
</li>
</ul>
<h2 id="heading-the-passwd-command">The <code>passwd</code> Command</h2>
<p>There is another command that is not related to <code>chage</code> command. It is a <code>passwd</code> command which changes passwords for user accounts. Its primary use is for changing passwords rather than managing detailed aspects of password policies. It's the command used for regular password updates or if an account's password needs to be reset for security reasons. A normal user may only change the password for their own account, while the superuser may change the password for any account.</p>
<ol>
<li><p>To lock a certain user, use:</p>
<pre><code class="lang-bash"> sudo passwd -l username
</code></pre>
<p> <img src="https://i.imgur.com/hYpSamT.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To view the password status of the named account, use:</p>
<pre><code class="lang-bash"> sudo passwd -S username
</code></pre>
<p> <img src="https://i.imgur.com/K9b2Hyp.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>To unlock a certain user, use:</p>
<pre><code class="lang-bash"> sudo passwd -u username
</code></pre>
<p> <img src="https://i.imgur.com/JEukBaW.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The <code>chage</code> command is essential for maintaining security and compliance within a Linux environment. By enforcing regular password changes and setting minimum and maximum password ages, organizations can significantly reduce the risks associated with stale or compromised passwords. Additionally, the ability to disable accounts automatically helps manage access for temporary users or contractors, ensuring that only current, authorized users can access system resources.</p>
<p>While <code>passwd</code> plays a critical role in password management, its capabilities regarding the direct setting of account and password expiration dates are limited. For detailed management of password and account expiration policies, including setting specific expiration dates, use the <code>chage</code> command for password-related settings and <code>usermod</code> for account expiration. These tools offer the granularity and control needed for effective user account management and security policy enforcement.</p>
<h2 id="heading-references">References:</h2>
<ol>
<li><p><a target="_blank" href="https://man7.org/linux/man-pages/man1/chage.1.html">chage(1) — Linux manual page</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=UYBPpaWUT64">Linux Crash Course - User Account &amp; Password Expiration</a></p>
</li>
<li><p><a target="_blank" href="https://www.linuxcapable.com/chage-command-in-linux/">chage Command in Linux with Examples</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Background and Foreground in Linux]]></title><description><![CDATA[In the context of Linux and Unix-like operating systems, foregrounding and backgrounding are concepts that relate to job control—a way of managing running processes from a shell (command line interface). When you run programs or commands in a shell, ...]]></description><link>https://karlygash-yakiyayeva.dev/background-and-foreground-in-linux</link><guid isPermaLink="true">https://karlygash-yakiyayeva.dev/background-and-foreground-in-linux</guid><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Bash]]></category><dc:creator><![CDATA[Karlygash Yakiyayeva]]></dc:creator><pubDate>Tue, 12 Mar 2024 04:58:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/h0Vxgz5tyXA/upload/f7749ee09dd2973fb3091650f7070ae3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the context of Linux and Unix-like operating systems, foregrounding and backgrounding are concepts that relate to job control—a way of managing running processes from a shell (command line interface). When you run programs or commands in a shell, they can be executed in either the foreground or the background, affecting how they interact with the terminal and the user.</p>
<p>It is recommended not to open multiple terminals in one server. Instead, foreground and background processes should be used.</p>
<h2 id="heading-background-processes"><strong>Background Processes</strong></h2>
<p><a target="_blank" href="https://www.digitalocean.com/community/tutorials/how-to-use-bash-s-job-control-to-manage-foreground-and-background-processes#managing-background-processes:~:text=CTRL%20%2B%20C%3A-,Managing%20Background%20Processes,-The%20main%20alternative">Running a process in the background</a> means that a process is still running but doesn't have control over the terminal. It is associated with the specific terminal that started it but does not block access to the shell. Instead, it executes in the background, leaving the user able to interact with the system while the command runs. This is particularly useful for long-running tasks that don't require immediate user interaction. For example, a long-running task like a large file download can be initiated in the background, freeing up the terminal for other commands.</p>
<p>Because background processes return control to the shell immediately without waiting for the process to complete, many background processes can run at the same time.</p>
<p>There are two ways to send a process to the background:</p>
<ol>
<li><p>Append <code>&amp;</code> to the end of the command to send it to the background immediately. For example, <code>cp largefile.txt backup &amp;</code> will copy the file while returning the terminal for other commands.</p>
</li>
<li><p>Press <code>Ctrl+Z</code> to suspend the running process. Then, type <code>bg</code> to send it to the background and resume execution.</p>
</li>
</ol>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Do not log out of the server before saving your changes in the background because backgrounding a process does not survive a logout of your shell.</div>
</div>

<h2 id="heading-foreground-processes"><strong>Foreground Processes</strong></h2>
<p>By default, <a target="_blank" href="https://www.digitalocean.com/community/tutorials/how-to-use-bash-s-job-control-to-manage-foreground-and-background-processes#managing-background-processes:~:text=your%20Linux%20skills.-,Managing%20Foreground%20Processes,-Most%20processes%20that">processes are started in the foreground</a>. This means that until the program exits or changes state, it is not allowed to interact with the shell as it takes control of the terminal. This means that the user can interact with the process directly.</p>
<p>For example, if a text editor is run from the command line without backgrounding it, the terminal becomes occupied by the text editor, and it can't be used for other commands until the text editor is closed.</p>
<p>Because of the way that a foreground process interacts with its terminal, there can be only a single foreground process for every terminal window.</p>
<h2 id="heading-job-identification"><strong>Job Identification</strong></h2>
<p>In a multitasking environment, multiple running processes in the background can be managed using job identifiers (job IDs) provided by the shell. The <code>jobs</code> command lists the running jobs and their statuses in the current shell session. A job can be a command or a pipeline of commands that are started as a single unit.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709995740491/7059a85c-f5b8-4041-985a-bbf805d09ef0.png" alt class="image--center mx-auto" /></p>
<p>Here's a breakdown of the typical output format:</p>
<ul>
<li><p><strong>Job Number</strong>: Each job is assigned a unique job number (e.g., <code>[1]</code>, <code>[2]</code>, <code>[3]</code>) for identification. This number is used when you want to refer to a specific job using other job control commands like <code>fg</code> (foreground) and <code>bg</code> (background).</p>
</li>
<li><p><strong>Current Job Indicators</strong>:</p>
<ul>
<li><p>The <code>+</code> sign indicates the current job, which is the most recent job that was put into the background or stopped.</p>
</li>
<li><p>The <code>-</code> sign indicates the previous job, which is the second most recent job that was manipulated.</p>
</li>
<li><p>Jobs without these indicators are neither the current nor the previous job.</p>
</li>
</ul>
</li>
<li><p><strong>State</strong>: This shows the current state of the job. Common states include:</p>
<ul>
<li><p><code>Running</code>: The job is actively running in the background.</p>
</li>
<li><p><code>Stopped</code>: The job has been suspended (e.g., by pressing <code>Ctrl+Z</code>). It is not currently running but can be resumed.</p>
</li>
<li><p><code>Done</code>: The job has been completed. It means the command finished its execution.</p>
</li>
</ul>
</li>
<li><p><strong>Command Name</strong>: This is the command or pipeline that constitutes the job. It shows what command the job is running or was running.</p>
</li>
</ul>
<h2 id="heading-hands-on-exercise-overview">Hands-on Exercise Overview</h2>
<p>This hands-on will focus on managing foreground and background processes and will demonstrate how to leverage your shell’s job control functions to gain more flexibility in how you run commands.</p>
<h3 id="heading-managing-foreground-processes">Managing Foreground Processes</h3>
<ol>
<li><p>Start a command that runs indefinitely and suspend it with <code>CTRL + Z</code>:</p>
<pre><code class="lang-bash"> htop
</code></pre>
<p> This utility will continue to run and update its display until it is terminated. Press <code>CTRL + Z</code> to suspend the running foreground process.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709989770479/b9738f18-e891-486f-97a6-495991971b10.png" alt class="image--center mx-auto" /></p>
<p> When pressing <code>CTRL + Z</code>, the terminal registers a “suspend” command, which then sends the SIGTSTP (signal terminal stop) signal to the foreground process. Essentially, this will pause the execution of the command and return control to the terminal.</p>
</li>
<li><p>Run <code>ping</code> command to connect to <a target="_blank" href="http://google.com"><code>google.com</code></a> every 5 seconds and terminate it with <code>CTRL + C</code>.</p>
<pre><code class="lang-bash"> ping -i 5 google.com
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709989949764/691c78b2-dd34-45a1-b8ea-e01d137073c0.png" alt class="image--center mx-auto" /></p>
<p> Linux terminals are usually configured to send the “SIGINT” signal (short for “signal interrupt”) to the current foreground process when the user presses the <code>CTRL + C</code> key combination. The SIGINT signal tells the program that the user has requested termination using the keyboard.</p>
</li>
</ol>
<h3 id="heading-managing-background-processes">Managing Background Processes</h3>
<ol start="3">
<li><p>To start the previous <code>ping</code> command as a background process, append a <code>&amp;</code> to the end of the command:</p>
<pre><code class="lang-bash"> ping -i 5 google.com &amp;
</code></pre>
<p> This tells the shell not to wait for the process to complete, but instead to begin execution and immediately return the user to a prompt. The output of the command will still display in the terminal (unless redirected<a target="_blank" href="https://www.digitalocean.com/community/tutorials/an-introduction-to-linux-i-o-redirection">),</a> but you can type additional commands as the background process continues.</p>
<p> The <code>bash</code> job control system will return output like this:</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709990320816/b16440e3-24ad-4be3-9d42-05bd45b35f9a.png" alt class="image--center mx-auto" /></p>
<p> You’ll then receive the normal output from the <code>ping</code> command:</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709990375978/611952c1-4ab0-4d22-b1bd-ae03f5396a53.png" alt class="image--center mx-auto" /></p>
<p> However, you can also type commands at the same time. The background process’s output will be mixed among the input and output of your foreground processes, but it will not interfere with the execution of the foreground processes.</p>
</li>
<li><p>To list all stopped or backgrounded processes, use the <code>jobs</code> command:</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">jobs</span>
</code></pre>
<p> If the previous <code>ping</code> command is still running in the background, the <code>jobs</code> command’s output will be similar to this:</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709991011973/c5984deb-67c2-4113-b6db-1d9e9f97a77c.png" alt class="image--center mx-auto" /></p>
<p> This indicates that you currently have two background processes, one is stopped and the second one is running. The <code>[1], [2]</code> represent the command’s <em>job spec</em> or job number. Reference this with other job and process control commands, like <code>kill</code>, <code>fg</code>, and <code>bg</code> by preceding the job number with a percentage sign. In this case, reference for instance, the second job as <code>%2</code>.</p>
</li>
<li><p>To stop a specific background process use the <code>kill</code> command with the associated job number.</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">kill</span> %2
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709991290028/432af8e2-54a4-41f1-867f-ffa2c8f94637.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<h3 id="heading-moving-processes-between-foreground-and-background">Moving Processes between Foreground and Background</h3>
<ol start="6">
<li><p>To move the currently running process to the background, first, the process must be stopped with <code>CTRL+Z</code>, and then <code>bg</code> command should be used to start it again in the background:</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">bg</span>
</code></pre>
<p> The job status line will be shown again, this time with the ampersand appended:</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709993903729/688b426f-a41f-4eda-94ea-a1cb8efd9357.png" alt class="image--center mx-auto" /></p>
<p> By default, the <code>bg</code> command operates on the most recently-stopped process. Because background processes return control to the shell immediately without waiting for the process to complete, many background processes can run at the same time. If multiple processes have been stopped in a row without starting them again, you can reference a specific process by its job number to move the correct process to the background.</p>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">Note that not all commands can be backgrounded. Some processes will automatically terminate if they detect that they have been started with their standard input and output directly connected to an active terminal.</div>
 </div>
</li>
<li><p>To move background processes to the foreground, type:</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">fg</span>
</code></pre>
<p> This operates on your most recently backgrounded process (indicated by the <code>+</code> in the <code>jobs</code> command’s output). It immediately suspends the process and puts it into the foreground. To specify a different job, use its job number:</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">fg</span> %2
</code></pre>
</li>
</ol>
<h2 id="heading-references">References:</h2>
<ol>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=HzsgkzCL9ow&amp;list=PLT98CRl2KxKHKd_tH3ssq0HPrThx2hESW&amp;index=8">Linux Crash Course: Background (bg) and Foreground (fg)</a></p>
</li>
<li><p><a target="_blank" href="https://www.ibm.com/docs/en/aix/7.2?topic=processes-">Processes</a></p>
</li>
<li><p><a target="_blank" href="https://www.digitalocean.com/community/tutorials/how-to-use-bash-s-job-control-to-manage-foreground-and-background-processes">How To Use Bash's Job Control to Manage Foreground and Background Processes</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Understanding Bash Aliases in Linux]]></title><description><![CDATA[In Linux, aliases are shortcuts that replace long or frequently used commands with shorter, more convenient ones, improving efficiency by speeding up the workflow and avoiding potential spelling errors. They can also replace commands with additional ...]]></description><link>https://karlygash-yakiyayeva.dev/understanding-bash-aliases-in-linux</link><guid isPermaLink="true">https://karlygash-yakiyayeva.dev/understanding-bash-aliases-in-linux</guid><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[Bash]]></category><category><![CDATA[Linux]]></category><category><![CDATA[alias]]></category><dc:creator><![CDATA[Karlygash Yakiyayeva]]></dc:creator><pubDate>Mon, 11 Mar 2024 07:09:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/ziXk5pV36nE/upload/7e1addbce4ecb87a044b51ce09cc51d9.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In Linux, <a target="_blank" href="https://phoenixnap.com/kb/linux-alias-command#:~:text=What%20Is%20an%20Alias%20in%20Linux%3F">aliases</a> are shortcuts that replace long or frequently used commands with shorter, more convenient ones, improving efficiency by speeding up the workflow and avoiding potential spelling errors. They can also replace commands with additional options, making them easier to use.</p>
<h2 id="heading-alias-benefits">Alias Benefits</h2>
<ul>
<li><p>Save time by typing less.</p>
</li>
<li><p>Improve command memorability through custom names.</p>
</li>
<li><p>Increase efficiency by automating repetitive tasks.</p>
</li>
</ul>
<h2 id="heading-linux-alias-syntax">Linux Alias Syntax</h2>
<p>To create an alias, use the <code>alias</code> command and its syntax as follows:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">alias</span> [name]=<span class="hljs-string">'[value]'</span>
</code></pre>
<ul>
<li><p><code>alias</code>: Invokes the <code>alias</code> command.</p>
</li>
<li><p><code>[name]</code>: the name of the alias is being created. This is what will be typed in the terminal instead of the full command. A name is a user-defined string, excluding special characters and <strong>'alias'</strong>, <strong>'unalias'</strong> keywords that cannot be used as names.</p>
</li>
<li><p><code>[value]</code>: the actual command that the alias represents. This can be a simple command or a more complex command chain. Commands can also include options, arguments, and variables.</p>
</li>
</ul>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>Note:</strong> Enclosing the value in single quotation marks (<strong>'</strong>) <strong>will not expand </strong>any variables used with the command. To expand the variables, use double quotation marks (<strong>"</strong>).</div>
</div>

<h2 id="heading-create-aliases-in-linux"><strong>Create Aliases in Linux</strong></h2>
<p>There are two types of aliases to create in Linux:</p>
<ul>
<li><p><strong>Temporary</strong>. Add them using the <code>alias</code> command.</p>
</li>
<li><p><strong>Permanent</strong>. These require editing the system files.</p>
</li>
</ul>
<h3 id="heading-create-a-temporary-alias">Create a Temporary Alias</h3>
<p>Aliases defined directly in the terminal are temporary and last only for the current terminal session. Use the <code>alias</code> command to create a temporary alias. For example, adding <code>move</code> as an alias for the <code>mv</code> command with the option of asking for confirmation before overwriting:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">alias</span> move=<span class="hljs-string">'mv -i'</span>
</code></pre>
<p>Another use for aliases is to create a shortcut for running scripts. To do this, provide the <a target="_blank" href="https://phoenixnap.com/glossary/absolute-path">absolute path to the scrip</a>t as the value:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">alias</span> frename=<span class="hljs-string">'Example/Test/file_rename.sh'</span>
</code></pre>
<p>In this example, using <code>frename</code> as a command runs the <code>file_rename.sh</code> bash script.</p>
<h3 id="heading-create-a-permanent-alias">Create a Permanent Alias</h3>
<p>To make an alias permanent, add it to the shell's configuration file, such as <code>~/.bashrc</code> or <code>~/.bash_profile</code>, and then source the file or restart your terminal. Depending on the type of shell you are using, use:</p>
<ul>
<li><p>Bash shell: <em>~/.bashrc</em></p>
</li>
<li><p>Zsh shell: <em>~/.zshrc</em></p>
</li>
<li><p>Fish shell: <em>~/.config/fish/config.fish</em></p>
</li>
</ul>
<p>Start by opening the shell configuration file in a text editor. In this example, we are using the Bash shell and vim text editor:</p>
<pre><code class="lang-bash">sudo vim ~/.bashrc
</code></pre>
<p>Scroll down until you find a section that lists default system aliases. For ease of use, create a separate section with a descriptive comment and add your aliases using the <code>alias</code> command syntax.</p>
<p>In our example:</p>
<pre><code class="lang-bash"><span class="hljs-comment">#Custom aliases</span>
<span class="hljs-built_in">alias</span> c=<span class="hljs-string">'clear'</span>;
<span class="hljs-built_in">alias</span> df=<span class="hljs-string">'df -h -x squashfs -x tmpfs -x devtmpfs'</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710081825534/698c44ca-b4cb-4bba-a0dc-6df713c68c8c.png" alt class="image--center mx-auto" /></p>
<p>Once all of the new aliases are added, press <strong>ESC,</strong> type <strong>:wq!</strong> to save the changes to the configuration file.</p>
<p>The new aliases automatically load in the next terminal session. If you want to use them in the current session, load the configuration file using the <code>source</code> command:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">source</span> ~/.bashrc
</code></pre>
<p>The output of the <code>df</code> command before creating an alias for it:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710082427680/5b7727b1-7a6d-4481-86a5-3487c8fc4272.png" alt class="image--center mx-auto" /></p>
<p>The output of the <code>df</code> command after creating an alias for it:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710082503420/4278631c-cfc0-438d-a2e8-0ec6ffb8522a.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-list-aliases-in-linux"><strong>List Aliases in Linux</strong></h2>
<p>Using the <code>alias</code> command on its own displays a list of all currently set aliases:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">alias</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710082843480/cbd470c4-4a65-4e58-b40e-dff5893ac283.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-remove-aliases-in-linux"><strong>Remove Aliases in Linux</strong></h2>
<p>To remove an alias, use the <code>unalias</code> command with the following syntax:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">unalias</span> [name]
</code></pre>
<p>Adding the <code>-a</code> option allows to remove all aliases:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">unalias</span> -a
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710083117013/4f8f8487-2c5f-498c-9c5f-a11a4cb85ae2.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-references">References:</h2>
<ol>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=Ok_kD_sgNcs&amp;list=PLT98CRl2KxKHKd_tH3ssq0HPrThx2hESW&amp;index=9"><strong>Linux Cra</strong></a><a target="_blank" href="https://phoenixnap.com/glossary/absolute-path"><strong>sh Course - B</strong></a><a target="_blank" href="https://www.youtube.com/watch?v=Ok_kD_sgNcs&amp;list=PLT98CRl2KxKHKd_tH3ssq0HPrThx2hESW&amp;index=9"><strong>ash Aliases</strong></a></p>
</li>
<li><p><a target="_blank" href="https://opensource.com/article/19/7/bash-aliases"><strong>Bash aliases you can’t live without</strong></a></p>
</li>
<li><p><a target="_blank" href="https://phoenixnap.com/kb/linux-alias-command">Linux alias Command: How to Use It With Examples</a></p>
</li>
<li><p><a target="_blank" href="https://phoenixnap.com/kb/linux-commands-cheat-sheet"><strong>Linux Commands Cheat Sheet</strong></a></p>
</li>
</ol>
]]></content:encoded></item></channel></rss>