[linux] Using the passwd command from within a shell script

I'm writing a shell script to automatically add a new user and update their password. I don't know how to get passwd to read from the shell script instead of interactively prompting me for the new password. My code is below.

adduser $1
passwd $1
$2
$2

This question is related to linux bash unix shell

The answer is


You could use chpasswd

echo $1:$2 | chpasswd


Nowadays, you can use this command:

echo "user:pass" | chpasswd

This is the definitive answer for a teradata node admin.

Go to your /etc/hosts file and create a list of IP's or node names in a text file.

SMP007-1
SMP007-2
SMP007-3

Put the following script in a file.

#set a password across all nodes
printf "User ID: "
read MYUSERID
printf "New Password: "
read MYPASS

while read -r i; do
    echo changing password on "$i"
    ssh root@"$i" sudo echo "$MYUSERID":"$MYPASS" | chpasswd
    echo password changed on "$i"
done< /usr/bin/setpwd.srvrs

Okay I know I've broken a cardinal security rule with ssh and root but I'll let you security folks deal with it.

Now put this in your /usr/bin subdir along with your setpwd.srvrs config file.

When you run the command it prompts you one time for the User ID then one time for the password. Then the script traverses all nodes in the setpwd.srvrs file and does a passwordless ssh to each node, then sets the password without any user interaction or secondary password validation.


For me on Raspbian it works only this way (old password added):

#!/usr/bin/env bash

username="pi"
password="Szevasz123"
new_ps="Szevasz1234"

passwd ${username} << EOD
${password}
${new_ps}
${new_ps}
EOD

For those who need to 'run as root' remotely through a script logging into a user account in the sudoers file, I found an evil horrible hack, that is no doubt very insecure:

sshpass -p 'userpass' ssh -T -p port user@server << EOSSH
sudo -S su - << RROOT
userpass
echo ""
echo "*** Got Root ***"
echo ""
#[root commands go here]
useradd -m newuser
echo "newuser:newpass" | chpasswd
RROOT
EOSSH

Here-document works if your passwd doesn't support --stdin and you don't want to (or can't) use chpasswd for some reason.

Example:

#!/usr/bin/env bash

username="user"
password="pass"

passwd ${username} << EOD
${password}
${password}
EOD

Tested under Arch Linux. This passwd is an element of shadow-utils and installed from the core/filesystem package, which you usually have by default since the package is required by core/base.


Have you looked at the -p option of adduser (which AFAIK is just another name for useradd)? You may also want to look at the -P option of luseradd which takes a plaintext password, but I don't know if luseradd is a standard command (it may be part of SE Linux or perhaps just an oddity of Fedora).


You can use the expect utility to drive all programs that read from a tty (as opposed to stdin, which is what passwd does). Expect comes with ready to run examples for all sorts of interactive problems, like passwd entry.


Tested this on a CentOS VMWare image that I keep around for this sort of thing. Note that you probably want to avoid putting passwords as command-line arguments, because anybody on the entire machine can read them out of 'ps -ef'.

That said, this will work:

user="$1"
password="$2"
adduser $user
echo $password | passwd --stdin $user

Read the wise words from:

I quote:

Nothing you can do in bash can possibly work. passwd(1) does not read from standard input. This is intentional. It is for your protection. Passwords were never intended to be put into programs, or generated by programs. They were intended to be entered only by the fingers of an actual human being, with a functional brain, and never, ever written down anywhere.

Nonetheless, we get hordes of users asking how they can circumvent 35 years of Unix security.

It goes on to explain how you can set your shadow(5) password properly, and shows you the GNU-I-only-care-about-security-if-it-doesn't-make-me-think-too-much-way of abusing passwd(1).

Lastly, if you ARE going to use the silly GNU passwd(1) extension --stdin, do not pass the password putting it on the command line.

echo $mypassword | passwd --stdin # Eternal Sin.
echo "$mypassword" | passwd --stdin # Eternal Sin, but at least you remembered to quote your PE.
passwd --stdin <<< "$mypassword" # A little less insecure, still pretty insecure, though.
passwd --stdin < "passwordfile" # With a password file that was created with a secure `umask(1)`, a little bit secure.

The last is the best you can do with GNU passwd. Though I still wouldn't recommend it.

Putting the password on the command line means anyone with even the remotest hint of access to the box can be monitoring ps or such and steal the password. Even if you think your box is safe; it's something you should really get in the habit of avoiding at all cost (yes, even the cost of doing a bit more trouble getting the job done).


Sometimes it is useful to set a password which nobody knows. This seems to work:

tr -dc A-Za-z0-9 < /dev/urandom | head -c44 | passwd --stdin $user

I stumbled upon the same problem and for some reason the --stdin option was not available on the version of passwd I was using (shipped in Ubuntu 14.04).

If any of you happen to experience the same issue, you can work it around as I did, by using the chpasswd command like this:

echo "<user>:<password>" | chpasswd

The only solution works on Ubuntu 12.04:

echo -e "new_password\nnew_password" | (passwd user)

But the second option only works when I change from:

echo "password:name" | chpasswd

To:

echo "user:password" | chpasswd

See explanations in original post: Changing password via a script


Examples related to linux

grep's at sign caught as whitespace How to prevent Google Colab from disconnecting? "E: Unable to locate package python-pip" on Ubuntu 18.04 How to upgrade Python version to 3.7? Install Qt on Ubuntu Get first line of a shell command's output Cannot connect to the Docker daemon at unix:/var/run/docker.sock. Is the docker daemon running? Run bash command on jenkins pipeline How to uninstall an older PHP version from centOS7 How to update-alternatives to Python 3 without breaking apt?

Examples related to bash

Comparing a variable with a string python not working when redirecting from bash script Zipping a file in bash fails How do I prevent Conda from activating the base environment by default? Get first line of a shell command's output Fixing a systemd service 203/EXEC failure (no such file or directory) /bin/sh: apt-get: not found VSCode Change Default Terminal Run bash command on jenkins pipeline How to check if the docker engine and a docker container are running? How to switch Python versions in Terminal?

Examples related to unix

Docker CE on RHEL - Requires: container-selinux >= 2.9 What does `set -x` do? How to find files modified in last x minutes (find -mmin does not work as expected) sudo: npm: command not found How to sort a file in-place How to read a .properties file which contains keys that have a period character using Shell script gpg decryption fails with no secret key error Loop through a comma-separated shell variable Best way to find os name and version in Unix/Linux platform Resource u'tokenizers/punkt/english.pickle' not found

Examples related to shell

Comparing a variable with a string python not working when redirecting from bash script Get first line of a shell command's output How to run shell script file using nodejs? Run bash command on jenkins pipeline Way to create multiline comments in Bash? How to do multiline shell script in Ansible How to check if a file exists in a shell script How to check if an environment variable exists and get its value? Curl to return http status code along with the response docker entrypoint running bash script gets "permission denied"