Import users from CSV file

8,367

Solution 1

There's an app for that! The newusers tool which is part of the passwd package is designed to batch create users:

DESCRIPTION
   The newusers command reads a file (or the standard input by default)
   and uses this information to update a set of existing users or to
   create new users. Each line is in the same format as the standard
   password file (see passwd(5)) with the exceptions explained below:

You will need to create a file with this format:

username:passwd:UID:GID:full name,room number,work phone,home phone,other:directory:shell

Many of these can be ignored and the default values will be used. You only need to specify the username and password. For example:

tom:password1:::::
danny:password2:::::

If I save that as users.txt and run this command:

sudo newusers < users.txt 

The users are created:

$ grep -E 'tom|danny' /etc/passwd
tom:x:1005:1006:::
danny:x:1006:1007:::

Solution 2

With a script you can. This needs a file with user and password commaseparated:

while IFS="," read -r user passwd ; do      
        echo "useradd -m -p $(mkpasswd "$passwd") $user"
done < /home/$USER/Downloads/users.txt
  • mkpasswd can be installed with sudo apt-get install whois
  • Change the , to a ; if you need that.

Save this as users.sh and set permissions with chmod +x users.sh

If you then do

./users.sh > users_create.sh

You get a text file with all the commands so you can verify it and

chmod +x users.sh
./users_create.sh

will then create them.


Testing

Example file:

wdn,password123 
wdn2,password345

saved as "users.txt" in "~/Downloads".

Execute script:

./users.sh 
useradd -m -p acBNi2tbw9iaw wdn
useradd -m -p OHOzeMGqbcMso wdn2

and

./users.sh  > users_create.sh
~/Downloads$ more users_create.sh 
useradd -m -p Q1BVotdoA3ucI wdn
useradd -m -p siUX7mYTYw.3A wdn2

(password are encrypted).

After this all you need to do is execute is to make this executable with chmod +x users.sh and execute it with ./users_create.sh (I did not do that last bit so if not working please comment).

Solution 3

Here is an awk one-liner:

sudo awk -F',' '{ command="useradd -p $( mkpasswd "$2" ) "$1;print command; system(command) }' userlist.txt

Or for readability, here's the format:

sudo awk -F',' '{ 
            command="useradd -p $(mkpasswd "$2 ")" $1; 
            print command; 
            system(command)
           }' userlist.txt

Explanation:

awk's system function allows running shell commands while awk is processing entries from text file. We create a variable "command" that is just text of the command we want to run. Using comma as field separator -F',' , we take field #2 and #1 and place them to match syntax of the useradd command. Once the text of the command is assembled, system(command) executes useradd -p $(mkpasswd password) username , for each line of the text. print command part is optional, merely for debugging and verifying that all usernames have been processed

Addition:

The oneliner can be turned into an awk script like so:

#!/usr/bin/awk -f


BEGIN {FS=",";}

{ 
     command="useradd -p $(mkpasswd "$2") " $1; 
     print command; 
    system( command )
}

Now make sure the script has executable permissions with sudo chmod +x script-name.awk and run it with any input file like so sudo ./awkscript.sh userlist.txt if it is in your current working directory, or you can call that script anywhere by placing it into one of the $PATH directories

Possible , in the password

To take into account possibility of having comma in password, I suggest you use sub() function. Sub function changes first instance of a character or word in each line. In other words, if we have an entry such as testuser,foo,bar, where foo,bar is password, and we change first entry to space, we can use awk normally , without telling it to use -F',' flag. Awk will translate each entry to testuser foo,bar, and treat testuser as $1 and foo,bar as $2. To put this into code:

sudo awk '{ sub(","," ");command="useradd -p $( mkpasswd "$2" ) "$1;print command; system(command) }' userlist.txt

Solution 4

Here is a python solution:

#!/usr/bin/env python2
import subprocess, crypt

with open('/path/to/file.csv') as f:
    for line in f:
        i = line.find(',')
        name = line[:i]
        password = line.rstrip()[i+1:]
        encpt_passwd = crypt.crypt(password, '2b')
        command = 'useradd -m -p {0} {1}'.format(encpt_passwd, name).split()
        subprocess.call(command)

This will handle passwords having commas.

  • line.find(',') will find the lowest index of , in each line of the file

  • line[:i] will take the slice of the line containg the username

  • line.rstrip()[i+1:] will contain the password

  • crypt module generates encrypted password from input of the form crypt.crypt(password, salt). encpt_passwd will contain the encrypted password. In crypt.crypt(password, '2b'), password is the saved plain password and 2b is the salt.

  • subprocess.call(command) will simply run the command to generate users

Solution 5

I have a shorter awk version (@Serg =)):

First install whois, we need the command mkpasswd

sudo apt-get install whois

Than you can use this oneliner:

awk -F',' '{print "Create user: "$1; system("sudo useradd -p $(mkpasswd "$2") "$1)}' users

or without any output:

awk -F',' '{system("sudo useradd -p $(mkpasswd "$2") "$1)}' users

Content of users:

foo,foopasswd
bar,password
foobar,foobar

The user name is in the first column, the unencrypted password in the 2nd column.


In fairness, I mention a problem here. Passwords can not include a comma.

Share:
8,367

Related videos on Youtube

Driekus
Author by

Driekus

Updated on September 18, 2022

Comments

  • Driekus
    Driekus over 1 year

    Is it possible to import users by using CSV file? or something like a LDAP connection to import all users?

    • Daniel Alder
      Daniel Alder almost 9 years
      Both is possible. For importing you'll need a script for running adduser or useradd for each user. For LDAP you need to configure PAM. I recommend to focus your question to one of these two solutions because they are so completely different
    • fedorqui
      fedorqui almost 9 years
      I cannot understand how a question like this, showing no effort at all, not following any of the site guidelines, can get upvotes at all, or even more than any of the documented answers.
    • A.B.
      A.B. almost 9 years
      Why the downvotes?
    • Sergiy Kolodyazhnyy
      Sergiy Kolodyazhnyy almost 9 years
      @fedorqui can you elaborate please , where exactly the question fails ? I agree that OP didn't show any effort, but I don't see how this question is different from others "How do I do X and X ?" type of questions ?
    • A.B.
      A.B. almost 9 years
      @fedorqui "Is it possible to import users by using CSV file?" it's a good and legitime question.
    • fedorqui
      fedorqui almost 9 years
      @Serg then others are also bad :D I was astonished by the upvotes. Why? See the description when you hover on the upvote: "This question shows research effort; it is useful and clear". The original question does not show any effort at all (format, research, etc). More info in How do I ask a good question.
    • fedorqui
      fedorqui almost 9 years
      @A.B. see comment above
  • fedorqui
    fedorqui almost 9 years
    for users in $(cat file) is not the best way to loop in a file. Instead, just use while IFS="," read -r user passwd ; do ... ; done < file. $user and $passwd will contain the 1st and 2nd columns, etc.
  • Rinzwind
    Rinzwind almost 9 years
    Like so @fedorqui ? (feel free to edit it and help me beat Serg ;) )
  • fedorqui
    fedorqui almost 9 years
    Yep, way better. I would also use $() instead of backticks, since they are preferred. Also, it is always good practice to quote variables when echoing
  • A.B.
    A.B. almost 9 years
    What if the password should contain a comma? =)
  • A.B.
    A.B. almost 9 years
    What if the password should contain a comma? =)
  • A.B.
    A.B. almost 9 years
    What if the password should contain a colon? =)
  • A.B.
    A.B. almost 9 years
    You have already my upvote, once again =)
  • Sergiy Kolodyazhnyy
    Sergiy Kolodyazhnyy almost 9 years
    Good job, hence +1, works even with comas in password
  • heemayl
    heemayl almost 9 years
    @Serg I have already given +1 to your one (and others)..
  • A.B.
    A.B. almost 9 years
    Common, accept a parameter for the CSV file :) anyway +1
  • Rinzwind
    Rinzwind almost 9 years
    Then you find another delimiter ;)