Search for:
  • Home/
  • Bash/
  • Comparing and Contrasting Bash and Python Scripts for User Creation

Comparing and Contrasting Bash and Python Scripts for User Creation

In this blog post, we’ll delve into the world of scripting for system administration, specifically focusing on user account creation. We’ll compare and contrast two scripts: a Bash script and its Python counterpart. Both aim to achieve the same goal – creating a new user account on a Linux system – but they do so in different ways, each with its own strengths and weaknesses.

Overview of the Bash Script

The Bash script provided is a straightforward, interactive script intended for creating a user account on a Linux system. Here are its key features:

  1. Superuser Check: It starts by ensuring it’s run with superuser privileges, crucial for performing user account operations.
  2. User Interaction: The script uses the read command to interactively gather the username, the real name (for the account comment), and the password.
  3. Account Creation and Management: Utilising useradd to create the user account, it then sets the password using the passwd command and forces a password change on the first login.
  4. Security Note: The script is not secure for production use as it handles passwords in cleartext, which can be a significant security risk.
# This script adds new users on the local system.
# It requires at least one argument: the username. Remaining arguments will be treated as the comment.
# The script generates a secure password with random special characters for the new account.
# It must be executed with superuser privileges.

# Check for superuser privileges
if [[ "${UID}" -ne 0 ]]; then
  echo 'Error: You must be a superuser to run this script.' >&2
  exit 1

# Check if at least one argument is provided
if [[ "${#}" -lt 1 ]]; then
  echo "Usage: ${0} USER_NAME [COMMENT]..." >&2
  echo 'Provide a username and optionally a comment.' >&2
  exit 1

# Assign the first argument as the username

# Concatenate the remaining arguments as the comment

# Define the set of special characters

# Generate the base password
PASSWORD=$(date +%s%N${RANDOM}${RANDOM} | sha256sum | head -c48)

# Decide on a random number of special characters to add (up to 10)

# Generate a string of random special characters
RANDOM_SPECIALS=$(echo "$SPECIAL_CHARS" | fold -w1 | shuf | head -c$NUM_SPECIAL_CHARS)

# Combine the base password and random specials

# Shuffle the combined string to mix special characters within
FINAL_PASSWORD=$(echo "$COMBINED_PASSWORD" | fold -w1 | shuf | tr -d '\n')

# Create the user with the provided username and comment
useradd -c "${COMMENT}" -m "${USER_NAME}" &> /dev/null

if [[ "${?}" -ne 0 ]]; then
  echo "The user creation for ${USER_NAME} failed." >&2
  exit 1

# Set the password for the user
echo "${USER_NAME}:${FINAL_PASSWORD}" | chpasswd

if [[ "${?}" -ne 0 ]]; then
  echo "Setting the password for ${USER_NAME} failed." >&2
  exit 1

# Force password change on first login
passwd -e "${USER_NAME}"

# Display the username, password, and the host
echo "User: ${USER_NAME}"
echo "Password: ${FINAL_PASSWORD}"
echo "Host: ${HOST_NAME}"

exit 0

Bash Script Pros and Cons


  • Simplicity: Easy to understand and modify, even for those new to scripting.
  • Direct System Interaction: Bash scripts are ‘close to the metal’ in terms of interacting directly with system commands.


  • Security Risks: Handling passwords in cleartext is a major vulnerability.
  • Limited Error Handling: Bash has less sophisticated error handling compared to more advanced programming languages like Python.

Python Script for User Creation

Let’s consider a Python equivalent that accomplishes the same task. This script would utilise modules like subprocess for executing system commands, and getpass for securely handling passwords. Python’s standard libraries offer more tools for secure and efficient scripting.

# Importing the subprocess module to run shell commands from within Python.
# This is used for executing user creation and password setting commands.
import subprocess

# Importing the random module to generate random numbers and select random characters.
# This is used for creating a part of the secure password.
import random

# Importing the hashlib module for cryptographic hashing.
# It's used here to hash a random string for password generation.
import hashlib

# Importing the os module to generate a secure random byte string.
# This is utilised for the base of the password before hashing.
import os

def add_user(username, comment):
    Create a new user with a secure, randomly generated password.

    username (str): The username for the new user.
    comment (str): The comment or description for the user account.

    str: The generated password for the new user.

    # Generate a secure password:
    # - Use os.urandom to generate a random byte string of length 48.
    # - Encode this byte string and hash it using SHA256.
    # - Convert the hash to a hexadecimal representation.
    base_password = hashlib.sha256(os.urandom(48)).hexdigest()

    # Define a string of special characters for the password.
    special_chars = '!@#$%^&*()-+='

    # Generate a random number of special characters to be added to the password.
    # The number of special characters is between 1 and 10.
    num_specials = random.randint(1, 10)
    random_specials = ''.join(random.sample(special_chars, num_specials))

    # Combine the base password with the random special characters.
    combined_password = base_password + random_specials

    # Shuffle the combined password to mix the special characters within it.
    final_password = ''.join(random.sample(combined_password, len(combined_password)))

    # Create the user account using the 'useradd' command.
    # - The username and comment are passed as arguments.
    # - The command is executed with '' to ensure it runs correctly.
    try:['useradd', '-c', comment, '-m', username], check=True)

        # Set the password for the user.
        # This is done by piping the password to the 'chpasswd' command using shell execution.
        set_password_command = "echo '{}:{}' | chpasswd".format(username, final_password)['sh', '-c', set_password_command], check=True)

    except subprocess.CalledProcessError as e:
        # Print the error if the subprocess fails.
        print("Error: {}".format(e))

    # Return the generated password.
    return final_password

# Example usage of the function.
# - 'newuser' is the username.
# - 'New User' is the comment.
password = add_user('newuser', 'New User')

# Print the username and password.
print("User: newuser")
print("Password: {}".format(password))

Comparing Python to Bash

Python Advantages:

  • Enhanced Security: Python can handle sensitive data like passwords more securely, especially when combined with additional libraries.
  • Advanced Error Handling: Python’s exception handling offers more control over dealing with errors.
  • Versatility and Scalability: Python scripts can be easily integrated into larger systems, and Python’s vast array of libraries allows for more complex operations.

Python Disadvantages:

  • Complexity: For simple system administration tasks, Python scripts can be overkill and less straightforward than Bash scripts.
  • Additional Overhead: Python scripts can introduce more overhead, both in terms of performance and in terms of system dependencies.


While the Bash script is well-suited for simple, quick tasks and is highly effective in the hands of an experienced system administrator, Python offers more robustness, security, and scalability, which is crucial for larger, more complex systems. The choice between Bash and Python ultimately depends on the specific requirements of the task at hand, the environment in which the script will run, and the level of security and complexity required.

Through this comparison, we see that both Bash and Python have their places in the toolbox of system administration. The key is to choose the right tool for the job, considering the balance between simplicity, security, and functionality.

Leave A Comment

All fields marked with an asterisk (*) are required