Non-Interactive User Password Change in Linux: Command Line Methods Without Expect


3 views

When automating Linux system administration tasks, you often need to change user passwords without manual interaction. Traditional methods like passwd command require STDIN input, which isn't ideal for scripting scenarios.

The most straightforward method is using chpasswd, which reads username:password pairs from STDIN:

echo "username:newpassword" | sudo chpasswd

For Ubuntu/Debian systems, you can also use:

echo "username:$(openssl passwd -6 'newpassword')" | sudo chpasswd -e

Another approach is using usermod with encrypted passwords:

sudo usermod --password $(echo "newpassword" | openssl passwd -1 -stdin) username

While these methods work, be aware that:

  • Command line arguments may be visible in process lists
  • Bash history may store sensitive commands
  • For production systems, consider using SSH certificates or other auth methods

When implementing this in scripts:

# Secure method using environment variable
NEWPASS="complex_password_here"
echo "username:$NEWPASS" | sudo chpasswd
unset NEWPASS

If encountering issues:

# Check password policy requirements
sudo grep -E "^PASS" /etc/login.defs

# Verify password change worked
sudo grep username /etc/shadow

For Ubuntu/Debian systems, the most direct method is using the chpasswd utility which is specifically designed for batch password changes:

echo "username:newpassword" | sudo chpasswd

This works because chpasswd reads username:password pairs from stdin. The command needs root privileges, hence the sudo.

If chpasswd isn't available, here are three other approaches:

Using passwd with --stdin

echo "newpassword" | sudo passwd --stdin username

Note: The --stdin flag isn't available on all Linux distributions, but works on many including some Ubuntu versions.

Using usermod

sudo usermod --password $(echo "newpassword" | openssl passwd -1 -stdin) username

This method hashes the password first using OpenSSL before passing it to usermod.

Python One-liner

python -c "import crypt; print(crypt.crypt('newpassword', crypt.mksalt(crypt.METHOD_SHA512)))" | sudo tee /etc/shadow

While these methods work, be aware that:

  • The password appears in shell history
  • Visible in process listings during execution
  • Potential exposure through SSH logging

For production systems, consider using SSH keys or temporary password files that get immediately deleted.

Here's how you might implement this in an automated provisioning script:

#!/bin/bash
NEW_USER="deploy"
TEMP_PASS="initPass123!"

# Create user if doesn't exist
id -u $NEW_USER &>/dev/null || sudo useradd -m $NEW_USER

# Set password non-interactively
echo "$NEW_USER:$TEMP_PASS" | sudo chpasswd

# Force password change on first login
sudo passwd -e $NEW_USER

This creates a user with a temporary password that must be changed at first login.