Skip to main content

Command Palette

Search for a command to run...

Linux User Creation Bash Script

Updated
7 min readView as Markdown
S

I am on my way to being a world class DevOps engineer.

Task : Your company has employed many new developers. As a SysOps engineer, write a bash script called create_users.sh that reads a text file containing the employee’s usernames and group names, where each line is formatted as user; groups.

Script Requirements :

  1. Create a bash script called create_users.sh

  2. Create users and groups with home directories and appropriate permissions and ownership.

  3. Generate random passwords for the users.

  4. Log all actions to /var/log/user_management.log

  5. Store passwords securely in /var/secure/user_passwords.txt

  6. Hand errors, such as existing users and log these errors.

Here is how to write a script that finds a solution to the given task.

  1. Declare Shebang

     #!/bin/bash
    

    Note: The very first step to writing a script is declaring shebang(#!). Then specify what type of script you're writing. Here, it's a bash script. Hence, its declared with /bain/bash.

  2. Declare Arrays

     #Declare User and Groups Arrays
     users=()
     groups=()
    

    The 'users' and 'groups' arrays are to store the usernames and group names read from the input file which allows to keep track of each user and their associated groups as you processed the input file, ensuring that users could be created and then added to their respective groups, including handling their password generation and logging actions accordingly.

  3. Declare logfiles and password paths

     #Declare logfiles and password paths
     log_file="/var/log/user_management.log"
     password=="/var/secure/user_passwords.txt"
    

    In this step, we establish the paths for the log file and password file in our bash script. The /var/log/user_management.log holds detail activities of a user while the /var/secure/user_passwords will securely store generated user passwords.

  4. Read the input file

     # Read input file using functions
     function readInputFile() {
         local file="$1"
         # Read input file
         while IFS= read -r line; do
             user=$(echo "$line" | cut -d';' -f1 | tr -d '[:space:]')
             group=$(echo "$line" | cut -d';' -f2 | tr -d '[:space:]')
             # Add user to the users array
             users+=("$user")
             # Add group to the groups array
             groups+=("$group")
         done < "$file"
     }
    

    This function reads the input file line by line, splitting each line into user and group using a semicolon as the delimiter. It trims any whitespace from these values and adds them to their respective arrays.

    First, we define a function called readInputFile. This function takes a file as argument, which is the path to the input file and reads it line by line.

    The IFS=';' sets the internal field separator to a semicolon, which allows us to split each line into user and group variables.

    Then clear any whitespace around the user and group values using the tr -d '[:space:]' command.

    The username and groups are added to their arrays using the users+=("$user") and groups+=("$groups") command.

  5. Check Argument Passed

     # Check if necessary amount of argument is passed(1 arg)
     if [ "$#" -ne 1 ]; then
         echo "Usage: $0 <input_file>"
         exit 1
     fi
    

    This checks if required argument is passed to the script, if not it displays a usage message and exits the script with an error status code.

  6. Read Input file

     # Read input file
     input_file="$1"
     echo "Reading your input file: $input_file"
     readInputFile "$input_file"
    

    Capture the file path which is assigned to a variable as an argument: input_file="$1"

    Print Information to terminal:echo "Reading your input file: $input_file"

    Call the Function to Read the File : read_input_file "$input_file"

  7. Check if log and password files exist and create them if they don't exist

     # Check existence of the log and password files, and create them if not
     if [ ! -f "$log_file" ]; then
         mkdir -p /var/log
         touch "$log_file"
         chmod 640 "$log_file"
     fi
    
     if [ ! -f "$password_file" ]; then
         mkdir -p /var/secure
         touch "$password_file"
         chmod 600 "$password_file"
     fi
    

    This checks if the log and password files exist and creates a /var/log and /var/secure directories and necessary files with it's necessary permissions assigned to it.

  8. Iterating Over Users Array in Bash

  9.  # Iterate over the users array
     for (( i = 0; i < ${#users[@]}; i++ )); do
         user="${users[$i]}"
         user_groups="${groups[$i]}"
    
         if id "$user" &>/dev/null; then
             echo "User $user already exists, Skipped" | tee -a "$log_file"
         else
    

    In the above script, to process each user and their associated group from arrays (users and groups), the script uses a for loop. Then, it assigns current username to user, assigns associated groups to groups and checks if user exists.

  10. Create User

     # Create user
            useradd -m -s /bin/bash "$user"
            if [[ $? -ne 0 ]]; then
                echo "Create User $user failed" | tee -a "$log_file"
                exit 1
            fi
            echo "User $user created successfully" | tee -a "$log_file"
    

    useradd -m -s /bin/bash "$user" creates the user with a home directory and sets the default shell to /bin/bash .

    if [[ $? -ne 0 ]]; then: Checks the exit status ($?) of the previous command (useradd). A non-zero exit status indicates an error during user creation.

    echo "User $user created successfully" | tee -a "$log_file": Logs a success message indicating that user creation was successful

    tee -a "$log_file": Appends the success message to the $log_file, ensuring that the action is logged for auditing or troubleshooting purposes.

  11. Set User Password

    # Set password
            password=$(openssl rand -base64 50 | tr -dc 'A-Za-z0-9!?%=' | head -c 10)
            echo "$user:$password" | chpasswd
            if [[ $? -ne 0 ]]; then
                echo "Set password for $user failed" | tee -a "$log_file"
                exit 1
            fi
            echo "Password for $user set successfully" | tee -a "$log_file"
            echo "$user,$password" >> "$password_file"
    

    This generates random passwords and appends the passwords to users using the openssl rand -base64 50 command to create a 50-character random string. It then filters the string to include only specific characters using tr -dc 'A-Za-z0-9!?%=' that includes alphabets, numbers and special characters and shortens it to 10 characters with head -c 10.

    The generated password is assigned to the user with the echo "$user:$password" | chpasswd command, thus setting the user's password. Then the script checks the chpasswd command's exit status using $?. If the command fails, it logs the error to a file and exits with status 1.

  12. Add User to Groups

     # Add user to personal group
            usermod -aG "$user" "$user"
            if [[ $? -ne 0 ]]; then
                echo "Add user $user to personal group failed" | tee -a "$log_file"
                exit 1
            fi
            echo "User $user added to personal group successfully" | tee -a "$log_file"
    
            # Add user to other groups
            IFS=',' read -r -a group_array <<< "$user_groups"
            for group in "${group_array[@]}"; do
                if grep -q "^$group:" /etc/group; then
                    echo "Group $group already exists" | tee -a "$log_file"
                else
                    groupadd "$group"
                    if [[ $? -ne 0 ]]; then
                        echo "Create group $group failed" | tee -a "$log_file"
                        exit 1
                    fi
                    echo "Group $group created successfully" | tee -a "$log_file"
                fi
                usermod -aG "$group" "$user"
                if [[ $? -ne 0 ]]; then
                    echo "Add user $user to group $group failed" | tee -a "$log_file"
                    exit 1
                fi
                echo "User $user added to group $group successfully" | tee -a "$log_file"
            done
        fi
    done
    
    exit 0
    

    This part of the script adds the user to its personal group by using the usermod -aG "$user" "$user" command to add each user to a group with the same name as their username. This ensures that every user has a personal group, which helps with file sharing and permissions management. If usermod fails, the script logs an error to a log file, which aids troubleshooting.

    The script the adds users to other specified groups and also manages users in multiple groups. It reads group names from the variable ($user_groups) which is separated by commas. The script checks for the existence of each group and creates it if necessary using groupadd. Then, it adds the user to each group with usermod -aG. This is important for setting up access permissions based on the members of the group.

  13. To Handle Errors and Logging

    The script logs any errors encountered during the addition of users to groups or the creation of groups by using the tee -a $log_file" as seen in the code. Then, exit 1 indicates an abnormal termination of the script due to an error.

After writing your script you save and exit your script, add executable permissions to the script, then execute your script to confirm that the written script functions correctly.

  • To save and exit the script, it depends on the text editor used to write the script.

    For Nano text editor: press ctrl + O (the letter 'O', not the number zero), then press the enter button to save the script and finally ctrl + x to exit the nano editor.

    For Vim text editor: press esc to ensure you are in normal mode, then press the colon button : , then type wq and finally, press the enter button to save and exit the script.

  • To add executable permissions to the script, you use the chmod +x thescriptname.sh command.

  • To execute the script, you use the sudo ./thescriptname.sh command.

Check out HNG here : https://hng.tech/internship, https://hng.tech/hire.