使用变量驱动的SCP脚本无法免密执行,硬编码版本可正常运行
看起来你遇到了一个很典型的变量替换导致SCP免密失效的问题,我来帮你分析下可能的原因和解决办法:
核心问题排查方向
最常见的原因是变量展开后的命令和硬编码版本存在细微差异,或者脚本运行的环境导致变量解析不符合预期。我们可以一步步来定位:
验证变量展开后的命令是否完全匹配硬编码版本
在你的脚本里,scp命令前加上几行调试输出,看看变量替换后的命令和你手动写的硬编码命令是不是完全一致:# 在scp命令前添加调试输出 echo "生成的SCP命令:" echo "scp gfstd@${SERVER_NAME}:${FOLDER_ROOT_PATH}/details_all_data_${CURDATE}.dat.gz /local/FILE_UPLOADS/I_FILES/"运行脚本后,把输出的命令和你能正常运行的硬编码版本对比,重点看主机名、路径、日期格式有没有差异——哪怕是一个多余的空格、大小写错误,都可能导致SSH密钥匹配失败。
检查变量的实际值是否正确
有时候变量赋值可能因为shell环境差异出问题,比如日期格式、路径是否有特殊字符。可以在脚本开头添加变量值打印:echo "调试变量值:" echo "SERVER_NAME: $SERVER_NAME" echo "FOLDER_ROOT_PATH: $FOLDER_ROOT_PATH" echo "CURDATE: $CURDATE"确认这些值和硬编码的内容完全一致,比如
CURDATE是不是严格的YYYYMMDD格式,没有多余的符号。确保脚本用正确的Shell运行
你的脚本开头指定了#!/bin/ksh,但你是用sh data_load.sh运行的——不同Shell(比如ksh和bash/sh)的变量解析规则可能有细微差别。建议直接用ksh data_load.sh来运行脚本,避免Shell兼容问题。检查SSH密钥的匹配逻辑
SSH免密是基于主机身份匹配的,如果$SERVER_NAME解析的IP和硬编码的bcpstd.root.net对应的IP不一致,或者你的~/.ssh/config里有主机别名配置,可能导致密钥不匹配。可以用ping $SERVER_NAME和ping bcpstd.root.net确认指向同一个IP,同时检查远程服务器gfstd用户的~/.ssh/authorized_keys里是否正确添加了你的本地公钥,且权限设置正确(authorized_keys权限为600,.ssh目录权限为700)。
修改后的示例脚本(带调试)
#!/bin/ksh SERVER_NAME=bcpstd.root.net FOLDER_ROOT_PATH=/data/feed/daily CURDATE=$(date +"%Y%0m%0d") # 用$()代替反引号,可读性更好 # 调试输出变量 echo "=== 调试信息 ===" echo "SERVER_NAME: $SERVER_NAME" echo "FOLDER_ROOT_PATH: $FOLDER_ROOT_PATH" echo "CURDATE: $CURDATE" # 输出要执行的命令 echo "=== 即将执行的SCP命令 ===" echo "scp gfstd@${SERVER_NAME}:${FOLDER_ROOT_PATH}/details_all_data_${CURDATE}.dat.gz /local/FILE_UPLOADS/I_FILES/" # 执行SCP scp gfstd@${SERVER_NAME}:${FOLDER_ROOT_PATH}/details_all_data_${CURDATE}.dat.gz /local/FILE_UPLOADS/I_FILES/
通过这些步骤,你应该能快速定位到变量替换中的问题,让脚本和硬编码版本一样实现免密执行。
备注:内容来源于stack exchange,提问作者Pat

