<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Shem Maiwuya</title>
    <description>The latest articles on DEV Community by Shem Maiwuya (@xtasy).</description>
    <link>https://dev.to/xtasy</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1697917%2Fbc77e961-b448-4b51-a278-b145dd124267.jpg</url>
      <title>DEV Community: Shem Maiwuya</title>
      <link>https://dev.to/xtasy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/xtasy"/>
    <language>en</language>
    <item>
      <title>It wasn't "Love at first sight"</title>
      <dc:creator>Shem Maiwuya</dc:creator>
      <pubDate>Sat, 04 Apr 2026 07:12:20 +0000</pubDate>
      <link>https://dev.to/xtasy/it-wasnt-love-at-first-sight-1o9n</link>
      <guid>https://dev.to/xtasy/it-wasnt-love-at-first-sight-1o9n</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/wecoded-2026"&gt;2026 WeCoded Challenge&lt;/a&gt;: Echoes of Experience&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I started my coding or programming journey due to 10% curiosity and 90% the fact that I did not want to graduate from my computer science degree with no programming knowledge whatsoever. So I researched the field to get into and the language. I contemplated between C, C++ and Python. I eventually settled for Python.&lt;/p&gt;

&lt;p&gt;The first Hello World on the terminal made me feel like a god, and I have been chasing that feeling since. Maybe that's the reason I preferred the CLI, writing CLI-based applications. I later fell in love with C and Go. Those have been what I've been using for a while now.&lt;/p&gt;

&lt;p&gt;I still never focused on a field. I just learn what interests me at the moment, from DevOps to reverse engineering, from databases to embedded systems. At least a jack of all trades, master of one is better than a master of one.&lt;/p&gt;

&lt;p&gt;I eventually discovered GNU/Linux. I was very sure that I was just testing it on a VM, that I would never daily drive it. But here I am, using Void Linux on both of my PCs for years now and can't think of changing to anywhere else. Linux also made me discover Linus Torvalds and Richard Stallman, the creators. They showed me what the peak of programming looked like. Also seeing what people create in random repos, reading about the creation of Doom, the creation of xbps (Void Linux), and people like Terry A. Davis were an inspiration too.&lt;/p&gt;

&lt;p&gt;When I look back at my journey, all I can say is that consistency pays. I've really come a long way from someone who saw lines of code as magic to the present me who reads the source code of random repos for fun.&lt;/p&gt;

&lt;p&gt;I am not where I want to be, but I am much better than where I was. Curiosity and not wanting to be left out made me discover a world I never expected. In my next life, I hope I still discover this path.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>wecoded</category>
      <category>dei</category>
      <category>career</category>
    </item>
    <item>
      <title>Day ??? of learning go. Building cli apps</title>
      <dc:creator>Shem Maiwuya</dc:creator>
      <pubDate>Fri, 16 Aug 2024 06:55:22 +0000</pubDate>
      <link>https://dev.to/xtasy/day-of-learning-go-building-cli-apps-280p</link>
      <guid>https://dev.to/xtasy/day-of-learning-go-building-cli-apps-280p</guid>
      <description>&lt;h2&gt;
  
  
  Why cli??
&lt;/h2&gt;

&lt;p&gt;I have always had a preference for command line interface (CLI) and terminal user interface (TUI) tools over their graphical user interface (GUI) counterparts. This project, aptly named "Phraser" (no apologies for the poor naming), is a command line application designed to manage wallet seed phrases for crypto wallets. I developed this application to create a more convenient way to manage the seed phrases for my crypto wallets.&lt;br&gt;
It creates a directory and stores the phrases in encrypted JSON files. You can then move the JSON files and store them anywhere you want.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why go?
&lt;/h2&gt;

&lt;p&gt;To enhance my skills, I chose to rewrite a project I had previously written in Python using Go. Unlike the Python version, which requires a multitude of dependencies to be installed, the Go version can be compiled into a single binary, making it more portable and less cumbersome. Additionally, Go is known for its blazing speed(I couldn't resist:))&lt;/p&gt;
&lt;h2&gt;
  
  
  Tool used
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Go v1.22.5(of course)&lt;/li&gt;
&lt;li&gt;Cobra-cli&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;You can find a precompiled binary on the releases page of the GitHub repository(link at end of article).&lt;/p&gt;
&lt;h3&gt;
  
  
  Manual Installation
&lt;/h3&gt;

&lt;p&gt;If you prefer, you can clone the repository and install the dependencies to test it out.&lt;br&gt;
The instructions are in the Readme in the GitHub repository, but I will still highlight them here.&lt;/p&gt;
&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;Phraser is easy to use with a set of straightforward commands. Here's a basic overview:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   phraser &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;flags]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Commands
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;completion&lt;/strong&gt;: Generate the autocompletion script for the specified shell.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;create&lt;/strong&gt;: Creates a wallet in your store.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;gendoc&lt;/strong&gt;: Generate Markdown documentation for all commands.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get&lt;/strong&gt;: Retrieves data stored in a wallet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;init&lt;/strong&gt;: Initializes a store.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Options
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nt"&gt;-a&lt;/span&gt;, &lt;span class="nt"&gt;--amount&lt;/span&gt; int      amount of phrases to be inputted
  &lt;span class="nt"&gt;-h&lt;/span&gt;, &lt;span class="nt"&gt;--help&lt;/span&gt;            &lt;span class="nb"&gt;help &lt;/span&gt;&lt;span class="k"&gt;for &lt;/span&gt;phraser
  &lt;span class="nt"&gt;-s&lt;/span&gt;, &lt;span class="nt"&gt;--store&lt;/span&gt; string    name of the store to access
  &lt;span class="nt"&gt;-t&lt;/span&gt;, &lt;span class="nt"&gt;--toggle&lt;/span&gt;          Help message &lt;span class="k"&gt;for &lt;/span&gt;toggle
  &lt;span class="nt"&gt;-w&lt;/span&gt;, &lt;span class="nt"&gt;--wallet&lt;/span&gt; string   name of the wallet to be created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Initialize a new store:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   phraser init &lt;span class="nt"&gt;--store&lt;/span&gt; myStore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create a new wallet:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   phraser create &lt;span class="nt"&gt;--store&lt;/span&gt; myStore &lt;span class="nt"&gt;--wallet&lt;/span&gt; myWallet &lt;span class="nt"&gt;--amount&lt;/span&gt; 12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Retrieve a wallet's seed phrase:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   phraser get &lt;span class="nt"&gt;--store&lt;/span&gt; &lt;span class="nt"&gt;--wallet&lt;/span&gt; myWallet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This project taught me a lot about Go-like encryption/decryption, file handling, and also the cobra-cli for building CLI apps. Any feedback and corrections are appreciated.&lt;br&gt;
The source code can be found &lt;a href="https://github.com/xtasysensei/phraser" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>cli</category>
      <category>cobra</category>
      <category>cryptography</category>
    </item>
    <item>
      <title>Bash Scripting: Automating User Management in Linux</title>
      <dc:creator>Shem Maiwuya</dc:creator>
      <pubDate>Mon, 01 Jul 2024 17:15:52 +0000</pubDate>
      <link>https://dev.to/xtasy/bash-scripting-automating-user-management-in-linux-1m3c</link>
      <guid>https://dev.to/xtasy/bash-scripting-automating-user-management-in-linux-1m3c</guid>
      <description>&lt;h2&gt;
  
  
  Why do we automate?
&lt;/h2&gt;

&lt;p&gt;Managing users and groups on a Linux system can be a tedious task, especially if you have to handle multiple accounts. Fortunately, with a bit of scripting knowledge, you can automate this process. In this article, I will walk you through a simple Bash script designed to create users, assign them to groups, and set their passwords automatically.&lt;/p&gt;

&lt;p&gt;Why Automate User Management?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Efficiency: Automating repetitive tasks saves time.&lt;/li&gt;
&lt;li&gt;Consistency: Ensures the same process is followed every time.&lt;/li&gt;
&lt;li&gt;Error Reduction: Minimizes the risk of human error.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  New to Bash scripting?
&lt;/h2&gt;

&lt;p&gt;For those trying to learn about bash scripting, kindly visit &lt;a href="https://dev.to/alexindevs/bash-scripting-for-software-engineers-a-beginners-guide-1j65"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Script Overview
&lt;/h2&gt;

&lt;p&gt;This project had me creating a simple script that performs the following functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reads the users and groups supplied in the .txt file&lt;/li&gt;
&lt;li&gt;Creates the users and groups from read data&lt;/li&gt;
&lt;li&gt;Assigns randomly generated password to each user. Passwords are saved in &lt;code&gt;/var/secure/user_passwords.csv&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Adds users to appropriate groups&lt;/li&gt;
&lt;li&gt;Creates a &lt;code&gt;$HOME&lt;/code&gt; directory for each user with appropriate permission&lt;/li&gt;
&lt;li&gt;Logs all script actions in &lt;code&gt;/var/log/user_management.log&lt;/code&gt;
Each step will be explained.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project's repository can be found &lt;a href="https://github.com/xtasysensei/create-users-bash" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before running the script, ensure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Root privileges (the script needs to be run as root).&lt;/li&gt;
&lt;li&gt;An input file containing user information (e.g., employees.txt).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Detailed Explanation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Checking for Root Privileges
&lt;/h3&gt;

&lt;p&gt;The script starts by checking if it is being run as root. This is crucial because user and group management operations require root permissions.It does this by verifying the&lt;code&gt;$EUID&lt;/code&gt; variable is 0.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$EUID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: This script needs to run as root. Use sudo"&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating Necessary Directories
&lt;/h3&gt;

&lt;p&gt;If the required directories (/var/log and /var/secure) do not exist, the script creates them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create necessary directories if they don't exist&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; /var/log &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/log
&lt;span class="k"&gt;fi

if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; /var/secure &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/secure
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Logging Function
&lt;/h3&gt;

&lt;p&gt;A logging function log_message is defined to log messages with timestamps to a log file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;log_message&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +&lt;span class="s2"&gt;"%Y-%m-%d %H:%M:%S"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; - &lt;/span&gt;&lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$log_file&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Validating Input Arguments
&lt;/h3&gt;

&lt;p&gt;The script expects exactly one argument, the path to the employee file. If the argument is not provided or the file does not exist, it logs an error and exits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check for correct number of arguments&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"$#"&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 1 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nv"&gt;arg_err&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Usage: &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;file_path&amp;gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$arg_err&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    log_message &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$arg_err&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi  

&lt;/span&gt;&lt;span class="nv"&gt;employee_file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;

&lt;span class="c"&gt;# Check if the employee file exists&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$employee_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nv"&gt;file_missing_err&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Error: File '&lt;/span&gt;&lt;span class="nv"&gt;$employee_file&lt;/span&gt;&lt;span class="s2"&gt;' not found."&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file_missing_err&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    log_message &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file_missing_err&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Securing the Password File
&lt;/h3&gt;

&lt;p&gt;The password file is created and secures by setting correct permissions so that only the owner can read the file created for users and passwords. Permission &lt;strong&gt;600&lt;/strong&gt; only gives the owner read privileges&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Secure password file&lt;/span&gt;
log_message &lt;span class="s2"&gt;"Securing &lt;/span&gt;&lt;span class="nv"&gt;$password_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nv"&gt;$password_file&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"User,password"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$password_file&lt;/span&gt;
    &lt;span class="nb"&gt;chmod &lt;/span&gt;600 &lt;span class="nv"&gt;$password_file&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Processing Users and Groups
&lt;/h3&gt;

&lt;p&gt;The snippets below read the employee file line by line, processes each user and their associated groups, and performs the following operations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User Creation: Checks if the user exists, creates the user if not, and sets a random password.&lt;/li&gt;
&lt;li&gt;Group Creation: Creates a group with the same name as the user and adds the user to it. Also, adds the user to additional specified groups.&lt;/li&gt;
&lt;li&gt;Home Directory: Ensures the user has a home directory.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Let's break it down
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Reading the Input File
The snippet below reads each line from a file, splits the line into user and groups based on the semicolon, and then trims any extra whitespace from these variables.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;';'&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; user &lt;span class="nb"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c"&gt;# Read users and groups from the .txt file&lt;/span&gt;
    &lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | xargs&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;groups&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$groups&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | xargs&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It also checks if there is a blank line in between entries. The condition checks if either user or groups is empty (-z checks for a zero-length string).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$groups&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nv"&gt;newline_err&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Skipping invalid line in the input file"&lt;/span&gt;
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newline_err&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        log_message &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newline_err&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;continue
fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Creating user and group array
The snippet below logs and prints the user being processed, splits their groups into an array, trims any whitespace from each group, and then logs and prints the cleaned-up list of group
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=&amp;gt; Processing user: &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    log_message &lt;span class="s2"&gt;"Processing user: &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; group_array &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$groups&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="p"&gt;!group_array[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
        &lt;/span&gt;group_array[&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;]=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;group_array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | xargs&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;done

    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=&amp;gt; Groups for &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;group_array&lt;/span&gt;&lt;span class="p"&gt;[*]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    log_message &lt;span class="s2"&gt;"Groups for &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;group_array&lt;/span&gt;&lt;span class="p"&gt;[*]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Creating group with the same name as the user
This snippet checks if a group exists, creates the group if it does not exist, and logs the actions taken
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="c"&gt;# Create group with the same name as the user&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;getent group &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &amp;amp;&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
      &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Group &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; already exists."&lt;/span&gt;
      log_message &lt;span class="s2"&gt;"Group &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; already exists."&lt;/span&gt;
&lt;span class="k"&gt;else
      if &lt;/span&gt;groupadd &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
         &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=&amp;gt; Group &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; created."&lt;/span&gt;
         log_message &lt;span class="s2"&gt;"Group &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; created."&lt;/span&gt;
      &lt;span class="k"&gt;else
         &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error creating group &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
         log_message &lt;span class="s2"&gt;"Error creating group &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
         &lt;span class="k"&gt;continue
      fi
fi&lt;/span&gt;   
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a user exists our script logs it and moves on else the user is created and then logged.&lt;/p&gt;

&lt;p&gt;NOTE: &lt;code&gt;&amp;gt; /dev/null&lt;/code&gt; suppresses the response so that we don't have to see the output&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating &lt;code&gt;$HOME&lt;/code&gt; directory for user and generating passwords
This snippet handles the creation of users, including setting up their home directory and assigning a password, while logging all actions and errors appropriately
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="c"&gt;# Creating user, user's home directory and assigning a randomly generated password&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=&amp;gt; Creating user: &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;
    log_message &lt;span class="s2"&gt;"Creating user: &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &amp;amp;&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"User &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; already exists."&lt;/span&gt;
        log_message &lt;span class="s2"&gt;"User &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; already exists."&lt;/span&gt;
    &lt;span class="k"&gt;else
        if &lt;/span&gt;useradd &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$shell&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=&amp;gt; User &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; created with home directory /home/&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
            log_message &lt;span class="s2"&gt;"User &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; created with home directory /home/&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;

            &lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;head&lt;/span&gt; /dev/urandom | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nt"&gt;-dc&lt;/span&gt; A-Za-z0-9 | &lt;span class="nb"&gt;fold&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; 16 | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 1&lt;span class="si"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | chpasswd&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
                &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$password_file&lt;/span&gt;
                &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=&amp;gt; Password set for &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
                log_message &lt;span class="s2"&gt;"Password set for &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
            &lt;span class="k"&gt;else
                &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error setting password for &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
                log_message &lt;span class="s2"&gt;"Error setting password for &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
                &lt;span class="k"&gt;continue
            fi
        else
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error creating user &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
            log_message &lt;span class="s2"&gt;"Error creating user &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
            &lt;span class="k"&gt;continue
        fi
    fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;if useradd -m -s "$shell" -g "$user" "$user"&lt;/code&gt; attempts to create a new user with a home directory (-m), specified shell (-s "$shell"), and primary group (-g "$user").&lt;br&gt;
&lt;code&gt;password=$(head /dev/urandom | tr -dc A-Za-z0-9 | fold -w 16 | head -n 1)&lt;/code&gt; generates a random 16-character password using &lt;code&gt;urandom&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;if echo "$user:$password" | chpasswd; then&lt;/code&gt; sets the generated password for the user using the &lt;code&gt;chpasswd&lt;/code&gt; command.&lt;br&gt;
Finally, &lt;code&gt;echo "$user,$password" &amp;gt;&amp;gt; $password_file&lt;/code&gt; appends the user and their password to the specified password file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding user to specified groups
This snippet processes each user and adds them to the specified groups, creating the groups if they don't already exist
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;group &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;group_array&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
        if &lt;/span&gt;getent group &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &amp;amp;&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt; already exists."&lt;/span&gt;
            log_message &lt;span class="s2"&gt;"Group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt; already exists."&lt;/span&gt;
        &lt;span class="k"&gt;else
            if &lt;/span&gt;groupadd &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
                &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt; created."&lt;/span&gt;
                log_message &lt;span class="s2"&gt;"Group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt; created."&lt;/span&gt;
            &lt;span class="k"&gt;else
                &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error creating group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
                log_message &lt;span class="s2"&gt;"Error creating group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
                &lt;span class="k"&gt;continue
            fi
        fi
        if &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=&amp;gt; Added &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; to group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
            log_message &lt;span class="s2"&gt;"Added &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; to group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
        &lt;span class="k"&gt;else
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error adding &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; to group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
            log_message &lt;span class="s2"&gt;"Error adding &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; to group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
            &lt;span class="k"&gt;continue
        fi
done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It loops through the group, groups that don't exist are created with the &lt;code&gt;groupadd&lt;/code&gt; command.&lt;br&gt;
&lt;code&gt;if usermod -aG "$group" "$user"&lt;/code&gt; attempts to add the user to the group. It throws an error if the user is already a member of the group&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;End of Loop and File Processing
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"--------------------"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt; &amp;lt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$employee_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;echo "--------------------"&lt;/code&gt; prints a separator line for clarity in the output.&lt;br&gt;
&lt;code&gt;done &amp;lt; "$employee_file"&lt;/code&gt; continues processing the next user and group pairs from the employee_file.&lt;/p&gt;

&lt;h3&gt;
  
  
  The complete script looks like this
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;';'&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; user &lt;span class="nb"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c"&gt;# Read users and groups from the .txt file&lt;/span&gt;
    &lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | xargs&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;groups&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$groups&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | xargs&lt;span class="si"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$groups&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nv"&gt;newline_err&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Skipping invalid line in the input file"&lt;/span&gt;
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newline_err&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        log_message &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newline_err&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;continue
    fi

    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=&amp;gt; Processing user: &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    log_message &lt;span class="s2"&gt;"Processing user: &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; group_array &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$groups&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="p"&gt;!group_array[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
        &lt;/span&gt;group_array[&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;]=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;group_array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | xargs&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;done

    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=&amp;gt; Groups for &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;group_array&lt;/span&gt;&lt;span class="p"&gt;[*]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    log_message &lt;span class="s2"&gt;"Groups for &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;group_array&lt;/span&gt;&lt;span class="p"&gt;[*]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="c"&gt;# Create group with the same name as the user&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;getent group &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &amp;amp;&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Group &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; already exists."&lt;/span&gt;
        log_message &lt;span class="s2"&gt;"Group &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; already exists."&lt;/span&gt;
    &lt;span class="k"&gt;else
        if &lt;/span&gt;groupadd &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=&amp;gt; Group &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; created."&lt;/span&gt;
            log_message &lt;span class="s2"&gt;"Group &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; created."&lt;/span&gt;
        &lt;span class="k"&gt;else
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error creating group &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
            log_message &lt;span class="s2"&gt;"Error creating group &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
            &lt;span class="k"&gt;continue
        fi
    fi&lt;/span&gt;

    &lt;span class="c"&gt;# Creating user, user's home directory and assigning a randomly generated password&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=&amp;gt; Creating user: &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;
    log_message &lt;span class="s2"&gt;"Creating user: &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &amp;amp;&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"User &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; already exists."&lt;/span&gt;
        log_message &lt;span class="s2"&gt;"User &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; already exists."&lt;/span&gt;
    &lt;span class="k"&gt;else
        if &lt;/span&gt;useradd &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$shell&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=&amp;gt; User &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; created with home directory /home/&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
            log_message &lt;span class="s2"&gt;"User &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; created with home directory /home/&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;

            &lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;head&lt;/span&gt; /dev/urandom | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nt"&gt;-dc&lt;/span&gt; A-Za-z0-9 | &lt;span class="nb"&gt;fold&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; 6 | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 1&lt;span class="si"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | chpasswd&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
                &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$password_file&lt;/span&gt;
                &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=&amp;gt; Password set for &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
                log_message &lt;span class="s2"&gt;"Password set for &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
            &lt;span class="k"&gt;else
                &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error setting password for &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
                log_message &lt;span class="s2"&gt;"Error setting password for &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
                &lt;span class="k"&gt;continue
            fi
        else
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error creating user &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
            log_message &lt;span class="s2"&gt;"Error creating user &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
            &lt;span class="k"&gt;continue
        fi
    fi&lt;/span&gt;

    &lt;span class="c"&gt;# Add the user to other specified groups&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;group &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;group_array&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
        if &lt;/span&gt;getent group &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &amp;amp;&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt; already exists."&lt;/span&gt;
            log_message &lt;span class="s2"&gt;"Group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt; already exists."&lt;/span&gt;
        &lt;span class="k"&gt;else
            if &lt;/span&gt;groupadd &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
                &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt; created."&lt;/span&gt;
                log_message &lt;span class="s2"&gt;"Group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt; created."&lt;/span&gt;
            &lt;span class="k"&gt;else
                &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error creating group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
                log_message &lt;span class="s2"&gt;"Error creating group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
                &lt;span class="k"&gt;continue
            fi
        fi
        if &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=&amp;gt; Added &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; to group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
            log_message &lt;span class="s2"&gt;"Added &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; to group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
        &lt;span class="k"&gt;else
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error adding &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; to group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
            log_message &lt;span class="s2"&gt;"Error adding &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt; to group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
            &lt;span class="k"&gt;continue
        fi
    done

    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"--------------------"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt; &amp;lt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$employee_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;This project has taught me a lot about Linux permission system, user and group management, loops, conditionals and file manipulation in bash. For those interested in putting their skills to the test, you can head over to &lt;a href="https://hng.tech/internship" rel="noopener noreferrer"&gt;HNG Internship&lt;/a&gt; where they accept DevOps interns. It is totally free but a premium version  is available, visit &lt;a href="https://hng.tech/premium" rel="noopener noreferrer"&gt;here&lt;/a&gt; for more info.&lt;/p&gt;

&lt;p&gt;P.S: Any feedback will be appreciated. Thank you for reading.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>bash</category>
      <category>linux</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
