Linux chpasswd命令

安全警告: chpasswd命令用于批量更改用户密码,请谨慎使用。密码在传输和存储过程中可能会被记录,建议在生产环境中使用加密方式传输密码。

命令简介

chpasswd 命令用于批量更新用户密码。它从标准输入读取用户名和密码对,并使用这些数据来更新用户的密码。

主要特点:

  • 批量更新多个用户的密码
  • 支持明文和加密密码输入
  • 可以从文件或管道读取用户名/密码对
  • 通常需要root权限执行
  • 适用于自动化脚本和批量用户管理
注意: chpasswd命令默认需要root权限,并且会立即修改密码,没有确认提示。使用时请格外小心。

命令语法

chpasswd [选项]
echo "用户名:密码" | chpasswd [选项]
chpasswd [选项] < 密码文件

输入格式:每行一个用户名:密码对

用户名1:密码1
用户名2:密码2
用户名3:密码3

常用选项

选项 说明
-e, --encrypted 输入的密码已经是加密格式(如/etc/shadow中的格式)
-c, --crypt-method 方法 指定加密方法(DES, MD5, SHA256, SHA512等)
-m, --md5 使用MD5加密密码(已弃用,建议使用-c选项)
-R, --root CHROOT_DIR 在chroot目录中应用更改
-h, --help 显示帮助信息

命令示例

1. 基本使用:更改单个用户密码

使用echo和管道更改单个用户密码:

# 更改用户alice的密码
echo "alice:newpassword123" | sudo chpasswd

# 使用here document方式
sudo chpasswd << EOF
alice:newpassword123
EOF

# 验证密码是否更改
su - alice  # 然后输入新密码测试

2. 批量更改用户密码

批量更改多个用户的密码:

# 方法1:直接输入多行
sudo chpasswd << EOF
alice:password123
bob:password456
charlie:password789
EOF

# 方法2:从文件读取
cat > passwords.txt << EOF
alice:alicepass123
bob:bobpass456
charlie:charliepass789
EOF

sudo chpasswd < passwords.txt

# 方法3:使用循环
for user in alice bob charlie; do
    echo "$user:newpass$RANDOM" | sudo chpasswd
done

3. 使用加密密码

使用已加密的密码(避免明文传输):

# 生成加密密码
encrypted_pass=$(openssl passwd -1 "mypassword")
echo "alice:$encrypted_pass" | sudo chpasswd -e

# 或使用mkpasswd
encrypted_pass=$(mkpasswd --method=sha-512 "mypassword")
echo "bob:$encrypted_pass" | sudo chpasswd -e

# 直接使用/etc/shadow格式的密码
shadow_line="alice:\$6\$salt\$encryptedhash:..."
echo "$shadow_line" | sudo chpasswd -e

4. 指定加密方法

指定密码的加密算法:

# 使用SHA-512加密(现代Linux默认)
echo "alice:password123" | sudo chpasswd -c SHA512

# 使用SHA-256加密
echo "bob:password456" | sudo chpasswd -c SHA256

# 使用MD5加密(已不安全,不推荐)
echo "charlie:password789" | sudo chpasswd -c MD5

# 使用DES加密(非常不安全,仅用于兼容)
echo "david:password000" | sudo chpasswd -c DES

5. 重置用户密码

批量重置用户密码为随机密码:

# 生成随机密码并设置
for user in alice bob charlie; do
    random_pass=$(openssl rand -base64 12)
    echo "$user:$random_pass" | sudo chpasswd
    echo "用户 $user 的新密码: $random_pass"
done

# 使用pwgen生成易记密码
sudo apt install pwgen  # Debian/Ubuntu
# sudo yum install pwgen  # RHEL/CentOS

for user in user1 user2 user3; do
    random_pass=$(pwgen -s 12 1)
    echo "$user:$random_pass" | sudo chpasswd
    echo "$user:$random_pass" >> new_passwords.txt
done

6. 从CSV文件导入密码

从CSV格式文件批量导入用户名和密码:

# CSV文件格式:username,password
cat > users.csv << EOF
alice,AlicePass123
bob,BobPass456
charlie,CharliePass789
EOF

# 转换为chpasswd格式并执行
awk -F, '{print $1":"$2}' users.csv | sudo chpasswd

# 或使用cut命令
cut -d, -f1,2 users.csv | tr ',' ':' | sudo chpasswd

安全实践

安全注意事项

避免的安全风险:

  1. 明文密码: 避免在命令行中直接使用明文密码
  2. 历史记录: 密码可能保存在shell历史记录中
  3. 进程列表: 密码可能在ps命令的输出中可见
  4. 临时文件: 包含密码的文件可能未被安全删除

安全建议:

# 1. 使用加密密码
enc_pass=$(openssl passwd -1 "实际密码")
echo "user:$enc_pass" | sudo chpasswd -e

# 2. 使用文件并设置严格权限
echo "user:password" > temp_pass
chmod 600 temp_pass
sudo chpasswd < temp_pass
shred -u temp_pass  # 安全删除文件

# 3. 避免密码出现在历史记录中
# 在bash中,在命令前加空格(需要设置HISTCONTROL=ignorespace)
 echo "user:pass" | sudo chpasswd

# 4. 使用随机密码并立即显示
pass=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c12)
echo "user:$pass" | sudo chpasswd
echo "密码: $pass"  # 立即显示,然后手动记录

实用脚本示例

脚本1:安全批量更改密码
#!/bin/bash
# safe_bulk_password_change.sh - 安全批量更改用户密码

# 配置
PASSWORD_FILE="/tmp/passwords.$$"
LOG_FILE="/var/log/password_change.log"
ENCRYPT_METHOD="SHA512"

# 清理函数
cleanup() {
    if [ -f "$PASSWORD_FILE" ]; then
        shred -u "$PASSWORD_FILE"
    fi
}

# 注册清理函数
trap cleanup EXIT INT TERM

echo "开始批量更改密码..."
echo "时间: $(date)" | tee -a "$LOG_FILE"

# 创建临时密码文件(严格权限)
touch "$PASSWORD_FILE"
chmod 600 "$PASSWORD_FILE"

# 生成并设置新密码
while IFS= read -r user; do
    # 跳过空行和注释
    [[ "$user" =~ ^# ]] || [[ -z "$user" ]] && continue

    # 检查用户是否存在
    if ! id "$user" &>/dev/null; then
        echo "警告: 用户 $user 不存在,跳过" | tee -a "$LOG_FILE"
        continue
    fi

    # 生成随机密码
    new_password=$(openssl rand -base64 16 | tr -d '/+=' | cut -c1-12)

    # 记录到临时文件
    echo "$user:$new_password" >> "$PASSWORD_FILE"

    # 更改密码
    if sudo chpasswd -c "$ENCRYPT_METHOD" < "$PASSWORD_FILE"; then
        echo "成功: 用户 $user 密码已更改" | tee -a "$LOG_FILE"
        echo "密码: $new_password (请立即记录并删除此消息)" >> "$LOG_FILE"
    else
        echo "错误: 用户 $user 密码更改失败" | tee -a "$LOG_FILE"
    fi

    # 清空临时文件内容
    > "$PASSWORD_FILE"

done < <(getent passwd | grep -E ':/home/' | cut -d: -f1 | sort)

echo "批量密码更改完成" | tee -a "$LOG_FILE"
脚本2:密码过期强制重置
#!/bin/bash
# force_password_reset.sh - 强制密码过期用户重置密码

# 检查密码过期用户
expired_users=$(sudo chage -l | awk -F: '/密码过期/ && $2 ~ /过期/ {print $1}')

if [ -z "$expired_users" ]; then
    echo "没有密码过期的用户"
    exit 0
fi

echo "找到密码过期用户: $expired_users"
echo "开始重置密码..."

# 创建临时文件
temp_file=$(mktemp /tmp/passwords.XXXXXX)
chmod 600 "$temp_file"

for user in $expired_users; do
    # 生成新密码
    new_pass=$(pwgen -s 10 1)

    # 设置新密码
    echo "$user:$new_pass" > "$temp_file"
    if sudo chpasswd < "$temp_file"; then
        # 强制用户下次登录修改密码
        sudo chage -d 0 "$user"

        echo "用户: $user"
        echo "临时密码: $new_pass"
        echo "状态: 已重置,需要首次登录修改"
        echo "---"

        # 记录到安全日志
        logger -t "密码重置" "用户 $user 密码已重置"
    else
        echo "错误: 用户 $user 密码重置失败" >&2
    fi
done

# 清理
rm -f "$temp_file"
echo "密码重置操作完成"

密码加密方法详解

加密方法 标识符 安全性 使用建议
DES 无或$1$ 非常低 不应使用,仅兼容旧系统
MD5 $1$ 不推荐,已可被轻易破解
SHA-256 $5$ 中等 可用,但推荐使用SHA-512
SHA-512 $6$ 推荐使用,现代Linux默认
bcrypt $2a$, $2b$, $2y$ 非常高 非常安全,但可能不兼容所有系统

常见问题

特性 chpasswd passwd
交互性 非交互,批量操作 交互式,单个用户
输入方式 标准输入或文件 终端输入(不显示)
使用场景 批量管理、自动化脚本 日常密码更改
密码确认 无确认,直接更改 需要输入两次确认
安全性 较低(可能记录密码) 较高(不在历史中记录)

建议: 日常使用passwd命令,批量管理使用chpasswd但要格外注意安全。

查看系统默认的密码加密方法:

# 方法1:查看/etc/login.defs
grep -E '^ENCRYPT_METHOD' /etc/login.defs

# 方法2:查看PAM配置
grep -r "pam_unix.so" /etc/pam.d/ | grep sha512

# 方法3:查看现有用户的密码哈希前缀
sudo grep '^root:' /etc/shadow | cut -d: -f2 | cut -c-3

# 方法4:使用authconfig(RHEL/CentOS)
sudo authconfig --test | grep hashing

# 方法5:查看libcrypt设置
cat /etc/default/passwd 2>/dev/null | grep -i crypt

常见哈希前缀:

  • $1$ - MD5
  • $2a$, $2b$, $2y$ - bcrypt
  • $5$ - SHA-256
  • $6$ - SHA-512
  • 无前缀或$DES$ - DES

chpasswd执行失败的常见原因:

  1. 权限不足: 需要root权限
    # 使用sudo
    echo "user:pass" | sudo chpasswd
  2. 用户不存在: 检查用户名
    # 检查用户是否存在
    id username
    getent passwd username
  3. 密码太简单: 系统密码策略限制
    # 检查密码策略
    grep -E '^PASS_' /etc/login.defs
    # 或查看PAM策略
    cat /etc/pam.d/common-password
  4. 输入格式错误: 必须是"用户名:密码"格式
    # 正确格式
    echo "username:password" | chpasswd
    # 错误格式(缺少冒号)
    echo "username password" | chpasswd
  5. 加密密码格式错误: 使用-e选项时密码必须是正确加密格式
    # 正确生成加密密码
    enc_pass=$(openssl passwd -1 "mypassword")
    echo "user:$enc_pass" | chpasswd -e
  6. 系统限制: 用户账户被锁定或禁用
    # 检查账户状态
    sudo passwd -S username
    # 或查看/etc/shadow
    sudo grep "^username:" /etc/shadow

安全最佳实践

chpasswd使用最佳实践
  • 使用加密密码: 尽量使用-e选项配合已加密的密码
  • 设置文件权限: 包含密码的文件设置为600权限,并安全删除
  • 避免历史记录: 在命令前加空格避免记录到bash历史
  • 使用随机密码: 批量操作时生成强随机密码
  • 记录操作日志: 记录密码更改操作以便审计
  • 定期更换密码: 结合chage命令设置密码过期策略
  • 测试环境验证: 在生产环境使用前在测试环境验证脚本
  • 最小权限原则: 只为必要用户更改密码

相关命令