在执行部署脚本后,通过 ls -la 命令查看远程服务器文件时,显示的文件所有者是 games 而不是预期的 root 用户
远程服务器用户显示问题分析
问题描述
在执行部署脚本后,通过 ls -la
命令查看远程服务器文件时,显示的文件所有者是 games
而不是预期的 root
用户。
# 终端显示结果
drwxr-xr-x. 3 501 games 57 8月 15 15:03 .
drwxr-xr-x. 3 root root 20 8月 11 09:44 ..
drwxr-xr-x. 2 501 games 86 8月 15 15:03 assets
-rw-r--r--. 1 501 games 453 8月 15 15:03 favicon.svg
-rw-r--r--. 1 501 games 462 8月 15 15:03 index.html
原因分析
1. UID/GID 映射问题
2. 具体原因
A. 文件所有权保持
- rsync 行为:默认情况下,
rsync
会尝试保持文件的原始 UID/GID - 本地 UID:本地文件的 UID 是 501(通常是 macOS 用户的默认 UID)
- 远程映射:远程服务器上 UID 501 对应的用户是
games
B. 用户映射差异
# 本地系统(macOS)
UID 501 = 当前用户# 远程系统(Linux)
UID 501 = games 用户
UID 0 = root 用户
C. rsync 权限处理
- 虽然使用
root
用户连接,但rsync
保持了原始文件的 UID - 远程系统将 UID 501 解析为
games
用户
解决方案
方案一:修改 rsync 参数(推荐)
# 在 deploy.sh 中修改 rsync 命令
sshpass -p "$REMOTE_PASSWORD" rsync -avz --delete --chown=root:root \-e "ssh -o StrictHostKeyChecking=no -p $REMOTE_PORT" \"$LOCAL_DIST_DIR/" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/"
优点:
- 直接在传输时设置正确的所有者
- 一步到位,无需额外操作
- 保持部署流程的原子性
方案二:传输后修改所有权
# 在上传完成后添加
sshpass -p "$REMOTE_PASSWORD" ssh -o StrictHostKeyChecking=no -p "$REMOTE_PORT" "$REMOTE_USER@$REMOTE_HOST" \"chown -R root:root $REMOTE_DIR"
优点:
- 灵活性高,可以设置任意用户
- 不影响传输过程
方案三:使用 --numeric-ids 参数
# 保持数字 UID,不进行用户名映射
sshpass -p "$REMOTE_PASSWORD" rsync -avz --delete --numeric-ids \-e "ssh -o StrictHostKeyChecking=no -p $REMOTE_PORT" \"$LOCAL_DIST_DIR/" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/"
最佳实践建议
1. 生产环境配置
# 推荐的 rsync 配置
RSYNC_OPTS="-avz --delete --chown=www-data:www-data --chmod=D755,F644"
2. 安全考虑
- 为 Web 应用设置专用用户(如
www-data
) - 避免使用
root
用户运行 Web 服务 - 设置适当的文件权限
3. 部署流程优化
修复建议
基于当前的部署脚本,建议采用方案一,修改 rsync
命令添加 --chown=root:root
参数:
# 修改 upload_files 函数
upload_files() {log_info "上传文件到远程服务器..."# 使用 rsync 上传文件并设置正确的所有者if sshpass -p "$REMOTE_PASSWORD" rsync -avz --delete --chown=root:root \-e "ssh -o StrictHostKeyChecking=no -p $REMOTE_PORT" \"$LOCAL_DIST_DIR/" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/"; thenlog_success "文件上传完成"elselog_error "文件上传失败"exit 1fi
}
这样可以确保上传的文件在远程服务器上显示为 root
用户所有,符合预期的配置。