Contents

使用Shell中的密码自动创建用户帐户

1. 概述

有时,我们可能希望自动化用户创建过程,而无需与命令行交互。

在本教程中,我们将编写一个强大的 shell 脚本来自动化用户创建过程。我们将使用大多数 Linux 发行版附带的内置工具,在学习本教程的各个部分时构建我们的脚本。最后,我们将拥有一个健壮的 shell 脚本,我们可以手动或从另一个程序执行它。

2. 设置自动化脚本

我们将首先执行验证检查,例如检查用户是否已经存在,如果没有提供则分配默认密码。之后,我们将介绍实际用户创建和密码分配的一些变化。

2.1. 基本用法

我们将从命令行执行脚本并为其提供*-username-password*参数。如果出现验证错误,我们将看到包含说明的脚本使用消息。一旦脚本成功执行,我们将打印出用户名和密码。

让我们从创建脚本文件和编写usage函数开始:

#!/bin/sh
usage() {
  printf "create-user [-u|--username] <username>\n"
  printf " OPTIONS\n"
  printf "  -u --username\tusername of the new account (required)\n"
  printf "  -p --password\tpassword for the new account (optional)\n"
  printf "  -h --help\tprint this help\n"
  exit 1
}

**如果出现错误,我们将调用usage函数。**在我们的脚本中包含usage函数是 UNIX 和 Linux 的约定。

2.2. 进程命令选项

现在,我们需要处理命令选项。**我们将简单地使用while循环遍历参数并将值分配给变量。**之后,我们将进行一些完整性检查,如果没有提供密码作为参数,我们将分配一个默认密码。

让我们处理usage函数之后的参数:

while [ "$#" -gt 0 ]; do
  case "$1" in
    -u|--username) username="$2" shift ;;
    -p|--password) password="$2" shift ;;
        -h|--help) usage ;;
                *) usage ;;
  esac
  shift
done
[ -z "$username" ] && usage
[ -z "$password" ] && password=$(uuidgen | cut -d'-' -f1)

如果没有提供用户名,我们会打印出脚本的用法并使用退出代码 1 退出程序。在缺少密码的情况下,我们使用了uuidgen 命令来生成 UUID。在我们的例子中,我们只需要生成的 UUID 的前八个字符作为默认密码。

2.3. 检查用户是否存在

有时,我们可能有一个现有用户,其用户名与username参数相同。因此,我们需要事先检查用户数据库中的现有用户。我们可以使用userdbctl 命令。我们使用 userdbctl命令来查询 Linux 机器上的用户数据库

userdbctl命令为用户数据库中不存在的用户返回退出代码1。否则,它将返回 0

userdbctl user "$username" > /dev/null 2>&1
[ "$?" -eq 0 ] && echo "$username already exists" && exit 2

在上面的代码片段中,我们运行userdbctl命令并检查它返回的退出代码。** $?运算符包含我们在脚本中执行的最新命令的退出代码。在这种情况下,它将包含 0 或 1。

当然,我们可以离开这个安全检查,因为如果用户已经存在,useradd 命令将失败。但是,我们需要某种与我们的脚本配合得很好的简单反馈,因为useradd将为已经存在的用户名返回退出代码 9。

3. 创建用户并分配密码

现在预检查已完成,我们将继续创建实际用户。我们将使用useradd命令来创建用户。为了分配密码,我们将展示一些变体。

3.1. 带有*-p*选项的用户添加

useradd 命令使用 提供的用户名创建用户。我们还可以通过向useradd命令提供-p–password*选项来创建带有密码的用户*:

$ useradd -m newuser -p strongpassword
$ userdbctl user newuser
User name: newuser
Disposition: regular
Login OK: yes
Password OK: yes
UID: 1004
GID: 1004 (newuser)
Directory: /home/newuser
Storage: classic
Shell: /bin/bash
Passwords: none

-m标志为用户创建一个主目录。让我们在脚本中使用上述命令,并为其提供usernamepassword变量:

useradd -m "$username" -p "$password" > /dev/null 2>&1

3.2. useraddechopasswd命令

passwd 命令创建或更改现有用户帐户的密码。它将用户名作为参数,并提供密码修改的交互式提示。

让我们更改刚刚创建的新用户的密码

$ passwd newuser
Changing password for newuser.
Current password:
New password:
Retype new password:
passwd: password updated successfully

正如我们所见,passwd命令向我们展示了一个交互式提示。出于这个原因,我们将在passwd旁边使用echo命令来跳过交互式提示。

echo 命令是一个实用程序,它从标准输入中获取输入并将其打印到标准输出。我们还可以通过管道 echo与其他命令一起绕过提示和确认消息。因此,我们可以轻松地自动化涉及 shell 脚本或 Linux 终端中的提示的任务。

让我们看看它的实际效果:

$ echo -en "strongpassword\nnewpass\nnewpass\n" | passwd newuser
Changing password for newuser.
Current password:
New password:
Retype new password:
passwd: password updated successfully

这是发生的事情:

  • 我们通过*-e标志为echo命令启用了转义序列字符*支持
  • -n标志禁用打印尾随换行符
  • 我们回显当前密码,然后是新的和确认的密码
  • 每个密码都由“\n”字符分隔,因此它们被视为三个独立的标准输入
  • echo命令的输出通过 管道传送到passwd命令,我们用它来更改newuser的密码

现在我们对如何使用echo绕过提示有了一些了解,我们可以在脚本中实现这一点,而不是向useradd命令提供密码:

useradd -m "$username" > /dev/null 2>&1
echo -n "$password\n$password\n" | passwd "$username" /dev/null 2>&1

3.3. useraddechochpasswd命令

或者,我们可以使用chpasswd 命令更改新用户的密码。它执行与passwd相同的功能

让我们看看它的实际效果:

$ chpasswd
newuser:secretpasscode

与 passwd一样,chpasswd将向我们展示一个交互式多行提示。我们写下用户名,后跟冒号*(:)和新密码。之后,我们可以按 CTRL+D 来应用更改。像passwd一样,我们也可以使用echo*命令来自动化这个过程:

$ echo "newuser:code7654" | chpasswd

现在我们已经熟悉了chpasswd ,我们可以在脚本中使用它来代替passwd

useradd -m "$username"
echo "${username}:${password}" | chpasswd

4.收尾工作

我们的脚本几乎完成了。现在,我们需要编写反馈代码,让用户知道用户创建成功。

我们将检查脚本中执行的最新命令的退出代码,可能是useraddpasswdchpasswd,具体取决于使用的变体

if [ "$?" -eq 0 ]; then
  echo "Username: $username"
  echo "Password: $password"
else
  echo "Failed to set up user account"
  userdel -f "$username"
fi

让我们分解一下:

  • 我们检查先前执行的命令的退出代码,并期望它等于 0
  • 如果是0,通常表示成功,我们打印出用户名和密码
  • 在失败的情况下,我们打印出失败消息并使用userdel 命令从用户数据库中删除用户(如果它已创建)
  • -f标志强制 userdel删除用户——即使用户仍然登录——连同他们的主目录和邮件假脱机

我们现在准备测试脚本:

$ ./create-user -u "johndoe" -p "ys2b7444"
Username: johndoe
Password: ys2b7444
$ ./create-user -u "doejohn"
Username: doejohn
Password: 89c871de
$ ./create-user -u johndoe
johndoe already exists
$ ./create-user
create-user [-u|--username] <username>
OPTIONS
 -u --username  username of the new account (required)
 -p --password  password for the new account (optional)
 -h --help      print this help

我们的create-user脚本现已完成:

#!/bin/sh
usage() {
  printf "create-user [-u|--username] &lt;username&gt;\n"
  printf " OPTIONS\n"
  printf "  -u --username\tusername of the new account (required)\n"
  printf "  -p --password\tpassword for the new account (optional)\n"
  printf "  -h --help\tprint this help\n"
  exit 1
}
while [ "$#" -gt 0 ]; do
  case "$1" in
    -u|--username) username="$2" shift ;;
    -p|--password) password="$2" shift ;;
        -h|--help) usage ;;
                *) usage ;;
  esac
  shift
done
[ -z "$username" ] && usage
[ -z "$password" ] && password=$(uuidgen | cut -d'-' -f1)
useradd -m "$username" -p "$password" > /dev/null 2>&1
#------------#
# VARIATIONS #
#------------#
# useradd -m "$username"
# echo -n "$password\n$password\n" | passwd $username"
# echo "${username}:${password}" | chpasswd
if [ "$?" -eq 0 ]; then
  echo "Username: $username"
  echo "Password: $password"
else
  echo "Failed to set up user account"
  userdel -f "$username"
fi