在服务器迁移、VPS 更换、或跨主机复制文件时,一个常见需求是:
既要保证文件内容一致,也要尽量保留原始的时间戳和权限设置。
很多人会选择 SFTP 作为传输工具,但对它的“属性保留能力”存在误解。本文将从协议能力、客户端行为和实际使用方式三个层面进行说明。
SFTP 是否支持文件属性传输?
是的。
SFTP 协议在设计时就包含了“文件属性”的字段,除了文件内容以外,还可以携带:
- 文件权限(mode)
- 修改时间(mtime)
- 访问时间(atime)
- 文件大小
- 符号链接类型
也就是说,SFTP 并不是一个“只传字节流”的协议,它天生就支持基本元数据的同步。
关键在于:客户端是否开启 preserve
虽然协议支持,但很多 SFTP 客户端默认不会保留这些属性。
以 OpenSSH 自带的 sftp 为例,必须显式启用 -p 参数。
sftp -p remote_host
-p 表示:preserve(保留属性)
开启后,这个会话中所有的文件传输都会自动携带属性信息。
使用 sftp -p 后会保留什么?
在 OpenSSH 的实现中,-p 实际保留的是:
| 属性 | 是否保留 |
|---|---|
| 文件权限(rwx / mode) | ✅ |
| 修改时间(mtime) | ✅ |
| 访问时间(atime) | 多数实现支持 |
| 所有者(uid / gid) | ❌ |
| ACL | ❌ |
| xattr | ❌ |
| Linux capability | ❌ |
| hardlink | ❌ |
它的语义相当于:
cp -p
而不是:
cp -a
sftp -p 是会话级设置
当使用:
sftp -p remote_host
登录后,所有后续操作:
get file
put file
mget *.conf
mput *.log
都会自动以 preserve 模式执行,等价于每一条命令都写了 -p。
无需手动在每次 put 或 get 时重复指定。
适用场景
sftp -p 非常适合以下情况:
- 迁移脚本、配置文件、文档
- 同步普通数据目录
- 需要保持时间戳与权限,但不涉及系统级结构
例如:
- Shell 脚本(保持可执行权限)
- 日志、备份文件(保持时间排序)
- Web 文件、项目目录
不适用的情况
如果要迁移的是:
- 虚拟机存储目录
- 专业备份仓库
- 邮件服务器数据
- 容器或系统级数据目录
这些场景依赖:
- hardlink
- ACL
- xattr
- 精确的 uid/gid
那么 SFTP(即使加了 -p)也不够,必须使用:
rsync -aHAX
或 tar 级别的文件系统复制。
总结
| 需求 | 是否适合使用 sftp -p |
|---|---|
| 只需要保留时间和权限 | ✅ 非常适合 |
| 需要完整 Linux 文件系统语义 | ❌ 不适合 |
如果目标是“在传输中保持文件的时间戳和权限”,
那么:
sftp -p
就是正确、简洁且安全的选择。