为何使用SCP时SSH配置中的声明停止执行?
为何使用SCP时SSH配置中的声明停止执行?
我来帮你拆解这个问题——这其实是SCP和SSH在配置处理逻辑上的一个典型差异导致的,很多人用EC2 Instance Connect隧道的时候都踩过这个坑。
首先说核心原因:传统的SCP(也就是默认的scp1模式)并不会完整解析SSH配置里的所有声明。早期的SCP是基于rsh协议实现的,它本质上是个独立程序,不像SSH客户端那样会逐条处理ssh_config里的规则,尤其是LocalCommand这类和会话生命周期绑定的配置项,在SCP的默认模式下根本不会触发。
那怎么解决呢?给你几个实用的方案:
1. 强制SCP使用SFTP模式(最推荐)
SFTP是作为SSH的子系统运行的,它会完全遵循ssh_config的所有配置规则,包括你Match块里的LocalCommand。你有两种方式实现:
- 临时调用时加参数:每次用SCP的时候加上
-s参数,比如:scp -s local-file i-xxxxxx:/remote/path - 永久配置到SSH规则里:直接在你的Match块里加一行配置,这样不管是SSH还是SCP都会自动用SFTP模式:
Match host i-* exec "aws-proxy.sh %r %h ~/.ssh/aws-proxy.%h.%r" IdentityFile ~/.ssh/aws-proxy.%h.%r ProxyCommand aws ec2-instance-connect open-tunnel --instance-id %h PermitLocalCommand yes LocalCommand rm ~/.ssh/aws-proxy.%h.%r* ScpCommand sftp # 新增这一行
2. 把清理逻辑移到代理脚本里
如果不想改SCP的运行模式,你可以把删除临时密钥的逻辑放到aws-proxy.sh里,比如在脚本末尾加一段后台运行的延迟清理(防止隧道还在使用时就删掉密钥):
# 在aws-proxy.sh的最后加上 sleep 5 # 给连接关闭留一点时间 rm -f "$3"* &
不过这种方式不如第一种可靠,因为延迟时间很难精准控制,万一连接时间长了,密钥可能被提前删掉导致问题。
3. 确认PermitLocalCommand的全局设置
虽然你已经在Match块里设了PermitLocalCommand yes,但还是要检查一下全局的ssh_config里有没有把这个选项设为no——如果全局是no,Match块里的设置可能不会生效(不过这种情况比较少见)。
总结一下,最省心的方案就是给你的Match块加上ScpCommand sftp,这样SCP就会像SSH一样完整执行所有配置声明,你的临时密钥清理逻辑也能正常运行了。
备注:内容来源于stack exchange,提问作者Josh F.




