<?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" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ RHEL - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ RHEL - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 26 May 2026 04:43:56 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/rhel/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Schedule Tasks in Red Hat Enterprise Linux ]]>
                </title>
                <description>
                    <![CDATA[ Red Hat Enterprise Linux (RHEL) is a leading enterprise-grade Linux distribution widely regarded as the gold standard for mission-critical server environments. It provides robust, secure, and scalable solutions for organizations ranging from small bu... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-schedule-tasks-in-red-hat-enterprise-linux/</link>
                <guid isPermaLink="false">685c9989f2073d62fe9b82f5</guid>
                
                    <category>
                        <![CDATA[ RHEL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Linux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ rhcsa ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Hang Hu ]]>
                </dc:creator>
                <pubDate>Thu, 26 Jun 2025 00:51:21 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750869114329/79072c41-988a-41f2-9e2f-25618d78fefc.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Red Hat Enterprise Linux (RHEL) is a leading enterprise-grade Linux distribution widely regarded as the gold standard for mission-critical server environments. It provides robust, secure, and scalable solutions for organizations ranging from small businesses to Fortune 500 companies, powering everything from web servers and databases to cloud infrastructure and containerized applications.</p>
<p>You can use RHEL's task scheduling capabilities in scenarios like automating system maintenance (for example, log rotation or backup operations), managing routine administrative tasks (like user account cleanup or security updates), or orchestrating complex workflows in enterprise environments. These scheduling tools are essential for maintaining system health and ensuring that critical operations run without manual intervention.</p>
<p>For system administrators, think of task scheduling as the backbone of automated system management, enabling you to set up processes that run reliably in the background while you focus on more strategic initiatives. Its power lies in its flexibility and reliability, making it an indispensable skill for anyone managing Linux systems in production environments.</p>
<p>In this tutorial, you’ll learn how to schedule tasks in Red Hat Enterprise Linux using various built-in tools and techniques. This content is part of <strong>Schedule Future Tasks</strong>, which is Chapter 2 of the <a target="_blank" href="https://labex.io/courses/red-hat-system-administration-rh134-labs">Red Hat System Administration (RH134) course</a>. RH134 is a fundamental course for the Red Hat Certified System Administrator (RHCSA) certification, one of the most respected credentials in the Linux administration field.</p>
<p>This hands-on tutorial provides practical experience with the scheduling concepts covered in the RH134 curriculum, giving you the skills needed to automate tasks effectively in enterprise RHEL environments.</p>
<h3 id="heading-heres-what-well-cover">Here's what we'll cover:</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-schedule-a-one-time-job-with-at">How to Schedule a One-time Job with 'at'</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-manage-at-jobs">How to Manage 'at' jobs</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-schedule-recurring-user-jobs-with-crontab">How to Schedule Recurring User Jobs with 'crontab'</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-manage-user-crontab-entries">How to Manage User 'crontab' Entries</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-schedule-recurring-system-jobs-with-cron-directories">How to Schedule Recurring System Jobs with cron Directories</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-configure-systemd-timers-for-recurring-tasks">How to Configure systemd Timers for Recurring Tasks</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-manage-temporary-files-with-systemd-tmpfiles">How to Manage Temporary Files with systemd-tmpfiles</a></p>
</li>
</ul>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>This tutorial is designed to be beginner-friendly! You just need basic familiarity with using the Linux command line. If you can navigate directories and run simple commands, you're ready to start.</p>
<p>For those looking to deepen their RHEL knowledge, the <a target="_blank" href="https://labex.io/skilltrees/rhel">RHEL Skill Tree</a> offers comprehensive hands-on labs including <a target="_blank" href="https://labex.io/courses/red-hat-system-administration-rh124-labs">RH124</a>, <a target="_blank" href="https://labex.io/courses/red-hat-system-administration-rh134-labs">RH134</a>, <a target="_blank" href="https://labex.io/courses/red-hat-enterprise-linux-automation-with-ansible-rh294">RH294</a>, and other courses for RHCSA and RHCE certifications.</p>
<p>Don't worry if you're new to Red Hat Enterprise Linux – I'll explain everything step by step, and these concepts work on most Linux distributions too.</p>
<h2 id="heading-how-to-schedule-a-one-time-job-with-at"><strong>How to Schedule a One-time Job with 'at'</strong></h2>
<p>First, let’s learn how to schedule a job to run once at a future time using the <code>at</code> command. The <code>at</code> command is useful for executing commands that don’t need to be run repeatedly. We will schedule a simple job, inspect its details, and then remove it.</p>
<p>In this tutorial, we will work directly on the local system to learn task scheduling. You’ll execute all commands in your current terminal environment.</p>
<p>Let's schedule a job to print the current date and time into a file named <code>~/myjob.txt</code> in your home directory. We'll schedule it to run 3 minutes from now:</p>
<pre><code class="lang-bash">at now + 3 minutes &lt;&lt; EOF
date &gt; ~/myjob.txt
EOF
</code></pre>
<p>The <code>warning: commands will be executed using /bin/sh</code> message is normal. The <code>job N at ...</code> output indicates the job number and the scheduled execution time. Make a note of the job number, as you will need it later.</p>
<p>Next, let's schedule another job interactively. This method is useful for entering multiple commands or more complex scripts. We will schedule a job to append "Hello from at job!" to <code>~/at_output.txt</code> 5 minutes from now:</p>
<pre><code class="lang-bash">at now + 5 minutes
</code></pre>
<p>After typing the command and pressing Enter, you will see an <code>at&gt;</code> prompt. Type your command and then press <code>Ctrl+d</code> to finish:</p>
<pre><code class="lang-bash">at &gt; <span class="hljs-built_in">echo</span> <span class="hljs-string">"Hello from at job!"</span> &gt;&gt; ~/at_output.txt
at &gt; Ctrl+d
</code></pre>
<p>To view the jobs currently in the <code>at</code> queue, use the <code>atq</code> command. This command lists all pending <code>at</code> jobs for the current user.</p>
<pre><code class="lang-bash">atq
</code></pre>
<p>The output will show the job number, the scheduled time, the queue, and the user who scheduled it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750726190789/d2dd54c0-80a0-4bb2-8561-3114bb279387.png" alt="Output of atq command showing scheduled jobs" class="image--center mx-auto" width="672" height="333" loading="lazy"></p>
<p>You can inspect the commands that a specific <code>at</code> job will run using the <code>at -c</code> command followed by the job number. Replace <code>N</code> with one of the job numbers you noted earlier.</p>
<pre><code class="lang-bash">at -c N
</code></pre>
<p>This command will display the shell script that <code>at</code> will execute for that job. You should see the <code>date &gt; ~/myjob.txt</code> or <code>echo "Hello from at job!" &gt;&gt; ~/at_output.txt</code> command within the output.</p>
<p>Finally, to remove a scheduled <code>at</code> job, use the <code>atrm</code> command followed by the job number. Let's remove the first job we scheduled. Replace <code>N</code> with the job number of your first job.</p>
<pre><code class="lang-bash">atrm N
</code></pre>
<p>After removing the job, you can use <code>atq</code> again to verify that it is no longer in the queue.</p>
<pre><code class="lang-bash">atq
</code></pre>
<p>You should now only see the second job (if it hasn't executed yet) or an empty queue if both jobs have been removed or executed.</p>
<p>This completes the first step of scheduling one-time jobs with the <code>at</code> command.</p>
<h2 id="heading-how-to-manage-at-jobs"><strong>How to Manage 'at' jobs</strong></h2>
<p>Now, let’s delve deeper into managing <code>at</code> jobs, including scheduling jobs with different queues and verifying their execution. Understanding <code>at</code> queues can be useful for prioritizing tasks or separating different types of one-time jobs.</p>
<p>We will continue working on the local system to explore more advanced <code>at</code> job management features.</p>
<p>The <code>at</code> command allows you to specify a queue using the <code>-q</code> option. Queues are single letters from <code>a</code> to <code>z</code>. Queue <code>a</code> is the default, and jobs in queues <code>a</code> through <code>z</code> are executed with decreasing niceness (priority). Queue <code>a</code> has the highest priority, and queue <code>z</code> has the lowest. Queue <code>b</code> is reserved for batch jobs.</p>
<p>Let's schedule a job in queue <code>g</code> (a lower priority queue) to run in 2 minutes. This job will create a file named <code>~/queue_g_job.txt</code> with a timestamp:</p>
<pre><code class="lang-bash">at -q g now + 2 minutes &lt;&lt; EOF
date &gt; ~/queue_g_job.txt
EOF
</code></pre>
<p>You will see output similar to <code>job N at ...</code>. Note down this job number.</p>
<p>Next, let's schedule another job, this time in queue <code>b</code> (batch queue), which is typically used for jobs that can run when system load is low. This job will append "Batch job executed!" to <code>~/batch_job.txt</code>. We'll schedule it to run 4 minutes from now:</p>
<pre><code class="lang-bash">at -q b now + 4 minutes &lt;&lt; EOF
<span class="hljs-built_in">echo</span> <span class="hljs-string">"Batch job executed!"</span> &gt;&gt; ~/batch_job.txt
EOF
</code></pre>
<p>Again, note down the job number.</p>
<p>To see all pending jobs, including those in different queues, use <code>atq</code>.</p>
<pre><code class="lang-bash">atq
</code></pre>
<p>You should now see both jobs listed, with their respective queue letters (<code>g</code> and <code>b</code>).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750726218380/bcc9d551-0530-48d1-bf7f-46073c6f77a6.png" alt="Output of atq command showing scheduled jobs" class="image--center mx-auto" width="589" height="325" loading="lazy"></p>
<p>Now, wait for your scheduled jobs to execute. Wait for at least 5 minutes to allow all jobs to complete. You can check if the files created by your <code>at</code> jobs exist and contain the expected content.</p>
<p>Check <code>~/queue_g_job.txt</code>:</p>
<pre><code class="lang-bash">cat ~/queue_g_job.txt
</code></pre>
<p>You should see a date and time string.</p>
<p>Check <code>~/batch_job.txt</code>:</p>
<pre><code class="lang-bash">cat ~/batch_job.txt
</code></pre>
<p>You should see "Batch job executed!".</p>
<p>If the files are not present or empty, it might mean the jobs haven't executed yet, or there was an issue with the command. You can re-check <code>atq</code> to see if they are still pending.</p>
<h2 id="heading-how-to-schedule-recurring-user-jobs-with-crontab"><strong>How to Schedule Recurring User Jobs with 'crontab'</strong></h2>
<p>Next, you’ll learn how to schedule recurring tasks for a specific user using <code>crontab</code>. Unlike <code>at</code> jobs, which run once, <code>cron</code> jobs run repeatedly at specified intervals. This is ideal for routine maintenance, data backups, or generating reports.</p>
<p>We will continue working on the local system to learn about user crontab management.</p>
<p>The <code>crontab</code> command allows users to create, edit, and view their own <code>cron</code> jobs. Each user has their own <code>crontab</code> file.</p>
<p>To edit your <code>crontab</code> file, use the <code>crontab -e</code> command. This will open your <code>crontab</code> file in the default text editor (usually <code>vim</code>).</p>
<pre><code class="lang-bash">crontab -e
</code></pre>
<p><strong>Vim editor instructions:</strong></p>
<ul>
<li><p>Press <code>i</code> to enter insert mode (you'll see <code>-- INSERT --</code> at the bottom)</p>
</li>
<li><p>Use arrow keys to navigate</p>
</li>
<li><p>To save and exit: Press <code>Esc</code> to exit insert mode, then type <code>:wq</code> and press <code>Enter</code></p>
</li>
<li><p>To exit without saving: Press <code>Esc</code>, then type <code>:q!</code> and press <code>Enter</code></p>
</li>
</ul>
<p>Inside the editor, you will add a new line to define your <code>cron</code> job. A <code>cron</code> entry has five time-and-date fields, followed by the command to be executed. The fields are:</p>
<ul>
<li><p><strong>Minute (0-59)</strong></p>
</li>
<li><p><strong>Hour (0-23)</strong></p>
</li>
<li><p><strong>Day of Month (1-31)</strong></p>
</li>
<li><p><strong>Month (1-12)</strong></p>
</li>
<li><p><strong>Day of Week (0-7, where 0 or 7 is Sunday)</strong></p>
</li>
</ul>
<p>You can use <code>*</code> as a wildcard to mean "every" for a field, or <code>/</code> to specify step values (for example, <code>*/5</code> for every 5 minutes).</p>
<p>Let's schedule a job that appends the current date and time to a file named <code>~/my_cron_log.txt</code> every minute. This will allow us to quickly observe the <code>cron</code> job in action.</p>
<p>Follow these steps in Vim:</p>
<ol>
<li><p>Press <code>i</code> to enter insert mode</p>
</li>
<li><p>Add the following line to the <code>crontab</code> file:</p>
</li>
</ol>
<pre><code class="lang-bash">* * * * * /usr/bin/date &gt;&gt; ~/my_cron_log.txt
</code></pre>
<ol start="3">
<li><p>Press <code>Esc</code> to exit insert mode</p>
</li>
<li><p>Type <code>:wq</code> and press <code>Enter</code> to save and exit</p>
</li>
</ol>
<p>You should see a message indicating that a new <code>crontab</code> has been installed:</p>
<pre><code class="lang-plaintext">crontab: installing new crontab
</code></pre>
<p>To verify that your <code>cron</code> job has been successfully added, you can list your <code>crontab</code> entries using the <code>crontab -l</code> command:</p>
<pre><code class="lang-bash">crontab -l
</code></pre>
<p>You should see the line you just added:</p>
<pre><code class="lang-plaintext">* * * * * /usr/bin/date &gt;&gt; ~/my_cron_log.txt
</code></pre>
<p>Now, wait for a minute or two to allow the <code>cron</code> job to execute at least once. You can check the current time to see when the next minute mark will occur:</p>
<pre><code class="lang-bash">date
</code></pre>
<p>After waiting for at least two minutes to allow the cron job to execute a couple of times, check the content of the <code>~/my_cron_log.txt</code> file.</p>
<pre><code class="lang-bash">cat ~/my_cron_log.txt
</code></pre>
<p>You should see one or more lines, each containing a date and time, indicating that your <code>cron</code> job has executed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750726409656/bfd85cf0-316a-4c1d-89c2-0d60c30cd33f.png" alt="Cron job output in log file" class="image--center mx-auto" width="607" height="281" loading="lazy"></p>
<pre><code class="lang-plaintext">Mon Apr 8 10:30:01 AM EDT 2025
Mon Apr 8 10:31:01 AM EDT 2025
</code></pre>
<h2 id="heading-how-to-manage-user-crontab-entries"><strong>How to Manage User 'crontab' Entries</strong></h2>
<p>Now you will learn more advanced techniques for managing user <code>crontab</code> entries, including editing existing jobs, adding multiple jobs, and understanding special <code>cron</code> strings. Effective <code>crontab</code> management is crucial for automating routine tasks.</p>
<p>We will continue working on the local system to explore advanced crontab management techniques.</p>
<p>Let's start by adding a new <code>cron</code> job. This job will append "Hello from cron!" to <code>~/cron_messages.txt</code> every two minutes.</p>
<p>Open your <code>crontab</code> for editing:</p>
<pre><code class="lang-bash">crontab -e
</code></pre>
<p>In Vim:</p>
<ol>
<li><p>Press <code>i</code> to enter insert mode</p>
</li>
<li><p>Add the following line to the <code>crontab</code> file:</p>
</li>
</ol>
<pre><code class="lang-bash">*/2 * * * * <span class="hljs-built_in">echo</span> <span class="hljs-string">"Hello from cron!"</span> &gt;&gt; ~/cron_messages.txt
</code></pre>
<ol start="3">
<li><p>Press <code>Esc</code> to exit insert mode</p>
</li>
<li><p>Type <code>:wq</code> and press <code>Enter</code> to save and exit</p>
</li>
</ol>
<p>Verify that the entry is added:</p>
<pre><code class="lang-bash">crontab -l
</code></pre>
<p>You should see the newly added line.</p>
<p>Now, let's add another <code>cron</code> job that runs daily at 08:00 AM. This job will record the disk usage of your home directory to <code>~/disk_usage.log</code>.</p>
<p>Open your <code>crontab</code> for editing again:</p>
<pre><code class="lang-bash">crontab -e
</code></pre>
<p>In Vim:</p>
<ol>
<li><p>Press <code>i</code> to enter insert mode</p>
</li>
<li><p>Add the following line below the previous one:</p>
</li>
</ol>
<pre><code class="lang-bash">0 8 * * * du -sh ~ &gt;&gt; ~/disk_usage.log
</code></pre>
<ol start="3">
<li><p>Press <code>Esc</code> to exit insert mode</p>
</li>
<li><p>Type <code>:wq</code> and press <code>Enter</code> to save and exit</p>
</li>
</ol>
<p>Verify that both entries are present:</p>
<pre><code class="lang-bash">crontab -l
</code></pre>
<p>You should now see both <code>cron</code> jobs listed.</p>
<p><code>cron</code> also supports special strings that can simplify common schedules. These include <code>@reboot</code>, <code>@yearly</code>, <code>@annually</code>, <code>@monthly</code>, <code>@weekly</code>, <code>@daily</code>, <code>@midnight</code>, and <code>@hourly</code>. For example, <code>@hourly</code> is equivalent to <code>0 * * * *</code>.</p>
<p>Let's add a job that runs hourly and records the system uptime to <code>~/uptime_log.txt</code>.</p>
<p>Open your <code>crontab</code> for editing:</p>
<pre><code class="lang-bash">crontab -e
</code></pre>
<p>In Vim:</p>
<ol>
<li><p>Press <code>i</code> to enter insert mode</p>
</li>
<li><p>Add the following line:</p>
</li>
</ol>
<pre><code class="lang-bash">@hourly uptime &gt;&gt; ~/uptime_log.txt
</code></pre>
<ol start="3">
<li><p>Press <code>Esc</code> to exit insert mode</p>
</li>
<li><p>Type <code>:wq</code> and press <code>Enter</code> to save and exit</p>
</li>
</ol>
<p>Verify all three entries:</p>
<pre><code class="lang-bash">crontab -l
</code></pre>
<p>You should now see all three <code>cron</code> jobs.</p>
<p>To demonstrate the effect of these jobs, we will wait for a short period. Since the jobs are scheduled at different intervals, we won't see all of them execute immediately, but we can verify the setup.</p>
<p>Wait for at least 3 minutes to allow the <code>*/2</code> job to run at least once.</p>
<p>Check the <code>~/cron_messages.txt</code> file:</p>
<pre><code class="lang-bash">cat ~/cron_messages.txt
</code></pre>
<p>You should see at least one "Hello from cron!" message.</p>
<pre><code class="lang-plaintext">Hello from cron!
</code></pre>
<p>The <code>~/disk_usage.log</code> and <code>~/uptime_log.txt</code> files might not be created yet, depending on the current time, as they are scheduled for daily and hourly execution, respectively. The important part is that their entries are correctly configured in your <code>crontab</code>.</p>
<h2 id="heading-how-to-schedule-recurring-system-jobs-with-cron-directories"><strong>How to Schedule Recurring System Jobs with</strong> <code>cron</code> <strong>Directories</strong></h2>
<p>In this step, you will learn how to schedule recurring system-wide tasks using <code>cron</code> directories. Unlike user <code>crontab</code> entries, which are specific to a user, system <code>cron</code> jobs are managed by the root user and affect the entire system. These are typically used for system maintenance, log rotation, and other administrative tasks.</p>
<p>We will continue working on the local system to explore system-wide cron job configuration.</p>
<p>System-wide <code>cron</code> jobs are defined in <code>/etc/crontab</code> or by placing scripts in specific directories:</p>
<ul>
<li><p><code>/etc/cron.hourly/</code>: Scripts in this directory run once an hour.</p>
</li>
<li><p><code>/etc/cron.daily/</code>: Scripts in this directory run once a day.</p>
</li>
<li><p><code>/etc/cron.weekly/</code>: Scripts in this directory run once a week.</p>
</li>
<li><p><code>/etc/cron.monthly/</code>: Scripts in this directory run once a month.</p>
</li>
</ul>
<p>These directories are processed by the <code>run-parts</code> utility, which executes all executable files within them.</p>
<p>To manage system <code>cron</code> jobs, you need root privileges. Since the labex user has sudo access, we can use <code>sudo</code> for the required commands.</p>
<p>Let's create a simple script that logs a message to the system log. We will place this script in <code>/etc/cron.hourly/</code> to make it run hourly.</p>
<p>First, create the script file <code>/etc/cron.hourly/my_hourly_script</code>:</p>
<pre><code class="lang-bash">sudo nano /etc/cron.hourly/my_hourly_script
</code></pre>
<p>Add the following content to the file:</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>
logger <span class="hljs-string">"Hourly cron job executed at <span class="hljs-subst">$(date)</span>"</span>
</code></pre>
<p>Save and exit the editor (<code>Ctrl+o</code>, <code>Enter</code>, <code>Ctrl+x</code> in <code>nano</code>).</p>
<p>Next, you need to make the script executable. Without execute permissions, <code>run-parts</code> will ignore it.</p>
<pre><code class="lang-bash">sudo chmod +x /etc/cron.hourly/my_hourly_script
</code></pre>
<p>Now, let's verify that the script is executable:</p>
<pre><code class="lang-bash">ls -l /etc/cron.hourly/my_hourly_script
</code></pre>
<p>You should see <code>x</code> in the permissions, for example: <code>-rwxr-xr-x</code>.</p>
<p>Since <code>cron.hourly</code> jobs run once an hour, we can't wait for a full hour to verify its execution in this tutorial. But we can manually trigger the <code>run-parts</code> command for the hourly directory to simulate its execution.</p>
<pre><code class="lang-bash">sudo run-parts /etc/cron.hourly/
</code></pre>
<p>This command will execute all executable scripts in <code>/etc/cron.hourly/</code>. The script we created uses the <code>logger</code> command to write messages to the system log.</p>
<p>In a real RHEL system, you would be able to check the system logs using <code>journalctl</code> or <code>/var/log/messages</code> to verify that the script executed successfully.</p>
<p>This completes the system cron job management step. The script will remain in place and would execute hourly in a real system environment.</p>
<h2 id="heading-how-to-configure-systemd-timers-for-recurring-tasks"><strong>How to Configure</strong> <code>systemd</code> <strong>Timers for Recurring Tasks</strong></h2>
<p>Next, you will learn about <code>systemd</code> timers, which are a modern alternative to <code>cron</code> for scheduling tasks on Linux systems. <code>systemd</code> timers offer more flexibility and better integration with the <code>systemd</code> ecosystem.</p>
<p><code>systemd</code> timers work in conjunction with <code>systemd</code> service units. A timer unit (<code>.timer</code> file) defines when a task should run, and a service unit (<code>.service</code> file) defines what task should be executed.</p>
<p>We will continue working on the local system to explore systemd timer configuration.</p>
<p>You will need root privileges to create <code>systemd</code> unit files in system directories. Since the labex user has sudo access, we can use <code>sudo</code> for the required commands.</p>
<p>Let's create a simple service that logs a message to a file. We will place this service unit file in <code>/etc/systemd/system/</code> which is where custom service units are typically stored.</p>
<p>Create the service unit file <code>/etc/systemd/system/my-custom-task.service</code>:</p>
<pre><code class="lang-bash">sudo nano /etc/systemd/system/my-custom-task.service
</code></pre>
<p>Add the following content to the file:</p>
<pre><code class="lang-ini"><span class="hljs-section">[Unit]</span>
<span class="hljs-attr">Description</span>=My Custom Scheduled Task

<span class="hljs-section">[Service]</span>
<span class="hljs-attr">Type</span>=<span class="hljs-literal">on</span>eshot
<span class="hljs-attr">ExecStart</span>=/bin/bash -c <span class="hljs-string">'echo "My custom task executed at $(date)" &gt;&gt; /var/log/my-custom-task.log'</span>
</code></pre>
<p>Save and exit the editor (<code>Ctrl+o</code>, <code>Enter</code>, <code>Ctrl+x</code> in <code>nano</code>).</p>
<p>Next, create the timer unit file <code>/etc/systemd/system/my-custom-task.timer</code>. This timer will activate our service every 5 minutes.</p>
<pre><code class="lang-bash">sudo nano /etc/systemd/system/my-custom-task.timer
</code></pre>
<p>Add the following content to the file:</p>
<pre><code class="lang-ini"><span class="hljs-section">[Unit]</span>
<span class="hljs-attr">Description</span>=Run My Custom Scheduled Task every <span class="hljs-number">5</span> minutes

<span class="hljs-section">[Timer]</span>
<span class="hljs-attr">OnCalendar</span>=*:<span class="hljs-number">0</span>/<span class="hljs-number">5</span>
<span class="hljs-attr">Persistent</span>=<span class="hljs-literal">true</span>

<span class="hljs-section">[Install]</span>
<span class="hljs-attr">WantedBy</span>=timers.target
</code></pre>
<p>Save and exit the editor.</p>
<p><strong>Explanation of</strong> <code>OnCalendar</code>:</p>
<ul>
<li><p><code>*:0/5</code> means "every 5 minutes".</p>
<ul>
<li><p><code>*</code> for year, month, day, hour (any value).</p>
</li>
<li><p><code>0/5</code> for minute, meaning starting at minute 0, every 5 minutes (0, 5, 10, ..., 55).</p>
</li>
</ul>
</li>
</ul>
<p>In a typical <code>systemd</code> environment, you would now run <code>systemctl daemon-reload</code> to make <code>systemd</code> aware of the new unit files, and then <code>systemctl enable --now my-custom-task.timer</code> to start the timer.</p>
<p>Let's verify the existence of the created files:</p>
<pre><code class="lang-bash">ls -l /etc/systemd/system/my-custom-task.service
ls -l /etc/systemd/system/my-custom-task.timer
</code></pre>
<p>You should see output indicating that both files exist.</p>
<p>To simulate the execution of the service, you can manually run the command defined in <code>ExecStart</code>:</p>
<pre><code class="lang-bash">sudo /bin/bash -c <span class="hljs-string">'echo "My custom task executed at $(date)" &gt;&gt; /var/log/my-custom-task.log'</span>
</code></pre>
<p>Now, check the log file to see the output:</p>
<pre><code class="lang-bash">sudo cat /var/<span class="hljs-built_in">log</span>/my-custom-task.log
</code></pre>
<p>You should see the message you just logged:</p>
<pre><code class="lang-plaintext">My custom task executed at Tue Jun 10 06:54:40 UTC 2025
</code></pre>
<p>This completes the systemd timer configuration step. The service and timer unit files will remain in place for reference.</p>
<h2 id="heading-how-to-manage-temporary-files-with-systemd-tmpfiles"><strong>How to Manage Temporary Files with</strong> <code>systemd-tmpfiles</code></h2>
<p>Now you’ll learn how to manage temporary files and directories using <code>systemd-tmpfiles</code>. This utility is part of <code>systemd</code> and is responsible for creating, deleting, and cleaning up volatile and temporary files and directories. It's commonly used to manage <code>/tmp</code>, <code>/var/tmp</code>, and other temporary storage locations, ensuring that old files are removed periodically.</p>
<p>We will continue working on the local system to explore systemd-tmpfiles configuration.</p>
<p>You will need root privileges to configure <code>systemd-tmpfiles</code>. Since the labex user has sudo access, we can use <code>sudo</code> for the required commands.</p>
<p><code>systemd-tmpfiles</code> reads configuration files from <code>/etc/tmpfiles.d/</code> and <code>/usr/lib/tmpfiles.d/</code>. These files define rules for creating, deleting, and managing files and directories.</p>
<p>Let's create a custom configuration file to manage a new temporary directory. We will create a directory <code>/run/my_temp_dir</code> and configure <code>systemd-tmpfiles</code> to clean files older than 1 minute from it.</p>
<p>Create the configuration file <code>/etc/tmpfiles.d/my_temp_dir.conf</code>:</p>
<pre><code class="lang-bash">sudo nano /etc/tmpfiles.d/my_temp_dir.conf
</code></pre>
<p>Add the following content to the file:</p>
<pre><code class="lang-bash">d /run/my_temp_dir 0755 labex labex 1m
</code></pre>
<p><strong>Explanation of the line:</strong></p>
<ul>
<li><p><code>d</code>: Specifies that this entry defines a directory.</p>
</li>
<li><p><code>/run/my_temp_dir</code>: The path to the directory.</p>
</li>
<li><p><code>0755</code>: The permissions for the directory.</p>
</li>
<li><p><code>labex labex</code>: The owner and group for the directory.</p>
</li>
<li><p><code>1m</code>: The age after which files in this directory should be deleted (1 minute).</p>
</li>
</ul>
<p>Save and exit the editor (<code>Ctrl+o</code>, <code>Enter</code>, <code>Ctrl+x</code> in <code>nano</code>).</p>
<p>Now, let's tell <code>systemd-tmpfiles</code> to apply this configuration. The <code>--create</code> option will create the directory if it doesn't exist.</p>
<pre><code class="lang-bash">sudo systemd-tmpfiles --create /etc/tmpfiles.d/my_temp_dir.conf
</code></pre>
<p>Verify that the directory has been created with the correct permissions and ownership:</p>
<pre><code class="lang-bash">ls -ld /run/my_temp_dir
</code></pre>
<p>You should see output similar to:</p>
<pre><code class="lang-plaintext">drwxr-xr-x 2 labex labex 6 Jun 10 06:55 /run/my_temp_dir
</code></pre>
<p>Next, let's create a test file inside this new temporary directory:</p>
<pre><code class="lang-bash">sudo touch /run/my_temp_dir/test_file.txt
</code></pre>
<p>Verify the file exists:</p>
<pre><code class="lang-bash">ls -l /run/my_temp_dir/test_file.txt
</code></pre>
<p>Now, we need to wait for more than 1 minute for the file to become "old" according to our configuration. Wait for at least 70 seconds (1 minute and 10 seconds).</p>
<p>After waiting for more than 1 minute, we will manually run <code>systemd-tmpfiles</code> with the <code>--clean</code> option to trigger the cleanup process based on our configuration.</p>
<pre><code class="lang-bash">sudo systemd-tmpfiles --clean /etc/tmpfiles.d/my_temp_dir.conf
</code></pre>
<p>Finally, check if the <code>test_file.txt</code> has been removed:</p>
<pre><code class="lang-bash">ls -l /run/my_temp_dir/test_file.txt
</code></pre>
<p>You should get a "No such file or directory" error, indicating that <code>systemd-tmpfiles</code> successfully cleaned up the old file.</p>
<p>This completes configuring the systemd-tmpfiles. The configuration file and temporary directory will remain in place for reference.</p>
<h2 id="heading-summary"><strong>Summary</strong></h2>
<p>In this tutorial, you learned how to schedule and manage one-time tasks using the <code>at</code> command, including scheduling jobs interactively and non-interactively, viewing the <code>at</code> queue with <code>atq</code>, and deleting pending jobs with <code>atrm</code>. You also learned how to schedule recurring user-specific tasks using <code>crontab</code>, including how to edit, list, and remove cron jobs, and you learned the cron syntax for specifying execution times.</p>
<p>We also demonstrated how to schedule system-wide recurring tasks by placing scripts in standard cron directories (<code>/etc/cron.hourly</code>, <code>/etc/cron.daily</code>, etc.) and how to create custom cron jobs in <code>/etc/cron.d</code>.</p>
<p>Finally, you explored advanced task scheduling with <code>systemd</code> timers, learning to create and enable service and timer units for recurring tasks, and how to manage temporary files and directories using <code>systemd-tmpfiles</code> for automated cleanup.</p>
<p>This comprehensive tutorial provided practical experience in managing diverse task scheduling needs on RHEL systems, from simple one-off commands to complex recurring system processes.</p>
<p>To practice the operations from this tutorial, try the interactive hands-on lab: <a target="_blank" href="https://labex.io/labs/rhel-schedule-tasks-in-red-hat-enterprise-linux-588897?course=red-hat-system-administration-rh134-labs">Schedule Tasks in Red Hat Enterprise Linux</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn User Management in RHEL: A Comprehensive Guide ]]>
                </title>
                <description>
                    <![CDATA[ Imagine you're throwing a house party. You wouldn’t hand out keys to every guest, right? Some friends can roam freely, some should probably stick to the living room, and a few—well, let’s just say they need supervision. Managing users in RHEL is kind... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-user-management-in-rhel-a-comprehensive-guide/</link>
                <guid isPermaLink="false">67b5da0a6db178277c2bebc9</guid>
                
                    <category>
                        <![CDATA[ Linux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ RHEL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ user management ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tanishka Makode ]]>
                </dc:creator>
                <pubDate>Wed, 19 Feb 2025 13:18:02 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1739971027992/d19c4616-4c2e-4cc4-ac45-384e6520d1a8.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Imagine you're throwing a house party. You wouldn’t hand out keys to every guest, right? Some friends can roam freely, some should probably stick to the living room, and a few—well, let’s just say they need supervision.</p>
<p>Managing users in RHEL is kind of like that. You decide who gets in, what they can do, and how much control they have. Without proper management, things can get messy fast—like that friend who somehow DJs when no one asks.</p>
<p>So, let’s dive into user management and ensure your Linux system stays organized, secure, and drama-free! 🚀</p>
<h2 id="heading-table-of-contents">Table Of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-is-a-user-in-linux">What is a User in Linux?</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-understanding-sudo-in-user-management">Understanding sudo in User Management</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-user-management-commands-in-linux">User Management Commands in Linux</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-add-a-user">How to Add a User</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-check-if-a-user-is-created">How to Check if a User is Created</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-assign-a-password">How to Assign a Password</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-switch-users">How to Switch Users</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-groups-in-linux">Understanding Groups in Linux</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-modify-users">How to Modify Users</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-final-words">Final Words</a></p>
</li>
</ol>
<h2 id="heading-what-is-a-user-in-linux"><strong>What is a User in Linux?</strong></h2>
<p>A user in Linux is an account that allows someone (or a process) to interact with the system. Since Linux is a multi-user operating system, multiple users can exist on the same system, each with their own settings, files, and permissions. Users can have different levels of permissions, which determine what they can access or modify on the system.</p>
<p>Linux categorizes users into three main types based on their roles and privileges:</p>
<ol>
<li><p>Privileged Users: These users have unrestricted access to the entire system. They have the highest level of permissions and can perform any operation on the system. They can install/remove software, modify system files, create/manage users, and even delete everything. These users are also called root users.</p>
</li>
<li><p>System Users: The system creates these users to run background processes or services. They can’t login like a normal user. Their sole purpose is to manage system operations like databases, web servers and scheduled tasks.</p>
</li>
<li><p>Normal Users: These are the everyday users created by administrators or during system installation. They have their home directory and can store personal files and settings. They can’t modify system files but can execute tasks within their permission scope.</p>
</li>
</ol>
<h3 id="heading-understanding-sudo-in-user-management">Understanding <code>sudo</code> in User Management</h3>
<p>The <code>sudo</code> (Superuser Do) command allows a regular user to execute administrative tasks with elevated privileges. Since user management tasks—such as adding, modifying, or deleting users—require root access, normal users must use <code>sudo</code> before these commands.</p>
<p>Note that the following commands are executed as the root user. If you are using a normal user account, you must prefix them with <code>sudo</code> to perform user management tasks.</p>
<p>Now let’s see how we manage users on RHEL.</p>
<h2 id="heading-user-management-commands-in-linux">User Management Commands in Linux</h2>
<h3 id="heading-how-to-add-a-user">How to add a user</h3>
<p>To create a new user account, use following command:</p>
<p>Syntax:</p>
<pre><code class="lang-bash">useradd [user_name]
</code></pre>
<p>Example:</p>
<pre><code class="lang-bash">useradd Tanishka <span class="hljs-comment"># Root user</span>
sudo useradd Tanishka <span class="hljs-comment"># Normal user</span>
</code></pre>
<p>Once you create a user, you can verify its existence in the <code>/etc/passwd</code> file. This file stores essential user account information (but <strong>not passwords</strong>, despite the name).</p>
<h4 id="heading-how-to-check-if-a-user-is-created">How to check if a user is created</h4>
<p>To confirm the user entry in <code>/etc/passwd</code>, use one of the following methods:</p>
<ol>
<li>View the file using <code>cat</code> or <code>grep</code></li>
</ol>
<pre><code class="lang-bash">cat /etc/passwd <span class="hljs-comment"># Displays entire file content</span>
grep Tanishka /etc/passwd <span class="hljs-comment"># Displays information about Tanishka user only</span>
</code></pre>
<ol start="2">
<li>Use id command:</li>
</ol>
<p>The <code>id</code> command is used to display a user’s <strong>UID (User ID), GID (Group ID), and the groups they belong to</strong>. It helps in verifying user information and checking permissions.</p>
<pre><code class="lang-bash">id Tanishka
<span class="hljs-comment"># Displays user id of Tanishka,</span>
<span class="hljs-comment"># hence verifying user has been created</span>
</code></pre>
<p>Let’s understand what’s going on in the /etc/password fields. Each line in <code>/etc/passwd</code> represents a user account and contains seven fields separated by colons (<code>:</code>):</p>
<pre><code class="lang-bash">username:x:UID:GID:comment:home_directory:shell
</code></pre>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Field</strong></td><td><strong>Description</strong></td></tr>
</thead>
<tbody>
<tr>
<td>username</td><td>Name of the user (for example, john, admin).</td></tr>
<tr>
<td>x</td><td>Placeholder for the password (actual password is stored in /etc/shadow).</td></tr>
<tr>
<td>UID</td><td>User ID (for example, 1001 for a normal user, 0 for root).</td></tr>
<tr>
<td>GID</td><td>Group ID (primary group of the user).</td></tr>
<tr>
<td>comment</td><td>Optional user description (for example, full name or other info).</td></tr>
<tr>
<td>home_directory</td><td>User’s home directory (for example /home/john).</td></tr>
<tr>
<td>shell</td><td>The default shell assigned to the user (for example, /bin/bash, /bin/sh, /usr/sbin/nologin).</td></tr>
</tbody>
</table>
</div><h3 id="heading-how-to-assign-a-password">How to Assign a Password</h3>
<p>Once an account is created, it’s essential to assign a password to the account. Otherwise, that account can’t be logged in through a GUI login interface. To give a password to a user account, user this command:</p>
<p>Syntax:</p>
<pre><code class="lang-bash">passwd [user_name]
</code></pre>
<p>Example:</p>
<pre><code class="lang-bash">passwd Tanishka
</code></pre>
<p>You will be prompted to enter the password. Enter the password and you’re all set! Even though user information is stored in /etc/passwd file, actual information about the password is stored in the /etc/shadow file (weird, I know…).</p>
<p>To see the content of the /etc/shadow file, use this command:</p>
<pre><code class="lang-bash">cat /etc/shadow
</code></pre>
<p>Each line in <code>/etc/shadow</code> represents a user account password and contains nine fields separated by colons (<code>:</code>):</p>
<pre><code class="lang-bash">username:password:lastchg:min:max:warn:inactive:expire:reserved
</code></pre>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Field</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td>username</td><td>User’s login name</td></tr>
<tr>
<td>password</td><td>Encrypted password or password status (for example, locked)</td></tr>
<tr>
<td>lastchg</td><td>Last password change (days since Jan 1, 1970)</td></tr>
<tr>
<td>min</td><td>Minimum days between password changes</td></tr>
<tr>
<td>max</td><td>Maximum days before password change is required</td></tr>
<tr>
<td>warn</td><td>Warning period before password expiration</td></tr>
<tr>
<td>inactive</td><td>Inactive period after password expiration</td></tr>
<tr>
<td>expire</td><td>Account expiration date (days since Jan 1, 1970)</td></tr>
<tr>
<td>reserved</td><td>Reserved for future use</td></tr>
</tbody>
</table>
</div><p>To change password aging information, you use the <code>chage</code> (short for change age) command like this:</p>
<p>Syntax:</p>
<pre><code class="lang-bash">chage [OPTIONS] [user_name]
</code></pre>
<p>Example:</p>
<pre><code class="lang-bash">chage -l tanishka <span class="hljs-comment"># Lists the current password aging information</span>
chage -m 10 tanishka <span class="hljs-comment"># Sets the minimum days to change password</span>
chage -M 10 tanishka <span class="hljs-comment"># Sets the maximum days password must be changed</span>
chage -W 7 tanishka <span class="hljs-comment"># Sets the number of days before the password expires that the user will be warned to change the password</span>
chage -I 10 tanishka <span class="hljs-comment"># Sets the number of days after password expiration that the account will be disabled if not logged in</span>
chage -E 2025-12-31 tanishka <span class="hljs-comment"># Sets the date when the user account will expire </span>
chage -d 2024-12-25 tanishka <span class="hljs-comment"># Sets the last password change date</span>
</code></pre>
<p>Now that you have learned to create users and assign passwords, you need to know how to switch between users. Let’s see that now.</p>
<h3 id="heading-how-to-switch-users">How to Switch Users</h3>
<p>The <code>su</code> (Substitute User) command allows you to <strong>switch from one user to another</strong> without logging out of the current session.</p>
<p>Syntax:</p>
<pre><code class="lang-bash">su - [user_name]
</code></pre>
<p>Example:</p>
<pre><code class="lang-bash">su - Tanishka <span class="hljs-comment"># Switches to Tanishka user</span>
</code></pre>
<ul>
<li><p><code>su</code> stands for "substitute user" (or "switch user").</p>
</li>
<li><p>The <code>-</code> (hyphen) loads the target user's full environment, including their shell, path, and profile settings (similar to logging in as that user).</p>
</li>
<li><p>If no username is provided, it switches to the root user by default.</p>
</li>
</ul>
<p>To return to original or root user, simply enter ‘exit’.</p>
<h3 id="heading-understanding-groups-in-linux">Understanding Groups in Linux</h3>
<p>Just like a party where guests can belong to different social circles, Linux groups allow users to be part of different permission levels. Groups help manage file access, system privileges, and administrative controls efficiently.</p>
<p>Linux has two types of groups:</p>
<p><strong>1. Primary Group:</strong></p>
<ul>
<li><p>Every user has one primary group.</p>
</li>
<li><p>When a user creates a new file, it belongs to their primary group.</p>
</li>
<li><p>It is usually named the same as the username.</p>
</li>
</ul>
<p><strong>2. Secondary Groups:</strong></p>
<ul>
<li><p>A user can belong to multiple secondary groups.</p>
</li>
<li><p>These groups provide additional permissions beyond the primary group.</p>
</li>
<li><p>Users can be assigned to various secondary groups to access shared resources.</p>
</li>
</ul>
<p>To check a user’s group membership:</p>
<pre><code class="lang-bash">id [user_name]
</code></pre>
<p>This displays the user’s UID, primary group (GID), and any secondary groups they belong to.</p>
<p>To add a new group:</p>
<pre><code class="lang-bash">groupadd [group_name]
</code></pre>
<h3 id="heading-how-to-modify-a-user">How to Modify a User</h3>
<p>Sometimes, you might need to update user details, such as changing usernames, user IDs, group memberships, home directories, or login shells. You use the <code>usermod</code> command to modify existing user accounts while preserving their files and configurations.</p>
<p>Syntax:</p>
<pre><code class="lang-bash">usermod [OPTIONS] [user_name]
</code></pre>
<p>Let’s break down the different options available for modifying user accounts.</p>
<ol>
<li><strong>Change the username</strong></li>
</ol>
<p>If you want to rename an existing user, use the <code>-l</code> option:</p>
<p>Syntax:</p>
<pre><code class="lang-bash">usermod -l new_username old_username
</code></pre>
<p>Example:</p>
<pre><code class="lang-bash">usermod -l tanishkamakode tanishka
</code></pre>
<p>This renames <code>tanishka</code> to <code>tanishkamakode</code>. Just keep in mind that the home directory remains the same (<code>/home/tanishka</code>), so you might need to rename it manually.</p>
<p>To rename the home directory as well, use:</p>
<pre><code class="lang-bash">mv /home/tanishka /home/tanishkamakode
</code></pre>
<ol start="2">
<li><strong>Change the user id:</strong></li>
</ol>
<p>Each user has a unique User ID (UID). If you need to change it, use <code>-u</code>.</p>
<p>Syntax:</p>
<pre><code class="lang-bash">usermod -u new_UID user_name
</code></pre>
<p>Example:</p>
<pre><code class="lang-bash">usermod -u 2001 tanishka
</code></pre>
<p>This changes <code>tanishka</code>'s UID to <code>2001</code>. Before you do this, you’ll want to <strong>make sure that no other user has the same UID.</strong> This is important.</p>
<p>If the user owns files under the old UID, you should update them after changing the UID.</p>
<ol start="3">
<li><strong>Change the primary group</strong></li>
</ol>
<p>Every user belongs to a primary group. To change it, use <code>-g</code>.</p>
<p>Syntax:</p>
<pre><code class="lang-bash">usermod -g new_group user_name
</code></pre>
<p>Example:</p>
<pre><code class="lang-bash">usermod -g developers tanishka
</code></pre>
<p>This changes <code>tanishka</code>'s primary group to <code>developers</code>. Just keep in mind that <code>usermod -g developers tanishka</code> <strong>removes</strong> the user from all secondary groups. To avoid that, just make sure you check and re-add secondary groups as needed.</p>
<p>Also, the group must exist beforehand. To create a group, run this command:</p>
<p>Syntax:</p>
<pre><code class="lang-bash">groupadd [group_name]
</code></pre>
<p>Example:</p>
<pre><code class="lang-bash">groupadd developers
</code></pre>
<p>Now, to check tanishka’s group, do the following:</p>
<pre><code class="lang-bash">id tanishka
</code></pre>
<ol start="4">
<li><strong>Add to a secondary group</strong></li>
</ol>
<p>A user can belong to multiple secondary groups. Use <code>-G</code> to assign them.</p>
<p>Syntax:</p>
<pre><code class="lang-bash">usermod -G group1,group2 user_name
</code></pre>
<p>Example:</p>
<pre><code class="lang-bash">usermod -G linux,docker tanishka
</code></pre>
<p>This adds <code>tanishka</code> to the <code>sudo</code> and <code>docker</code> groups. Just keep in mind that this <strong>replaces</strong> any existing secondary groups that the user might already belong to. To add groups without removing the current ones, use <code>-aG</code> (append to groups) like this:</p>
<pre><code class="lang-bash">usermod -aG linux,docker tanishka
</code></pre>
<ol start="5">
<li><strong>Change the home directory:</strong></li>
</ol>
<p>You can change a user’s default home directory using <code>-d</code>.</p>
<p>Syntax:</p>
<pre><code class="lang-bash">usermod -d /new/home_directory user_name
</code></pre>
<p>Example:</p>
<pre><code class="lang-bash">usermod -d /home/tani tanishka
</code></pre>
<p>This sets <code>tanishka</code>'s home directory to <code>/home/tani</code>, but <strong>it does not move existing files</strong>. To move them, add the <code>-m</code> option:</p>
<pre><code class="lang-bash">usermod -d /home/tani -m tanishka
</code></pre>
<p>After moving the home directory, just make sure you’ve updated file ownership.</p>
<ol start="6">
<li><strong>Change the login shell:</strong></li>
</ol>
<p>The default shell for a user can be changed using <code>-s</code>.</p>
<p>Syntax:</p>
<pre><code class="lang-bash">usermod -s /new/shell user_name
</code></pre>
<p>Example:</p>
<pre><code class="lang-bash">usermod -s /bin/zsh tanishka
</code></pre>
<p>This changes <code>tanishka</code>'s default shell to <code>zsh</code>. Common shells include:</p>
<ul>
<li><p><code>/bin/bash</code> (default)</p>
</li>
<li><p><code>/bin/sh</code></p>
</li>
<li><p><code>/bin/zsh</code></p>
</li>
<li><p><code>/usr/sbin/nologin</code> (to disable login)</p>
</li>
</ul>
<p>With <code>usermod</code>, you can fine-tune user settings to match system requirements. Always check changes using:</p>
<pre><code class="lang-bash">id tanishka
grep tanishka /etc/passwd
</code></pre>
<h2 id="heading-final-words">Final Words</h2>
<p>In this article, we explored the fundamentals of user management in RHEL, a crucial aspect of system administration. We started with creating and managing users, then moved on to handling groups.</p>
<p>If you're new to Linux and want to build a strong foundation, check out my first tutorial on <a target="_blank" href="https://www.freecodecamp.org/news/guide-to-rhel-linux-basics/">Basic Linux Commands</a>, where I cover essential commands every beginner should know. You can also read my second tutorial on <a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-the-vim-text-editor-intro-for-devs/">Vim</a> to learn how to navigate and edit text efficiently in this powerful editor. These articles will complement what you’ve learned about user management here.</p>
<p>Keep practicing these commands, and soon they’ll become second nature to you. Mastery comes with repetition, so continue experimenting and applying these fundamentals in real-world scenarios.</p>
<p>Stay tuned for more articles. Get ready to take your RHEL skills to the next level.</p>
<p><a target="_blank" href="https://linktr.ee/tanishkamakode">Let’s connect!</a></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
