chpasswd 命令用于批量更新用户密码。它从标准输入读取用户名和密码对,并使用这些数据来更新用户的密码。
主要特点:
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 |
显示帮助信息 |
使用echo和管道更改单个用户密码:
# 更改用户alice的密码
echo "alice:newpassword123" | sudo chpasswd
# 使用here document方式
sudo chpasswd << EOF
alice:newpassword123
EOF
# 验证密码是否更改
su - alice # 然后输入新密码测试
批量更改多个用户的密码:
# 方法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
使用已加密的密码(避免明文传输):
# 生成加密密码
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
指定密码的加密算法:
# 使用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
批量重置用户密码为随机密码:
# 生成随机密码并设置
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
从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. 使用加密密码
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" # 立即显示,然后手动记录
#!/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"
#!/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$ - DESchpasswd执行失败的常见原因:
# 使用sudo
echo "user:pass" | sudo chpasswd
# 检查用户是否存在
id username
getent passwd username
# 检查密码策略
grep -E '^PASS_' /etc/login.defs
# 或查看PAM策略
cat /etc/pam.d/common-password
# 正确格式
echo "username:password" | chpasswd
# 错误格式(缺少冒号)
echo "username password" | chpasswd
-e选项时密码必须是正确加密格式
# 正确生成加密密码
enc_pass=$(openssl passwd -1 "mypassword")
echo "user:$enc_pass" | chpasswd -e
# 检查账户状态
sudo passwd -S username
# 或查看/etc/shadow
sudo grep "^username:" /etc/shadow
-e选项配合已加密的密码chage命令设置密码过期策略