Akamai缓存清理脚本Win10正常,Linux下失效求助
看起来你遇到的情况挺棘手——脚本在Windows上能正常完成缓存清理,到Linux上控制台输出和Windows完全一致,但就是没实际生效。结合Shell脚本跨平台的常见坑,我整理了几个大概率的原因和对应的排查、解决步骤:
1. Bash版本不支持declare -n命名引用特性
你的脚本里多处用到了declare -n(比如mk_auth_header函数里的local -n aka_props=$1),这个特性是Bash 4.0及以上版本才支持的。如果你的Linux系统用的是旧版Bash(比如CentOS 6自带的Bash 3.2),这部分代码会直接失效,但可能不会抛出明显报错,导致签名生成错误,Akamai API直接拒绝了你的请求。
排查&解决:
- 先在Linux终端执行
bash --version查看版本,如果低于4.0,要么升级Bash,要么修改代码替换declare -n的用法。 - 举个修改例子,把依赖命名引用的函数改成直接传递参数:
# 原mk_auth_header函数 function mk_auth_header { [ "$#" -lt 3 ] && return 1 local -n aka_props=$1 local timestamp=$2 local nonce=$3 echo -n "EG1-HMAC-SHA256 client_token=${aka_props[client_token]};access_token=${aka_props[access_token]};timestamp=${timestamp};nonce=${nonce};" } # 修改后(直接传递所需参数) function mk_auth_header { [ "$#" -lt 4 ] && return 1 local client_token=$1 local access_token=$2 local timestamp=$3 local nonce=$4 echo -n "EG1-HMAC-SHA256 client_token=${client_token};access_token=${access_token};timestamp=${timestamp};nonce=${nonce};" } # 调用时改为 AUTH_HEADER=$( mk_auth_header "${AKA_PROPS[client_token]}" "${AKA_PROPS[access_token]}" ${TIMESTAMP} ${NONCE} )
2. OpenSSL命令的跨平台输出差异
Windows和Linux的OpenSSL在base64编码的换行处理上有区别:Linux下openssl base64默认每76个字符加换行,而Windows版本可能不会。这会导致签名计算时的字符串不一致,Akamai无法验证你的请求合法性。
解决方法:
给openssl base64加上-A参数(取消自动换行),修改这两个函数:
function base64_hmac_sha256 { [ "$#" -lt 2 ] && return 1 local key=$1 local value=$2 echo -ne "${value}"| openssl sha256 -binary -hmac "${key}" | openssl base64 -A } function base64_sha256 { [ "$#" -lt 1 ] && return 1 local value=$1 echo -ne "${value}" | openssl dgst -binary -sha256 | openssl base64 -A }
3. 脚本换行符的跨平台问题
如果你的脚本是在Windows上编辑后传到Linux的,可能带有Windows的CRLF换行符(\r\n),而Linux系统期望LF(\n)。虽然多数情况下Shell能兼容,但某些命令(比如sed、awk)会把\r当成普通字符,导致变量值异常(比如签名里多了隐形的\r字符)。
排查&解决:
- 用
cat -A your_script.sh查看脚本,每行末尾如果有^M就是CRLF问题。 - 用
dos2unix your_script.sh转换换行符,或者在Vim里执行:set fileformat=unix后保存。
4. Curl命令的转义陷阱
脚本最后通过echo curl ... | bash -x的方式执行命令,这里的引号转义在Linux下可能出问题——比如-d \'${BODY}\'可能被解析成带单引号的参数,而不是把BODY内容作为POST数据传递。
优化方法:
直接执行curl命令,避免通过echo管道转义,修改最后一段代码:
curl -s -H "Expect:" \ -H "User-Agent:${P_NAME}" \ -H "Accept:${H_JSON}" \ -H "${H_JSON}" \ -H "${SIGNED_AUTH_HEADER}" \ -X POST -d "${BODY}" "${DATA_TO_SIGN[scheme]}://${DATA_TO_SIGN[host]}${DATA_TO_SIGN[request_uri]}" | jq .
5. 查看隐藏的错误详情
虽然你说控制台输出一致,但可能Linux下curl的错误被-s参数隐藏了。可以去掉-s换成-v,让curl输出详细的HTTP请求日志,直接看Akamai返回的错误信息(比如签名无效、权限不足、请求格式错误等):
curl -v -H "Expect:" \ -H "User-Agent:${P_NAME}" \ -H "Accept:${H_JSON}" \ -H "${H_JSON}" \ -H "${SIGNED_AUTH_HEADER}" \ -X POST -d "${BODY}" "${DATA_TO_SIGN[scheme]}://${DATA_TO_SIGN[host]}${DATA_TO_SIGN[request_uri]}"
内容的提问来源于stack exchange,提问作者S.Kav




