Previous Section  < Day Day Up >  Next Section

Recipe 8.17. Adding New Users in Batches

8.17.1 Problem

You want to be able to add several users at once, rather than having to enter each one individually.

8.17.2 Solution

Use the mass_useradd script. It's a shell script, so it should run just about anywhere. You'll also need mass_passwd. Store the two scripts in the same directory. You should also install the pwgen utility, for generating passwords. You'll need a colon-delimited text list of logins and usernames in this format:



login
:


firstname


lastname

You may also include additional GECOS data, like this:

dawns:Dawn Marie Schroder,,123-4567,trainers

Then invoke the mass_useradd script. It creates entries in /etc/passwd, /etc/group, and /etc/shadow; home directories; personal login groups; and passwords that expire at first use.

This tells mass_useradd to use the list of new users in newusers and to overwrite or create the output file newlogins.txt:

# sh mass_useradd < newusers > newlogins.txt

This appends the new logins and passwords to newlogins.txt:

# sh mass_useradd < newusers >> newlogins.txt

In addition to the output file, which is a simple list, mass_passwd creates a separate file for each user, containing the new login name and instructions. This makes it easy to print them individually for distribution. These files, plus a log file, are stored in the home directory of the user who runs the scripts (usually root):

# ls /root/mass_passwds

dawns.passwd.txt  nikitah.passwd.txt  mass_passwd.log  rubst.passwd.txt

8.17.3 Discussion

Because the scripts use standard Shadow Suite utilities, they are easy to customize by adjusting the options for the various utilities used in the scripts.

The output file looks like this:

dawns    shabaefi    1002

nikitah  gohbinga    1003

rubst    ahtoohaa    1004

/etc/passwd looks like this:

dawns:x:1002:1002:Dawn Marie Schroder,,123-4567,trainers:/home/dawns:/bin/bash

nikitah:x:1003:1003:Nikita Horse,,123-4567,equine:/home/nikitah:/bin/bash

rubst:x:1004:1004:Rubs The Cat,101,,234-5678,,test:/home/rubst:/bin/bash

The individual files generated for each user look like this:

---------------------------------------------------------

           Login name: rubst

           Password:   eejahgue

      Please log in and change your password; the system should prompt you to do this 

when you log in.  You can change your password at any time with the 'passwd' command.

          Choose a strong password - everyday words, birthdays, names of people or animals,

 all these are too easy to guess.

     Also, DO NOT give your password to anyone, ever.  The IT

     staff will never ask you for your password, and neither

     should anyone else.  You will be held responsible for all

     activity done via your account.

------------------------------------------------------------

8.17.4 Program: mass_useradd

#!/bin/sh

   

## Mass Useradd For Linux

## This script extracts new user data from a delimited

## text file, and automatically generates new user accounts. 

## It generates a random password for each login, and exports 

## the new logins and passwords to a text file.

## Passwords automatically expire at first login. The

## input file format is "username: full name" (no quotes) for 

## each line.

##

## Mass Useradd creates a "User Personal Group."

## The UID and the GID are the same. User's home directories

## are created with restrictive permissions, chmod 700.

## Mass Useradd uses standard Shadow Suite utilities.

## Values and behaviors are easily modifiable, according

## to the individual utility being called.  It calls

## a companion script, mass_passwd, to set each user password.  

## You should have received mass_passwd from the same source

## as mass_useradd.

##

## This script was created by Aaron Malone, and modified by

## Meredydd Luff, Peter Samuelson, and Kathryn Hogg.

## Many thanks!

## Carla Schroder wrote the documentation and pestered

## the aforementioned persons to write the script.

## Copyright (C) 2003  Carla Schroder

## carla at bratgrrl dot com

## This program is free software; you can redistribute

## it and/or modify it under the terms of the GNU General

## Public License as published by the Free Software

## Foundation; either version 2 of the License, or (at your

## option) any later version.

##

## This program is distributed in the hope that it will

## be useful, but WITHOUT ANY WARRANTY; without even the

## implied warranty of MERCHANTABILITY or FITNESS FOR A

## PARTICULAR PURPOSE.  See the

## GNU General Public License for more details.

## http://www.fsf.org/licenses/gpl.html

##

##   Usage:

##    #  sh mass_useradd < inputfile >> new-passwords.txt

##

   

PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:$PATH

   

# Read a line of input.

# the format of the input file must be like this:

# userlogin : FirstName LastName

# to use a comma-delimited file, change IFS=":$IFS" to

# IFS=",$IFS"

   

while IFS=":$IFS" read username realname; do

   

# First, weed out blank lines and #comments

        case "$username" in

                '' | \#*) continue ;;

        esac

   

# this part reads /etc/passwd and /etc/group, and calculates

# the next available UID and GID.

# it starts at {id=1000}, change this to suit

        id=$({ getent passwd; getent group; } | cut -f3 -d: | sort -un |

             awk 'BEGIN { id=1000 }

                  $1 =  = id { id++ }

                  $1 > id { print id; exit }')

# Now users are added to /etc/group, /etc/passwd,

# and home directories with chmod 700 are created

# Any of the groupadd, useradd, and chmod options

# can be changed to suit

        groupadd -g $id $username

        useradd -m -c "$realname" -g $username -u $id $username

        chmod 700 /home/$username

   

# Set the password.  This calls another script from

# this toolkit, mass_passwd, which can be used independently.

# mass_passwd outputs the username, password and userid.

        $(dirname $0)/mass_passwd -M $username

   

done

8.17.5 Program: mass_passwd

#!/bin/sh

   

## Mass Password Change for Linux

## This requires the Shadow Suite utilities.

## Usage:

##   mass_passwd username username ...

##   mass_passwd -g groupname groupname ...

##   mass_passwd -a

##

## This program is free software; you can redistribute

## it and/or modify it under the terms of the GNU General

## Public License as published by the Free Software

## Foundation; either version 2 of the License, or (at your

## option) any later version.

##

## This program is distributed in the hope that it will

## be useful, but WITHOUT ANY WARRANTY; without even the

## implied warranty of MERCHANTABILITY or FITNESS FOR A

## PARTICULAR PURPOSE.  See the

## GNU General Public License for more details.

## http://www.fsf.org/licenses/gpl.html

   

#############################################################

   

## This is where the "username.passwd.txt" files will

## be dumped. It will be created if it doesn't already exist

text_file_dir=$HOME/mass_passwds

log_file=mass_passwd.log

   

## Minimum userid considered a regular (human) user

min_uid=1000

   

## Length of generated passwords

pass_len=8

   

## Length of time, in days, before a password expires

pass_expire=90

   

##############################################################

## Few user-serviceable parts inside.

## You may wish to edit the text between the two ---------

## lines, below.

   

# Get the name of this program (probably "mass_passwd")

prog=${0##*/}

   

usage ( ) {

        echo "usage: $prog [-v] [-n] username ..."

        echo "       $prog [-v] [-n] [-g] groupname ..."

        echo "       $prog [-v] [-n] [-a]"

        echo "  -g   change passwords of everyone in a group"

        echo "  -a   change everyone's password"

        echo "  -v   verbose"

        echo "  -n   don't do it, just simulate (implies -v)"

        exit 0

}

short_usage ( ) {

        echo >&2 "usage: $prog [-v] [-g] [-a] name..."

        echo >&2 "       $prog -h    for help"

        exit 1

}

   

# echo something, but only if in verbose mode

vecho ( ) {

        test -n "$verbose" && echo "$@"

}

   

# Generate a random password.

#

# If pwgen is available, use that - that's what it's for, and it works well.

#

# If not, read /dev/urandom and filter out all non-

#alphanumeric characters until we have enough for a password.

# The numbers in the "tr -d" are ASCII values, in octal

# notation, of ranges of character values to delete.

#

# Using /dev/urandom like this is very inefficient, but

# who cares?

randompass ( ) {

        pwgen $pass_len 1 2>&- ||

        tr -d '[\000-\057][\072-\100][\133-\140][\173-\377]' < /dev/urandom |

          dd bs=$pass_len count=1 2>&-

}

   

# Interpret usernames / groupnames / "-a" mode, and return

# a list of usernames

get_users ( ) {

        if [ -n "$all_mode" ]; then

                getent passwd | awk -F: '{if ($3 >= '$min_uid') {print $1}}'

                return

        fi

        if [ -z "$group_mode" ]; then

                echo "$@"

                return

        fi

   

# ok, we're in group mode, must look up the users who

# belong to a group

        while [ -n "$1" ]; do

                g_ent=$(getent group "$1" 2>&-)

                if [ -z "$g_ent" ]; then

                        echo >&2 "warning: $1: group not found"

                        continue

                fi

                members=${g_ent##*:}

                gid=${g_ent%:*}

                gid=${gid##*:}

                echo "$members" | tr ',' ' '

                getent passwd | awk -F: '{if ($4 =  = '$gid') { print $1 } }'

                shift

        done

}

   

#############################################################

## main body

   

group_mode=; verbose=; all_mode=; simulate=; eol=;

while [ -z "$eol" ]; do

        case "$1" in

                -g) group_mode=1; shift ;;

                -v) verbose=1; shift ;;

                -a) all_mode=1; shift ;;

                -n) simulate=true; verbose=1; shift ;;

              # we're called from mass_useradd

                -M) mass_out=1; shift ;;   

                -h | -? | --help) usage ;;

                --) eol=1; shift ;;

                -*) short_usage ;;

                *) eol=1 ;;

        esac

done

   

# Set up a secure environment and the directory for

# printable text files

PATH=/usr/sbin:/usr/bin:$PATH

umask 077

mkdir -p $text_file_dir

cd $text_file_dir

   

processed=0

for u in $(get_users "$@"); do

        vecho -n "generating password for $u..."

        pass=$(randompass)

        echo "$u:$pass" | eval $simulate chpasswd

        vecho -n "."

        eval $simulate chage -M $pass_expire -d 2003-01-01 $u

        vecho -n "."

   

        rm -f $u.passwd.txt

        echo > $u.passwd.txt "\

-------------------------------------------------------------

                     Login name: $u

                     Password:   $pass

          Please log in and change your password; the system should prompt you to do this 

when you log in.  You can change your password at any time with the 'passwd' command.

          Choose a strong password - everyday words, birthdays, names of people or animals,

 all these are too easy to guess. Use combinations of letters and numbers. Write down your

 password in a safe place.

     Also, DO NOT give your password to anyone, ever.  The IT

     staff will never ask you for your password, and neither

     should anyone else.  You will be held responsible for all

     activity done via your account.

-------------------------------------------------------------"

        printf >> $log_file "$(date)   %-12s %s\\n" $u $pass

        vecho "$pass"

        if [ -n "$mass_out" ]; then

                uid=$(getent passwd $u | cut -f3 -d:)

                echo -e "$u\\t$pass\\t$uid"

        fi

        processed=$(expr $processed + 1)

done

   

if [ $processed -gt 0 ]; then

        test -z "$mass_out" &&

        echo >&2 "$processed password(s) reset - see $text_file_dir/$log_file"

else

        echo >&2 "no users specified - see '$prog -h' for help"

fi

8.17.6 See Also

    Previous Section  < Day Day Up >  Next Section