0Pricing
Linux Command Line & Bash Scripting Mastery · Урок

Автоматизация создания пользователей и групп

Массово создавайте, изменяйте и проверяйте учётные записи с помощью useradd, chage и управления фрагментами sudoers

«Автоматизация создания пользователей и групп» — бесплатный урок Linux Command Line & Bash Scripting Mastery на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Linux Command Line & Bash Scripting Mastery, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Linux Command Line & Bash Scripting Mastery содержит 4 уроков всего.

Зачем автоматизировать подготовку учетных записей пользователей?

Управление пользователями по одному с помощью useradd вполне подходит для нескольких учетных записей, но в корпоративных средах одновременно обычно подключаются десятки или сотни пользователей. Ручные команды приводят к ошибкам, несогласованности и невозможности провести аудит.

Сценарии Bash позволяют Вам:

  • каждый раз создавать пользователей со стандартными настройками (оболочка, домашний каталог, политика паролей);
  • читать CSV или текстовый файл с данными новых сотрудников и создавать учетные записи за один запуск;
  • вести журнал каждого действия, чтобы иметь аудиторский след для целей соответствия требованиям;
  • интегрироваться с конвейерами управления конфигурацией (Ansible, Chef, Jenkins).

В этом уроке Вы с нуля создадите готовый к эксплуатации сценарий подготовки учетных записей пользователей, рассмотрев useradd, chage, usermod, управление группами, фрагменты конфигурации sudoers и аудит после выполнения.

Чтение списка пользователей для массового создания

Канонический формат входных данных для массового создания учетных записей — текстовый файл с разделителями, по одной записи в строке. Типичный CSV может выглядеть так:

username,full_name,group,shell
alice,Alice Smith,developers,/bin/bash
bob,Bob Jones,ops,/bin/zsh

Используйте IFS и read внутри цикла while, чтобы безопасно разобрать файл. Пропуск строки заголовка с помощью tail -n +2 упрощает логику.

Основные защитные меры:

  • удаляйте начальные и конечные пробелы в каждом поле;
  • пропускайте пустые строки и строки комментариев, начинающиеся с #;
  • проверяйте, что обязательные поля не пусты, прежде чем вызывать системные команды.
#!/usr/bin/env bash
# parse_users.sh — safely read a CSV of users
set -euo pipefail

USER_FILE="${1:-users.csv}"

[[ -f "$USER_FILE" ]] || { echo "ERROR: $USER_FILE not found"; exit 1; }

tail -n +2 "$USER_FILE" | while IFS=',' read -r username full_name group shell; do
  # trim whitespace
  username="${username// /}"
  [[ -z "$username" || "$username" == \#* ]] && continue

  echo "Parsed -> user=$username group=$group shell=$shell"
done

Создание пользователей с помощью useradd

useradd — низкоуровневая утилита, записывающая данные в /etc/passwd, /etc/shadow и /etc/group. Наиболее важные параметры для сценариев:

  • -m — создать домашний каталог;
  • -s — установить оболочку входа;
  • -c — поле комментария GECOS (полное имя);
  • -G — дополнительные группы (через запятую);
  • -e — дата истечения срока действия учетной записи (YYYY-MM-DD).

Всегда проверяйте существование пользователя с помощью id перед вызовом useradd: при запуске для уже существующего пользователя команда возвращает код завершения 9 и выводит ошибку, которая может засорить журналы.

Примечание: useradd требует прав суперпользователя. В начале сценария добавьте проверку привилегий.

#!/usr/bin/env bash
# create_user.sh — idempotent single-user creation
set -euo pipefail

[[ $EUID -ne 0 ]] && { echo "Must run as root"; exit 1; }

USERNAME="$1"
FULL_NAME="${2:-}"
GROUP="${3:-staff}"
SHELL="${4:-/bin/bash}"

if id "$USERNAME" &>/dev/null; then
  echo "[SKIP] User $USERNAME already exists"
else
  useradd \
    --create-home \
    --shell "$SHELL" \
    --comment "$FULL_NAME" \
    --groups "$GROUP" \
    "$USERNAME"
  echo "[OK] Created $USERNAME"
fi

Безопасная установка начальных паролей

Никогда не прописывайте пароли непосредственно в сценариях. Для массового создания учетных записей существуют два безопасных подхода:

  • Сгенерировать случайный начальный пароль с помощью openssl rand или /dev/urandom, вывести его один раз и заставить пользователя сменить его при первом входе;
  • Установить предварительно хешированный пароль с помощью usermod -p, используя хеш SHA-512, чтобы пароль в открытом виде никогда не появлялся в списке процессов.

chpasswd — рекомендуемый инструмент для установки паролей в сценариях: он читает пары username:password из стандартного ввода, поэтому пароль не появляется в аргументах командной строки (видимых через ps).

После установки пароля используйте chage -d 0, чтобы принудительно потребовать немедленную смену пароля при следующем входе.

#!/usr/bin/env bash
# set_temp_password.sh
set -euo pipefail

[[ $EUID -ne 0 ]] && { echo "Must run as root"; exit 1; }

USERNAME="$1"

# Generate a 16-char random password (alphanumeric only)
TMP_PASS=$(tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 16)

# Set password via chpasswd (password never in argv)
echo "${USERNAME}:${TMP_PASS}" | chpasswd

# Force password change on next login
chage -d 0 "$USERNAME"

echo "[OK] Temporary password for $USERNAME: $TMP_PASS"
echo "[OK] User must change password on first login"

Управление сроком действия паролей с помощью chage

chage (изменение срока действия) управляет политикой старения паролей, хранящейся в /etc/shadow. Корпоративные политики безопасности обычно требуют:

  • максимального срока действия пароля (например, 90 дней);
  • минимального числа дней до следующей смены пароля;
  • периода предупреждения до истечения срока действия;
  • блокировки неактивной учетной записи после последнего использования пароля.

Основные параметры chage:

  • -M <days> — максимальный срок действия пароля;
  • -m <days> — минимальный срок действия пароля;
  • -W <days> — число дней для предупреждения до истечения срока;
  • -I <days> — число дней бездействия до блокировки учетной записи;
  • -E <date> — абсолютная дата истечения срока действия учетной записи;
  • -l — показать текущие настройки пользователя.
#!/usr/bin/env bash
# apply_password_policy.sh — enforce org-wide ageing policy
set -euo pipefail

[[ $EUID -ne 0 ]] && { echo "Must run as root"; exit 1; }

# Policy constants
MAX_AGE=90
MIN_AGE=1
WARN_DAYS=14
INACTIVE_DAYS=30

apply_policy() {
  local user="$1"
  chage \
    -M "$MAX_AGE" \
    -m "$MIN_AGE" \
    -W "$WARN_DAYS" \
    -I "$INACTIVE_DAYS" \
    "$user"
  echo "[OK] Policy applied to $user"
}

# Apply to all non-system users (UID >= 1000)
awk -F: '$3 >= 1000 && $3 < 65534 { print $1 }' /etc/passwd | while read -r user; do
  apply_policy "$user"
done

Массовое управление группами

Группы — основной механизм управления доступом к ресурсам. Сценарий подготовки учетных записей должен убедиться, что необходимые группы существуют, прежде чем добавлять в них пользователей: useradd -G nonexistent завершится ошибкой.

Используйте groupadd идемпотентно, проверяя код завершения: он возвращает 9, если группа уже существует. Идиома getent group <name> — переносимая и понятная альтернатива поиску с помощью grep в /etc/group.

gpasswd -a добавляет пользователя в группу, не заменяя уже существующие членства (в отличие от usermod -G, который заменяет список дополнительных групп).

#!/usr/bin/env bash
# ensure_groups.sh — create groups if missing, then add users
set -euo pipefail

[[ $EUID -ne 0 ]] && { echo "Must run as root"; exit 1; }

REQUIRED_GROUPS=(developers ops security auditors)

for grp in "${REQUIRED_GROUPS[@]}"; do
  if getent group "$grp" &>/dev/null; then
    echo "[SKIP] Group $grp already exists"
  else
    groupadd "$grp"
    echo "[OK] Created group $grp"
  fi
done

# Safely add a user to a group (append, don't replace)
add_to_group() {
  local user="$1" group="$2"
  gpasswd -a "$user" "$group" 2>/dev/null && echo "[OK] $user -> $group"
}

Полный сценарий массового создания учетных записей

Соберем все вместе: один сценарий читает CSV, создает пользователей и группы, устанавливает политику паролей, записывает в журнал каждое действие и корректно обрабатывает ошибки, не останавливая весь пакет.

Важные проектные решения в приведенном ниже сценарии:

  • LOG_FILE с временными метками сохраняет все операции для аудита;
  • ошибки отдельных пользователей записываются в журнал, но не прерывают цикл (|| log_error);
  • сценарий идемпотентен — его безопасно повторно запускать после частичных сбоев;
  • весь вывод направляется одновременно в терминал и файл журнала с помощью tee.
#!/usr/bin/env bash
# bulk_provision.sh — production user provisioning
set -uo pipefail

[[ $EUID -ne 0 ]] && { echo "Must run as root"; exit 1; }

USER_FILE="${1:-users.csv}"
LOG_FILE="/var/log/user_provision_$(date +%F).log"

log()  { echo "[$(date '+%F %T')] $*" | tee -a "$LOG_FILE"; }
err()  { log "ERROR: $*"; }

log "=== Provisioning started from $USER_FILE ==="

tail -n +2 "$USER_FILE" | while IFS=',' read -r username fullname group shell; do
  username="${username// /}"
  [[ -z "$username" || "$username" == \#* ]] && continue
  group="${group:-staff}"
  shell="${shell:-/bin/bash}"

  # Ensure group exists
  getent group "$group" &>/dev/null || groupadd "$group"

  # Create user idempotently
  if id "$username" &>/dev/null; then
    log "[SKIP] $username exists"
  else
    useradd -m -s "$shell" -c "$fullname" -G "$group" "$username" || { err "useradd failed for $username"; continue; }
    TMP="$(tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 14)"
    echo "${username}:${TMP}" | chpasswd
    chage -M 90 -m 1 -W 14 -I 30 -d 0 "$username"
    log "[OK] $username created (group=$group) tmp_pass=$TMP"
  fi
done

log "=== Provisioning complete ==="

Управление фрагментами конфигурации sudoers

Прямое редактирование /etc/sudoers опасно: синтаксическая ошибка лишит всех доступа к sudo. Безопасный подход — использовать файлы-фрагменты в /etc/sudoers.d/, проверяя каждый из них с помощью visudo -c -f перед установкой.

Рекомендации для фрагментов sudoers:

  • называйте файлы в соответствии с командой или ролью, права которой они предоставляют (например, 10-developers, 20-ops);
  • используйте правила для групп (%developers ALL=(ALL) NOPASSWD: /usr/bin/systemctl), а не строки для отдельных пользователей;
  • всегда устанавливайте права 0440 и владельца root:root;
  • проверяйте конфигурацию с помощью visudo -c — при любой синтаксической ошибке команда завершается с ненулевым кодом.
#!/usr/bin/env bash
# write_sudoers_fragment.sh
set -euo pipefail

[[ $EUID -ne 0 ]] && { echo "Must run as root"; exit 1; }

FRAGMENT_NAME="${1:-10-developers}"
SUDOERS_DIR="/etc/sudoers.d"
TMP_FILE="$(mktemp)"

# Write the fragment to a temp file first
cat > "$TMP_FILE" << 'EOF'
# Developers: restart services and view journals without full root
%developers ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart *, /usr/bin/journalctl
%ops        ALL=(ALL) NOPASSWD: ALL
EOF

# Validate BEFORE installing
if visudo -c -f "$TMP_FILE"; then
  install -m 0440 -o root -g root "$TMP_FILE" "${SUDOERS_DIR}/${FRAGMENT_NAME}"
  echo "[OK] Installed ${SUDOERS_DIR}/${FRAGMENT_NAME}"
else
  echo "[ERROR] sudoers syntax check failed — fragment NOT installed"
  rm -f "$TMP_FILE"
  exit 1
fi
rm -f "$TMP_FILE"

Аудит существующих учетных записей

После создания учетных записей и регулярно в дальнейшем следует проверять базу пользователей на наличие аномалий:

  • Учетные записи с UID 0 — любая учетная запись с UID 0, кроме root, является критическим событием безопасности;
  • Учетные записи без пароля — записи с пустым полем пароля или полем, содержащим !, в /etc/shadow;
  • Истекшие, но все еще активные учетные записи — вывод chage -l можно обработать массово;
  • Пользователи с оболочками, но без домашнего каталога — такая неправильная настройка нарушает вход в систему.

Создать структурированный отчет и отправить его по электронной почте команде безопасности несложно с помощью mail или добавив отчет в контролируемый путь журнала.

#!/usr/bin/env bash
# audit_users.sh — produce a security-relevant user report
set -uo pipefail

REPORT="/var/log/user_audit_$(date +%F).txt"

echo "=== User Audit Report $(date) ===" > "$REPORT"

echo "" >> "$REPORT"
echo "--- Accounts with UID 0 (should be root only) ---" >> "$REPORT"
awk -F: '$3 == 0 { print $1 }' /etc/passwd >> "$REPORT"

echo "" >> "$REPORT"
echo "--- Accounts with empty password field ---" >> "$REPORT"
awk -F: '($2 == "" || $2 == "!") && $3 >= 1000 { print $1 }' /etc/shadow 2>/dev/null >> "$REPORT" || echo "  (requires root)" >> "$REPORT"

echo "" >> "$REPORT"
echo "--- Normal users (UID 1000-60000) ---" >> "$REPORT"
awk -F: '$3 >= 1000 && $3 < 60000 { printf "%-20s uid=%-6s shell=%s\n", $1, $3, $7 }' /etc/passwd >> "$REPORT"

cat "$REPORT"
echo "Report saved to $REPORT"

Блокировка, разблокировка и удаление учетных записей

Вывод пользователя из системы не менее важен, чем его подключение. Когда пользователь покидает организацию, выполните следующие действия:

  1. Немедленно заблокируйте учетную запись (usermod -L) — команда добавляет ! перед хешем пароля в shadow, предотвращая вход без удаления данных;
  2. Отзовите права sudo — удалите фрагмент sudoers пользователя, если он существует;
  3. Передайте владение его файлами руководителю или архивной учетной записи;
  4. Архивируйте домашний каталог в tar-архив перед удалением;
  5. Удалите учетную запись с помощью userdel -r — команда удаляет домашний каталог и почтовый буфер.

usermod -U разблокирует учетную запись (удаляет префикс !); это удобно для временной приостановки.

#!/usr/bin/env bash
# offboard_user.sh — lock, archive, then optionally delete
set -euo pipefail

[[ $EUID -ne 0 ]] && { echo "Must run as root"; exit 1; }

USERNAME="$1"
ARCHIVE_DIR="/srv/archived-homes"
mkdir -p "$ARCHIVE_DIR"

# 1. Lock account
usermod -L "$USERNAME"
echo "[OK] Account $USERNAME locked"

# 2. Remove sudoers fragment if present
SUDOERS_FILE="/etc/sudoers.d/${USERNAME}"
[[ -f "$SUDOERS_FILE" ]] && rm -f "$SUDOERS_FILE" && echo "[OK] Removed sudoers fragment"

# 3. Archive home directory
HOME_DIR="$(getent passwd "$USERNAME" | cut -d: -f6)"
if [[ -d "$HOME_DIR" ]]; then
  tar -czf "${ARCHIVE_DIR}/${USERNAME}_$(date +%F).tar.gz" -C "$(dirname "$HOME_DIR")" "$(basename "$HOME_DIR")"
  echo "[OK] Home archived to ${ARCHIVE_DIR}/${USERNAME}_$(date +%F).tar.gz"
fi

echo "[NOTICE] Review archive, then run: userdel -r $USERNAME"

Тестирование сценария в режиме пробного запуска

Сценарии подготовки учетных записей для эксплуатации должны быть пригодны для тестирования без побочных эффектов. Реализуйте режим пробного запуска с помощью флага DRY_RUN, заменяющего все изменяющие команды заглушками echo.

Шаблон прост: определите вспомогательную функцию run(), которая в зависимости от флага либо выполняет команду, либо выводит ее. Такой подход означает, что:

  • при тестировании выполняется каждый путь кода;
  • вывод точно показывает, что произошло бы при реальном запуске;
  • конвейеры CI могут проверять логику без доступа суперпользователя.

Дополните пробный запуск специальным префиксом тестовых пользователей (например, test_), чтобы их было легко удалить после интеграционных тестов.

#!/usr/bin/env bash
# provision_with_dryrun.sh
set -euo pipefail

DRY_RUN="${DRY_RUN:-false}"

# Wrapper: execute or echo
run() {
  if [[ "$DRY_RUN" == "true" ]]; then
    echo "[DRY-RUN] $*"
  else
    "$@"
  fi
}

create_user() {
  local user="$1" group="$2"
  if id "$user" &>/dev/null; then
    echo "[SKIP] $user exists"
    return
  fi
  run useradd -m -s /bin/bash -G "$group" "$user"
  run chage -M 90 -m 1 -W 14 -d 0 "$user"
  echo "[OK] $user provisioned (dry=$DRY_RUN)"
}

# Test run
DRY_RUN=true create_user testuser developers
echo "---"
create_user realuser developers 2>/dev/null || true

Какую команду следует использовать, чтобы добавить пользователя в дополнительную группу, не удаляя его членство в существующих группах?

В сценарии массового создания учетных записей Вам нужно добавить существующего пользователя в группу auditors. Пользователь уже входит в группы developers и staff. Какая команда сохранит все существующие членства и добавит новое?

Повторение урока: автоматизация создания пользователей и групп

В этом уроке Вы создали полный готовый к эксплуатации набор инструментов для подготовки учетных записей пользователей. Основные выводы:

  • Безопасно разбирайте входные данные — используйте циклы IFS/read, пропускайте пустые строки и строки комментариев, проверяйте поля перед любым системным вызовом;
  • Основы useradd — всегда используйте -m (домашний каталог), -s (оболочка), -c (комментарий) и -G (группы); сначала проверяйте существование с помощью id для обеспечения идемпотентности;
  • Пароли — задавайте через стандартный ввод chpasswd, чтобы пароль в открытом виде не попадал в аргументы процесса; принудительно требуйте смену при первом входе с помощью chage -d 0;
  • chage для политики — унифицируйте максимальный срок действия (-M), количество дней предупреждения (-W) и блокировку после бездействия (-I) для всех несистемных учетных записей;
  • Членство в группах — используйте gpasswd -a или usermod -aG (с флагом -a), чтобы добавлять членства, а не заменять их;
  • Фрагменты sudoers — записывайте их в /etc/sudoers.d/, проверяйте с помощью visudo -c -f перед установкой и задавайте права 0440 root:root;
  • Вывод пользователя из системы — заблокируйте учетную запись (usermod -L), архивируйте домашний каталог, затем удалите учетную запись; никогда не пропускайте архивирование;
  • Режим пробного запуска — оборачивайте изменяющие команды во вспомогательную функцию run(), чтобы конвейеры могли проверять логику без побочных эффектов, требующих прав суперпользователя.

Объединение этих шаблонов дает Вам воспроизводимый, проверяемый и безопасный уровень автоматизации управления удостоверениями Linux в любом масштабе.

Часто задаваемые вопросы

Урок «Автоматизация создания пользователей и групп» бесплатный?

Да — полный текст урока «Автоматизация создания пользователей и групп» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Linux Command Line & Bash Scripting Mastery, подпишись на CoddyKit PRO. Курс Linux Command Line & Bash Scripting Mastery содержит 4 уроков всего.

Чему я научусь в уроке «Автоматизация создания пользователей и групп»?

Массово создавайте, изменяйте и проверяйте учётные записи с помощью useradd, chage и управления фрагментами sudoers Ты практикуешь Linux Command Line & Bash Scripting Mastery с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Linux Command Line & Bash Scripting Mastery?

Предыдущий опыт не требуется. Linux Command Line & Bash Scripting Mastery на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.

Сколько времени занимает урок «Автоматизация создания пользователей и групп»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Linux Command Line & Bash Scripting Mastery?

Да. Каждый урок Linux Command Line & Bash Scripting Mastery включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Автоматизация создания пользователей и групп
  2. Управление службами systemd и создание файлов модулей
  3. Автоматизация дисков, файловых систем и монтирования
  4. Создание скриптов проверки состояния системы и оповещений
← Назад к Linux Command Line & Bash Scripting Mastery