SCP传输失败应先验证SSH连通性,因SCP基于SSH协议;常见问题包括端口误用(-P非-p)、权限不足、路径不存在、目录复制未加-r、空格需引号包裹、-p不保留属主、覆盖无提示等。

scp传输失败时先看ssh连不连得通
scp底层走的就是ssh协议,所有连接、认证、端口、密钥问题都会原样暴露出来。如果scp报错卡在“Permission denied”或“Connection refused”,别急着调scp参数,先手动试下:ssh user@host -p 2222。能连上ssh,scp大概率也能用;连不上,scp再加-v也只是把同样的错误多打印几行。
常见断点位置:
-
ssh默认端口不是22 → 必须用-P(大写P)指定,比如-P 2222,小写-p是保留文件时间戳的参数,混用会静默失效 - 目标用户没权限读源文件 → 比如
scp user@host:/var/log/syslog ./,但user对/var/log/syslog无读权限,scp会直接报Permission denied (publickey),实际和密钥无关 - 目标路径不存在且无写权限 →
scp file user@host:/no/such/path/会失败,scp不会自动创建父目录
复制目录必须加-r,但-r不等于“智能同步”
scp -r只是递归拷贝快照,不是rsync,没有增量、删除、跳过相同文件等逻辑。它会把整个源目录树完整覆盖到目标位置,哪怕目标已有同名文件且内容一致,也会重传。
使用时注意:
- 源路径末尾带
/和不带,行为不同:scp -r dir/ user@host:/dst拷贝dir下所有内容到/dst;scp -r dir user@host:/dst则把整个dir目录(含名字)拷过去,结果是/dst/dir/... -
-r不能跨协议或跨用户隐式提权:比如scp -r /etc user@host:/tmp,若/etc里有root专属文件,普通user可能读不到,导致部分文件跳过或报错 - 大目录传输建议加
-C开启压缩,尤其跨公网时;但内网千兆环境反而可能因CPU开销拖慢速度
文件名和路径里的空格、特殊字符要小心处理
scp本身不解析引号,shell先做变量展开和分词。如果你写scp "my file.txt" user@host:/path,双引号只在本地生效,远程路径/path没问题;但要是远程路径含空格,比如scp file user@host:"/home/my folder/",就必须把整个远程目标用引号包住,否则scp会把my和folder/当成两个参数,报错scp: ambiguous target。
更稳妥的做法是统一用单引号避免shell干扰:
- 本地有空格:
scp 'my file.txt' user@host:/tmp - 远程有空格:
scp file.txt user@host:'/home/my folder/' - 两边都有:
scp 'my file.txt' user@host:'/home/my folder/'
别依赖反斜杠转义,不同shell行为不一致,引号最可靠。
用-p保留时间戳和权限,但别指望它修好所有权
-p参数会让scp尝试保留源文件的修改时间、访问时间、权限位(如rw-r--r--),但它**不会也不该**保留UID/GID——因为远程用户很可能没有对应uid,硬设会导致权限混乱甚至拒绝写入。
所以:
- 传配置文件、脚本时加
-p很实用,避免执行权限丢失或touch误触发监控 - 传日志或数据文件时,
-p意义不大,时间戳本来就不准,权限也常需按目标环境重设 - 如果远程目标目录是
www-data:www-data,而你用user账户传文件,即使加了-p,文件属主仍是user:user,后续可能需要chown补一刀
真正容易被忽略的是:当目标路径已存在同名文件,scp会直接覆盖,不提示、不备份、不校验md5——传关键文件前,要么先ssh登录确认,要么用rsync --dry-run探路。


















