Is it possible to import users by using CSV file? or something like a LDAP connection to import all users?
6 Answers
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:::
-
-
-
@A.B. in that case, you need to use a different tool. I can't figure out how to have a colon in a password for
newuser
. Neither quoting, nor escaping seems to work :( Jun 8, 2015 at 18:38 -
Are you sure it works? Last time I tried it failed as soon as there was more than one line in the file - see bugs.launchpad.net/ubuntu/+source/shadow/+bug/1266675.– guntbertJun 8, 2015 at 19:21
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 withsudo 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).
-
2
for users in $(cat file)
is not the best way to loop in a file. Instead, just usewhile IFS="," read -r user passwd ; do ... ; done < file
.$user
and$passwd
will contain the 1st and 2nd columns, etc.– fedorquiJun 8, 2015 at 11:42 -
1Like so @fedorqui ? (feel free to edit it and help me beat Serg ;) )– RinzwindJun 8, 2015 at 11:53
-
Yep, way better. I would also use
$()
instead of backticks, since they are preferred. Also, it is always good practice to quote variables whenecho
ing– fedorquiJun 8, 2015 at 11:55 -
-
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
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 fileline[:i]
will take the slice of the line containg the usernameline.rstrip()[i+1:]
will contain the passwordcrypt
module generates encrypted password from input of the formcrypt.crypt(password, salt)
.encpt_passwd
will contain the encrypted password. Incrypt.crypt(password, '2b')
,password
is the saved plain password and2b
is the salt.subprocess.call(command)
will simply run the command to generate users
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.
My AWK version has a problem with ,
in the password. Here is my perl version:
#!/usr/bin/perl
use strict;
use warnings;
use Text::CSV;
my $file = $ARGV[0];
open my $fh, "<", $file or die "$file: $!";
my $csv = Text::CSV->new ({
binary => 1, # Allow special character. Always set this
auto_diag => 1, # Report irregularities immediately
sep_char => ','
});
while (my $row = $csv->getline ($fh)) {
print "User: ".$row->[0]."\n";
print "Password: ".$row->[1]."\n";
my $hashed = crypt($row->[1], "salt");
my $cmd = 'useradd -p '.$hashed.' '.$row->[0]."\n";
system($cmd);
}
close $fh;
Example:
CSV file users.csv
:
foo,"foopasswd"
bar,"password"
foobar,"""foo,bar"
Start the script
% sudo add_users users.csv
User: foo
Password: foopasswd
useradd -p sajllSNct/Wx2 foo
User: bar
Password: password
useradd -p sa3tHJ3/KuYvI bar
User: foobar
Password: "foo,bar
useradd -p saBWMpscG9WvA foobar
adduser
oruseradd
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