Using passwd Command in Shell Script

Written by: Linuxopsys   |   Last updated: September 8, 2023

Introduction

The passwd command in Unix-like systems lets users change passwords. By using it in shell scripts, we can automate and simplify password management tasks.

Interactive Approach

In the interactive approach, the passwd command will prompt the user to manually enter the new password and then re-enter it for confirmation. This is the most common method used when running the passwd command from the command line.

Example: This script prompts the user for a username and then invokes the passwd command for that user, which will then prompt the user to set a new password for the given username.

#!/bin/bash

read -p "Enter the username whose password you want to change: " username
passwd $username

Usage:

./changepass.sh
Enter the username whose password you want to change: bob
New password:
Retype new password:
passwd: password updated successfully

When you run this script, it will ask for the username and then prompt you to enter the new password for the given username twice (for confirmation).

This method is safest because the password isn't exposed in any command or script, and it's not visible to other users through commands like ps.

Here the password itself does not get stored in the command history. However, the invocation of the passwd command itself (without the password) would still appear in the history.

In the above script, we had to provide the password twice, we can change that behavior by piping the new password to the passwd command twice - once for the new password and once for its confirmation:

echo -e "$newpassword\n$newpassword" | sudo passwd "$username"

Example: The script's goal is to provide the password and its confirmation to the passwd command without the user having to type it twice.

#!/bin/bash

read -p "Please enter the username whose password you want to change: " username
if id "$username" &>/dev/null; then
    echo "Please enter the new password for $username:"
    read -s newpassword

    echo -e "$newpassword\n$newpassword" | sudo passwd "$username"
  
    if [ $? -eq 0 ]; then
        echo "Password for $username has been changed successfully."
    else
        echo "Failed to change the password for $username."
    fi
else
    echo "User $username does not exist."
fi

Usage:

./changnotwice.sh
Please enter the username whose password you want to change: bob
Please enter the new password for bob:
New password: Retype new password: passwd: password updated successfully
Password for bob has been changed successfully.

In this example, the read command is used with -s option, which does not show input characters (useful for sensitive information like passwords).

On some systems or configurations, passwd might not support taking input from stdin in this manner. To avoid such issues and have consistent behavior across different environments, more advanced tools like expect can be used, but they introduce additional complexity. Example:

#!/usr/bin/expect -f

send_user "Enter username: "
expect_user -re "(.*)\n" {
    set username $expect_out(1,string)
}

send_user "Enter new password for $username: "
expect_user -re "(.*)\n" {
    set newpassword $expect_out(1,string)
}

# Start the process
spawn sudo passwd $username

expect "New password:" 
send "$newpassword\r"

expect "Retype new password:"
send "$newpassword\r"

expect {
    "password updated successfully" {
        exit 0
    }
    "BAD PASSWORD:" {
        send_user "Failed to update password: Bad password.\n"
        exit 1
    }
    timeout {
        send_user "Script timed out\n"
        exit 2
    }
}

# Done
exit 0

Usage:

./chgexpect.sh
Enter username: bob
Enter new password for bob: bob
spawn sudo passwd bob
New password:
Retype new password:

Non-interactive Approach

In the non-interactive approach, the password is supplied to the passwd command without manual intervention, typically through piping or redirection. This can be done using passwd's --stdin option (on systems that support it) or using other utilities like chpasswd.

Using --stdin option

Using the --stdin option with the passwd command is another way to change a user's password non-interactively. When using this method, the new password is provided to passwd via its standard input.

Here's how you can use the --stdin option:

#!/bin/bash

username="$1"
new_password="$2"

echo "$new_password" | sudo passwd --stdin $username

When the script runs, the new password is echoed and piped directly to the passwd command, which changes the password for the specified user.

Note: If you're seeing the error message passwd: unrecognized option '--stdin', it means that the passwd command on your system doesn't support the --stdin option. This option is typically available on some distributions like CentOS Stream or RHEL, but may not be present on others, like Ubuntu.

Using echo and passwd

The combination of echo and passwd is often employed to update a user's password programmatically without having to interact with the passwd command's prompts. You can pipe the password twice into passwd.

#!/bin/bash

username="$1"
new_password="$2"

echo -e "$new_password\n$new_password" | sudo passwd $username

if [ $? -eq 0 ]; then
    echo "Password for $username has been changed successfully."
else
    echo "Failed to change the password for $username."
fi

Usage:

./chgecho.sh bob mynewpass321
New password: Retype new password: passwd: password updated successfully
Password for bob has been changed successfully.

Alternatively, you can have the script generate a somewhat random password, after execution, the password for target_username will be changed to the generated password. Example:

#!/bin/bash

username="$1"
new_password=$(date | sha256sum | cut -c1-8)
echo -e "$new_password\n$new_password" | passwd $username

Now, when you run the script, it will use the first 8 characters from the SHA-256 hash of the current date and time as the password.

Usage:

./chgsha.sh bob
New password: Retype new password: passwd: password updated successfully

Using chpasswd

chpasswd allows you to update passwords in batch mode. It reads a list of username and password pairs from standard input and updates the passwords. Passwords must be provided in clear text (not encrypted).

Example:

#!/bin/bash

username="$1"
new_password="$2"

echo "$username:$new_password" | sudo chpasswd

if [ $? -eq 0 ]; then
    echo "Password for $username has been changed successfully."
else
    echo "Failed to change the password for $username."
fi

Usage:

./chgtool.sh bob mynewpass321
Password for bob has been changed successfully.

In the above example, after executing chpasswd, we manually check the exit status ($?) to determine if the command was successful (exit status 0) or if there was an error (any other exit status). Based on this, we provide custom feedback with the echo command.

Note: The chpasswd doesn't usually produce verbose output. When it successfully updates passwords, it simply returns without any message. If there's an error, it will return an error message.

SHARE

Comments

Please add comments below to provide the author your ideas, appreciation and feedback.

Leave a Reply

Leave a Comment