237

I need to have the ability to create user accounts on my Linux (Fedora 10) and automatically assign a password via a bash script(or otherwise, if need be).

It's easy to create the user via Bash e.g.:

[whoever@server ]#  /usr/sbin/useradd newuser

Is it possible to assign a password in Bash, something functionally similar to this, but automatically:

[whoever@server ]# passwd newuser
Changing password for user testpass.
New UNIX password:
Retype new UNIX password: 
passwd: all authentication tokens updated successfully.
[whoever@server ]#
Alex Kulinkovich
  • 4,408
  • 15
  • 46
  • 50
ModernCarpentry
  • 3,127
  • 2
  • 20
  • 14
  • 14
    Why is this offtopic? – OrangeTux Feb 28 '13 at 19:08
  • 24
    I think this question is on topic. One of the strongest trends now is the DevOps attitude of "configuration as code", i e that the platform is created by "programming" a sequence of admin steps that bootstrap the platform. To do user management in script mode is definitely part of this programming. – Dan Bergh Johnsson Oct 29 '13 at 12:08
  • 2
    As a DevOps, I think this is a useful question (with useful answers) but that's with my SysAdmin hat on. It might make more sense to move this to SuperUser. – Anthony Geoghegan Apr 02 '14 at 10:53
  • 1
    Similar question: http://askubuntu.com/q/94060/250556 – ThorSummoner Aug 31 '15 at 18:51
  • This can also be solved with an `expect` script. – Yaron Jun 26 '16 at 06:49

20 Answers20

241

You could also use chpasswd:

echo username:new_password | chpasswd

so, you change password for user username to new_password.

Kijewski
  • 25,517
  • 12
  • 101
  • 143
SilverDaemon
  • 2,511
  • 1
  • 14
  • 3
139

You can run the passwd command and send it piped input. So, do something like:

echo thePassword | passwd theUsername --stdin
Tralemonkey
  • 1,510
  • 1
  • 9
  • 2
  • 3
    Bonus of that method is that it's secure (assumed `echo` is a builtin in the used shell, which it is commonly), at least concerning `/proc/`. – Marian May 30 '10 at 00:16
  • 9
    I had to do `echo -e "password\npassword\n" | passwd` on 13.04 – d0c_s4vage Mar 22 '14 at 12:45
  • 35
    --stdin has been deprecated in newer Linux systems. Please use chpasswd instead. – wuxb Aug 10 '14 at 18:47
  • 18
    @MarkusOrreilly works, but not when using a provisioning tool like Ansible. As @Nybble stated, you should be using chpasswd. So here is what works: `echo 'myuser:mypass' | chpasswd`. Hope that helps. – Amir Rustamzadeh Nov 11 '14 at 15:26
  • can i put this in a docker file? I think it should edible for docker. – qubsup Aug 01 '17 at 14:24
  • see error https://paste.ubuntu.com/p/N5YVmvY2Td/ and script https://paste.ubuntu.com/p/HWcsMNZ8VJ/ and userlist file https://paste.ubuntu.com/p/GQGvvd5CTD/ – alhelal Apr 03 '18 at 16:30
  • 2
    I'm surprised no-one has mentioned the reason passwd doesn't make this easy: this approach will put the new password straight into the shell history, unless steps are taken to prevent this. Anyone committed to going this route, should keep this is mind. – Max Barraclough Dec 24 '19 at 13:59
125

I was asking myself the same thing, and didn't want to rely on a Python script.

This is the line to add a user with a defined password in one bash line:

useradd -p "$(openssl passwd -6 $PASS)" $USER
  • Note the double quote to prevent the shell interpreting included special parameters. Namely $ in this case.
  • This uses a SHA-512 hash, specified by the -6 flag. See openssl passwd --help for more options.

Edit: Since c87a7f31a3 the option -crypt is removed. Therefore replaced with -6 flag in the example above.

netzego
  • 372
  • 4
  • 15
Damien
  • 1,944
  • 2
  • 18
  • 21
  • 33
    `useradd -p $(openssl passwd -1 $PASS) $USER` is more modern, as back-ticks are deprecated and `$()` is recommended. – Bryson Feb 04 '14 at 14:09
  • An issue I had with this: I had created my user with a shell of zsh, not realizing that at that point zsh hadn't been installed. The password login will fail if you do this, so before you assume this isn't working (it will definitely work on today's Arch and on Debian 7) you might check that on a brand new installation. – Bryson Feb 04 '14 at 14:10
  • 5
    `useradd -m -p -s /bin/bash `, -m Crates home directory, -s specifies users defualt shell, substitute `password` and `user` for your needs. – ThorSummoner Aug 31 '15 at 18:50
  • 2
    You can also salt the password: `useradd -m -p $(openssl passwd -1 -salt $SALT $PASS)` . I think this is required on later Ubuntu's. – craigmj Apr 26 '17 at 06:34
  • 1
    @Bryson don't use `-1` as that one uses MD5, which is not secure anymore. Use `-crypt` (default at least in OpenSSL 1.1.1). – quapka Aug 10 '20 at 20:43
  • @Bryson Add quotes to stop your shell from interpreting special parameters like `$`. This is a great way to shoot yourself in the foot. – netzego Jun 04 '23 at 13:30
72

The code below worked in Ubuntu 14.04. Try before you use it in other versions/linux variants.

# quietly add a user without password
adduser --quiet --disabled-password --shell /bin/bash --home /home/newuser --gecos "User" newuser

# set password
echo "newuser:newpassword" | chpasswd
Ying
  • 2,660
  • 24
  • 23
  • 3
    i don't understand `--gecos` – Alban Oct 22 '14 at 11:25
  • 14
    http://en.wikipedia.org/wiki/Gecos_field The gecos field, or GECOS field is an entry in the /etc/passwd file on Unix, and similar operating systems. It is typically used to record general information about the account or its user(s) such as their real name and phone number. GECOS means General Electric Comprehensive Operating System, which has been renamed to GCOS when GE’s large systems division was sold to Honeywell. – Ying Oct 29 '14 at 18:10
  • This was the right answer for me on Debian 8, worked like a charm on my Server setup bash script! – propz Apr 01 '18 at 14:47
  • 1
    The GECOS field is basically a user description field. Write whatever you want down there. – Константин Ван Aug 06 '19 at 00:19
37

I liked Tralemonkey's approach of echo thePassword | passwd theUsername --stdin though it didn't quite work for me as written. This however worked for me.

echo -e "$password\n$password\n" | sudo passwd $user

-e is to recognize \n as new line.

sudo is root access for Ubuntu.

The double quotes are to recognize $ and expand the variables.

The above command passes the password and a new line, two times, to passwd, which is what passwd requires.

If not using variables, I think this probably works.

echo -e 'password\npassword\n' | sudo passwd username

Single quotes should suffice here.

Aditya
  • 369
  • 6
  • 20
Paul S
  • 1,424
  • 1
  • 14
  • 12
  • 3
    Works beautifully in bash. However, if running in sh, then -e option does not work. I found out the hard way that it actually outputs "-e". Luckily, the -e option is not necessary in sh, the escaping is default there. The portable version is to use printf "password\npassword\n" | ... instead. – Dan Bergh Johnsson Oct 29 '13 at 12:09
  • Perfect answer for ubuntu. – Mashpy Rahman Aug 31 '16 at 07:30
29

The following works for me and tested on Ubuntu 14.04. It is a one liner that does not require any user input.

sudo useradd -p $(openssl passwd -1 $PASS) $USERNAME

Taken from @Tralemonkey

cevaris
  • 5,671
  • 2
  • 49
  • 34
22

Single liner to create a sudo user with home directory and password.

useradd -m -p $(openssl passwd -1 ${PASSWORD}) -s /bin/bash -G sudo ${USERNAME}
Sandeep
  • 28,307
  • 3
  • 32
  • 24
12

You can use the -p option.

useradd -p encrypted_password newuser

Unfortunately, this does require you to hash the password yourself (where passwd does that for you). Unfortunately, there does not seem to be a standard utility to hash some data so you'll have to write that yourself.

Here's a little Python script I whipped up to do the encryption for you. Assuming you called it pcrypt, you would then write your above command line to:

useradd -p $(pcrypt ${passwd}) newuser

A couple of warnings to be aware of.

  1. While pcrypt is running, the plaintext will be visible to any user via the ps command.
  2. pcrypt uses the old style crypt function - if you are using something more moderns like an MD5 hash, you'll need to change pcrypt.

and here's pcrypt:

#!/usr/bin/env python

import crypt
import sys
import random

saltchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

def salt():
    return random.choice(saltchars) + random.choice(saltchars)

def hash(plain):
    return crypt.crypt(arg, salt())

if __name__ == "__main__":
    random.seed()
    for arg in sys.argv[1:]:
        sys.stdout.write("%s\n" % (hash(arg),))
R Samuel Klatchko
  • 74,869
  • 16
  • 134
  • 187
10

--stdin doesn't work on Debian. It says:

`passwd: unrecognized option '--stdin'`

This worked for me:

#useradd $USER
#echo "$USER:$SENHA" | chpasswd

Here we can find some other good ways:

Aditya
  • 369
  • 6
  • 20
Roger
  • 8,286
  • 17
  • 59
  • 77
  • This is the proper way to do it, and the only way officially supported by the maintainers of the shadow suite. See [this bug report](http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=525153). – yar Sep 07 '11 at 19:30
6

You can use expect in your bash script.

From http://www.seanodonnell.com/code/?id=21

#!/usr/bin/expect 
######################################### 
#$ file: htpasswd.sh 
#$ desc: Automated htpasswd shell script 
######################################### 
#$ 
#$ usage example: 
#$ 
#$ ./htpasswd.sh passwdpath username userpass 
#$ 
###################################### 

set htpasswdpath [lindex $argv 0] 
set username [lindex $argv 1] 
set userpass [lindex $argv 2] 

# spawn the htpasswd command process 
spawn htpasswd $htpasswdpath $username 

# Automate the 'New password' Procedure 
expect "New password:" 
send "$userpass\r" 

expect "Re-type new password:" 
send "$userpass\r"
Carlos Tasada
  • 4,438
  • 1
  • 23
  • 26
6

I know I'm coming at this years later, but I can't believe no one suggested usermod.

usermod --password `perl -e "print crypt('password','sa');"` root

Hell, just in case someone wants to do this on an older HPUX you can use usermod.sam.

/usr/sam/lbin/usermod.sam -F -p `perl -e "print crypt('password','sa');"` username

The -F is only needed if the person executing the script is the current user. Of course you don't need to use Perl to create the hash. You could use openssl or many other commands in its place.

Jeight
  • 398
  • 1
  • 5
  • 14
5

I've tested in my own shell script.

  • $new_username means newly created user
  • $new_password means newly password

For CentOS

echo "$new_password" | passwd --stdin "$new_username"

For Debian/Ubuntu

echo "$new_username:$new_password" | chpasswd

For OpenSUSE

echo -e "$new_password\n$new_password" | passwd "$new_username"
3

Here is a script that will do it for you .....

You can add a list of users (or just one user) if you want, all in one go and each will have a different password. As a bonus you are presented at the end of the script with a list of each users password. .... If you want you can add some user maintenance options

like:

chage -m 18 $user
chage -M 28 $user

to the script that will set the password age and so on.

=======

#!/bin/bash

# Checks if you have the right privileges
if [ "$USER" = "root" ]
then

# CHANGE THIS PARAMETERS FOR A PARTICULAR USE
PERS_HOME="/home/"
PERS_SH="/bin/bash"

   # Checks if there is an argument
   [ $# -eq 0 ] && { echo >&2 ERROR: You may enter as an argument a text file containing users, one per line. ; exit 1; }
   # checks if there a regular file
   [ -f "$1" ] || { echo >&2 ERROR: The input file does not exists. ; exit 1; }
   TMPIN=$(mktemp)
   # Remove blank lines and delete duplicates 
   sed '/^$/d' "$1"| sort -g | uniq > "$TMPIN"

   NOW=$(date +"%Y-%m-%d-%X")
   LOGFILE="AMU-log-$NOW.log"

   for user in $(more "$TMPIN"); do
      # Checks if the user already exists.
      cut -d: -f1 /etc/passwd | grep "$user" > /dev/null
      OUT=$?
      if [ $OUT -eq 0 ];then
         echo >&2 "ERROR: User account: \"$user\" already exists."
         echo >&2 "ERROR: User account: \"$user\" already exists." >> "$LOGFILE"
      else
         # Create a new user
         /usr/sbin/useradd -d "$PERS_HOME""$user" -s "$PERS_SH" -m "$user"
         # passwdgen must be installed
         pass=$(passwdgen -paq --length 8)
         echo $pass | passwd --stdin $user
         # save user and password in a file
         echo -e $user"\t"$pass >> "$LOGFILE"
         echo "The user \"$user\" has been created and has the password: $pass"
      fi
   done
   rm -f "$TMPIN"
   exit 0
else
   echo >&2 "ERROR: You must be a root user to execute this script."
   exit 1
fi

===========

Hope this helps.

Cheers, Carel

3

The solution that works on both Debian and Red Hat. Depends on perl, uses sha-512 hashes:

cat userpassadd
    #!/usr/bin/env bash

    salt=$(cat /dev/urandom | tr -dc A-Za-z0-9/_- | head -c16)
    useradd -p $(perl -e "print crypt('$2', '\$6\$' . '$salt' . '\$')") $1

Usage:

userpassadd jim jimslongpassword

It can effectively be used as a one-liner, but you'll have to specify the password, salt and username at the right places yourself:

useradd -p $(perl -e "print crypt('pass', '\$6\$$salt\$')") username

Sam Sirry
  • 631
  • 5
  • 22
golem
  • 1,820
  • 1
  • 20
  • 25
2

From IBM (https://www.ibm.com/support/knowledgecenter/ssw_aix_61/com.ibm.aix.cmds1/chpasswd.htm):

Create a text file, say text.txt and populate it with user:password pairs as follows:

user1:password1
user2:password2
...
usern:passwordn

Save the text.txt file, and run

cat text.txt | chpassword

That's it. The solution is (a) scalable and (b) does not involve printing passwords on the command line.

Vietnhi Phuvan
  • 2,704
  • 2
  • 25
  • 25
1
{ echo $password; echo $password; } | passwd $username 
edacval
  • 11
  • 1
  • Whilst this may theoretically answer the question, [it would be preferable](http://meta.stackoverflow.com/q/8259) to include the essential parts of the answer here. – Werner Feb 07 '15 at 13:00
1

For RedHat / CentOS here's the code that creates a user, adds the passwords and makes the user a sudoer:

#!/bin/sh
echo -n "Enter username: "
read uname

echo -n "Enter password: "
read -s passwd

adduser "$uname"
echo $uname:$passwd | sudo chpasswd

gpasswd wheel -a $uname
Lefty G Balogh
  • 1,771
  • 3
  • 26
  • 40
1

usage: ./my_add_user.sh USER PASSWD

code:

#!/bin/bash
# my_add_user.sh

if [ "$#" -lt 2 ] 
 then
       echo "$0 username passwd"
       exit
fi

user=$1
passwd=$2

useradd $user -d /data/home/$user  -m  ;
echo $passwd | passwd $user --stdin;
hustljian
  • 965
  • 12
  • 9
1

Tralemonkey's solution almost worked for me as well ... but not quite. I ended up doing it this way:

echo -n '$#@password@#$' | passwd myusername --stdin

2 key details his solution didn't include, the -n keeps echo from adding a \n to the password that is getting encrypted, and the single quotes protect the contents from being interpreted by the shell (bash) in my case.

BTW I ran this command as root on a CentOS 5.6 system in case anyone is wondering.

slm
  • 15,396
  • 12
  • 109
  • 124
0

Kindly run below script with sudo permission for creating a user by script.

Note: This script supports all linux OSs like Redhat, Centos, Ubuntu, suse, kali, Arch, Bitname, BSD....etc

#!/bin/bash
#author: bablish jaiswal
#purpos: Linux user creation with a storng password
clear
#echo "Hi, I am a function to create sudo user with strong password. Kindly share following information"
echo -e "\n\n\n"
printf "\e[6;33mHi, I am a function to create sudo user with a strong password. Kindly share following information\e[0m";echo
read -p "user name:- " name #input name
read -p "complete path for $name home directory? example: /home/$name :- " home #user home path
( useradd  -m -d $home $name -s /bin/bash ) > /dev/null 2>&1
pass=$(cat /dev/urandom |tr -dc "[[:graph:]]" |head -c16)
(echo -e "$pass\n$pass" | passwd $name ) > /dev/null 2>&1
echo " "
printf "\e[6;33m-----------------------------Copy below credentials-------------------------\e[0m";echo
echo -e "User:- $name\nHomeDir:- $home\npassword:- $pass"
#svalue=$(cat /etc/sudoers |grep -i root |grep -i all|tail -n1 |awk '{$1=""}1')
svalue=$(cat /etc/sudoers |grep -i root |grep -i all|tail -n1 |awk '{print $2}')
echo "${name} ${svalue} NOPASSWD:ALL" >> /etc/sudoers && echo “Remark:- User $name is a sudo user”
linux.cnf
  • 519
  • 6
  • 7