8.17. Серийное добавление новых пользователей
Проблема
Требуется добавить сразу несколько учетных записей, вместо того чтобы вводить их по одной.
Решение
Воспользуйтесь сценарием mass_useradd. Это сценарий командного процессора, поэтому он должен работать практически везде. Вам также понадобится сценарий mass_passwd (листинг 8.2). Сохраните эти два сценария в одном каталоге. Также следует установить утилиту pwgen, генерирующую пароли.
Создайте список имён и паролей в формате:
имя_пользователя: имя фамилия
Также можно добавить дополнительные данные GECOS:
dawns:Dawn Marie Schroder,,123-4567,trainers
Затем запустите сценарий mass_useradd (листинг 8.1). Сценарий создаёт записи в /etc/passwd, /etc/group и /etc/shadow, домашние каталоги, персональные группы и пароли, которые становятся недействительными после первого использования.
Следующая команда приказывает mass_useradd использовать список новых пользователей из файла newusers с заменой/созданием выходного файла newlogins.txt:
sh mass_useradd < newusers > newlogins.txt
Присоединение новых имён и паролей к файлу newlogins.txt:
sh mass_useradd < newusers >> newlogins.txt
Помимо выходного файла, который представляет собой обычный список, mass_passwd создаёт для каждого пользователя отдельный файл с инструкциями. Эти файлы, а также файл журнала, хранятся в домашнем каталоге пользователя, запустившего сценарий (обычно root):
/root/mass_passwds/
dawns.passwd.txt
nikitah.passwd.txt
mass_passwd.log
rubst.passwd.txt
Комментарий
В сценариях используются стандартные средства Shadow Suite, поэтому они легко настраиваются посредством регулировки параметров утилит, задействованных в их работе.
Пример выходных данных:
dawns shabaefi 1002
nikitah gohbinga 1003
rubst ahtoohaa 1004
В файл /etc/passwd добавляются записи вида:
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,,234-5678,test:/home/rubst:/bin/bash
Листинг 8.1. Программа mass_useradd
#!/bin/sh
#
# Использование:
# sh mass_useradd < inputfile > new-passwords.txt
#
PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:$PATH
# Чтение строки входных данных.
# Формат входного файла:
# имя_пользователя : имя фамилия
# Чтобы в качестве разделителя использовалась запятая, замените
# IFS=":$IFS" на IFS=",$IFS"
while IFS=":$IFS" read username realname; do
# Сначала удаляем пустые строки и комментарии
case "$username" in
''|\#*) continue ;;
esac
# Чтение /etc/passwd и /etc/group и вычисление следующих свободных значений UID и GID.
# Программа начинает с id=1000, измените для своей системы.
id=$( { getent passwd; getent group; } | cut -f3 -d: | sort -un | awk 'BEGIN { id=1000 } $1 == id { id++ } $1 > id { print id; exit }' )
# Добавление новых пользователей в /etc/group и /etc/passwd.
groupadd -g $id $username
useradd -m -c "$realname" -g $username -u $id $username
# Создание домашнего каталога с разрешениями 700.
chmod 700 /home/$username
# Назначение пароля с помощью сценария mass_passwd.
$(dirname $0)/mass_passwd -M $username
done
Листинг 8.2. Программа mass_passwd
#!/bin/sh
# Каталог для сохранения файлов "username.passwd.txt"
# Если каталог не существует, он будет создан.
text_file_dir=$HOME/mass_passwds
log_file=mass_passwd.log
# Минимальный идентификатор для "обычных" пользователей
min_uid=1000
# Длина генерируемых паролей
pass_len=8
# Срок действия паролей (в днях)
pass_expire=90
# Получение имени программы (скорее всего, "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
}
# Вывод в verbose режиме
vecho() {
test -n "$verbose" && echo "$@"
}
# Генерация случайного пароля.
randompass() {
pwgen $pass_len 1 2>/dev/null || \
tr -d '[\000-\057][\072-\100][\133-\140][\173-\377]' < /dev/urandom | \
dd bs=$pass_len count=1 2>/dev/null
}
# Получение списка пользователей в зависимости от режима
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
while [ -n "$1" ]; do
g_ent=$(getent group "$1" 2>/dev/null)
if [ -z "$g_ent" ]; then
echo >&2 "warning: $1: group not found"
continue
fi
members=${g_ent##*:}
gid=${g_ent%%:*}
echo "$members" | tr '.' ' '
getent passwd | awk -F: '{if ($4 == '$gid') { print $1 }}'
shift
done
}
# Основной код
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 ;;
-M) mass_out=1; shift ;; # для вызова из mass_useradd
-h | -? | --help) usage ;;
--) eol=1; shift ;;
-*) short_usage ;;
*) eol=1 ;;
esac
done
# Настройка безопасного окружения и каталога для текстовых файлов
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 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.
"
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
См. также
bash(1), pwgen(1); домашняя страница программы pwgen (http://sourceforge.net/projects/pwgen/).