本文目录导读:

我来详细介绍Shell脚本迁移用户家目录的方法。
基本迁移流程
单用户迁移脚本
#!/bin/bash
# 迁移单个用户家目录
migrate_user_home() {
local username=$1
local new_base_dir=$2
# 检查用户是否存在
if ! id "$username" &>/dev/null; then
echo "错误: 用户 $username 不存在"
return 1
fi
# 获取当前家目录
local old_home=$(eval echo ~$username)
local new_home="${new_base_dir}/${username}"
# 检查新目录是否已存在
if [ -d "$new_home" ]; then
echo "警告: 新家目录 $new_home 已存在"
read -p "是否覆盖? (y/n): " confirm
if [ "$confirm" != "y" ]; then
return 1
fi
fi
# 创建新家目录
mkdir -p "$new_home"
# 复制文件(保留权限和时间戳)
echo "正在复制文件到 $new_home ..."
cp -rp "$old_home/"* "$new_home/"
cp -rp "$old_home/."* "$new_home/" 2>/dev/null # 复制隐藏文件
# 设置正确的所有权
chown -R "$username:$(id -gn $username)" "$new_home"
# 更新用户家目录配置
usermod -d "$new_home" "$username"
echo "用户 $username 的家目录已从 $old_home 迁移到 $new_home"
}
# 使用示例
# migrate_user_home "username" "/data/home"
批量迁移脚本
#!/bin/bash
# 批量迁移家目录
batch_migrate_home() {
local old_base_dir=$1
local new_base_dir=$2
local exclude_users=("root" "nobody" "systemd-coredump")
echo "开始批量迁移家目录..."
echo "从: $old_base_dir"
echo "到: $new_base_dir"
# 获取所有用户列表
for user_dir in "$old_base_dir"/*/; do
local username=$(basename "$user_dir")
# 跳过排除的用户
if [[ " ${exclude_users[@]} " =~ " ${username} " ]]; then
echo "跳过用户: $username"
continue
fi
# 检查是否为系统用户
local uid=$(id -u "$username" 2>/dev/null)
if [ "$uid" -gt 1000 ] 2>/dev/null; then # 只迁移普通用户
echo "正在迁移用户: $username"
migrate_user_home "$username" "$new_base_dir"
fi
done
}
# 使用示例
# batch_migrate_home "/home" "/data/home"
完整版迁移脚本
#!/bin/bash
# 配置
BACKUP_DIR="/backup/home_$(date +%Y%m%d)"
LOG_FILE="/var/log/home_migration_$(date +%Y%m%d_%H%M%S).log"
EXCLUDE_USERS=("root" "nobody" "systemd-coredump" "games")
# 日志函数
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# 错误处理
error_exit() {
log "错误: $1"
exit 1
}
# 备份家目录
backup_home() {
local username=$1
local old_home=$2
log "正在备份 $username 的家目录..."
mkdir -p "$BACKUP_DIR"
# 创建备份(使用tar或rsync)
if command -v rsync &>/dev/null; then
rsync -a --delete "$old_home/" "$BACKUP_DIR/$username/"
else
tar -czf "$BACKUP_DIR/${username}_home_backup.tar.gz" -C "$(dirname $old_home)" "$(basename $old_home)"
fi
log "备份完成: $BACKUP_DIR/$username"
}
# 检查磁盘空间
check_disk_space() {
local new_home=$1
local required_space=$2
local available_space=$(df "$new_home" | awk 'NR==2 {print $4}')
if [ "$available_space" -lt "$required_space" ]; then
return 1
fi
return 0
}
# 迁移用户家目录(完整版)
migrate_user_home_advanced() {
local username=$1
local new_base_dir=$2
log "开始迁移用户: $username"
# 检查用户
if ! id "$username" &>/dev/null; then
log "用户 $username 不存在"
return 1
fi
# 获取用户信息
local old_home=$(grep "^${username}:" /etc/passwd | cut -d: -f6)
local user_shell=$(grep "^${username}:" /etc/passwd | cut -d: -f7)
local uid=$(id -u "$username")
local gid=$(id -g "$username")
log "当前家目录: $old_home"
log "用户Shell: $user_shell"
# 检查是否是系统用户
if [ "$uid" -lt 1000 ]; then
log "跳过系统用户: $username"
return 1
fi
# 新家目录路径
local new_home="${new_base_dir}/${username}"
# 检查磁盘空间
local old_size=$(du -s "$old_home" 2>/dev/null | awk '{print $1}')
if ! check_disk_space "$new_base_dir" "$old_size"; then
log "错误: 目标磁盘空间不足"
return 1
fi
# 备份
if ! backup_home "$username" "$old_home"; then
log "备份失败,取消迁移"
return 1
fi
# 检查是否有用户正在登录
if who | grep -q "^$username "; then
log "警告: 用户 $username 当前已登录"
read -p "是否继续? (y/n): " confirm
if [ "$confirm" != "y" ]; then
return 1
fi
fi
# 创建新目录
mkdir -p "$new_home"
# 使用rsync复制(更快更可靠)
if command -v rsync &>/dev/null; then
log "使用rsync复制文件..."
rsync -a --progress "$old_home/" "$new_home/" 2>&1 | tee -a "$LOG_FILE"
else
log "使用cp复制文件..."
cp -rp "$old_home/"* "$new_home/"
cp -rp "$old_home/."* "$new_home/" 2>/dev/null
fi
# 检查复制是否成功
if [ $? -ne 0 ]; then
log "文件复制失败"
return 1
fi
# 设置权限
chown -R "$uid:$gid" "$new_home"
chmod --reference="$old_home" "$new_home"
# 更新系统配置
usermod -d "$new_home" -m "$username" 2>/dev/null || {
log "警告: usermod失败,尝试直接修改passwd文件"
# 直接修改passwd文件(谨慎操作)
sed -i "s|^${username}:.*:${uid}:${gid}:.*:${old_home}:.*|${username}:x:${uid}:${gid}:${username}:${new_home}:${user_shell}|" /etc/passwd
}
log "用户 $username 迁移完成"
log "旧家目录: $old_home"
log "新家目录: $new_home"
return 0
}
# 清理临时文件
cleanup() {
log "清理临时文件..."
# 可以添加清理逻辑
}
# 主函数
main() {
local mode=$1
case $mode in
"single")
read -p "输入用户名: " username
read -p "输入新家目录基路径: " new_base
migrate_user_home_advanced "$username" "$new_base"
;;
"batch")
read -p "输入旧家目录基路径 [/home]: " old_base
old_base=${old_base:-/home}
read -p "输入新家目录基路径: " new_base
log "批量迁移模式: $old_base -> $new_base"
# 获取所有用户列表
for user_dir in "$old_base"/*/; do
[ -d "$user_dir" ] || continue
local username=$(basename "$user_dir")
# 跳过排除用户
if [[ " ${EXCLUDE_USERS[@]} " =~ " ${username} " ]]; then
log "跳过用户: $username"
continue
fi
migrate_user_home_advanced "$username" "$new_base"
done
;;
"rollback")
read -p "输入需要回滚的用户名: " username
# 回滚逻辑
log "回滚功能待实现"
;;
*)
echo "用法: $0 {single|batch|rollback}"
echo " single - 迁移单个用户"
echo " batch - 批量迁移所有用户"
echo " rollback- 回滚迁移"
exit 1
;;
esac
cleanup
log "迁移完成,日志文件: $LOG_FILE"
}
# 执行主函数
main "$@"
使用示例
基本使用
# 迁移单个用户 ./migrate_home.sh single # 批量迁移 ./migrate_home.sh batch
命令行直接调用
# 单用户迁移 migrate_user_home "john" "/data/home" # 批量迁移 batch_migrate_home "/home" "/data/home"
重要注意事项
-
备份优先
- 迁移前务必备份原家目录
- 保留数据完整性
-
用户权限
- 需要root权限执行
- 确保目标目录权限正确
-
服务停止
# 迁移前停止相关服务 systemctl stop user-runtime-dir@$UID.service systemctl stop user@$UID.service
-
验证迁移
# 验证文件完整性 diff -r old_home new_home # 检查用户设置 getent passwd username id username
-
回滚方案
# 从备份恢复 systemctl stop user@$UID.service usermod -d /old/home username cp -rp /backup/home/username/* /old/home/ chown -R username:username /old/home
这个脚本提供了完整的家目录迁移功能,包括备份、迁移、验证和回滚机制,实际使用时请根据具体环境调整参数。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播