为何脚本在Kali Linux可正常运行,在Ubuntu却无法执行?
解决Kali开发的Bash脚本在Ubuntu下无法运行的问题
核心错误分析
- 管道语法错误:脚本中
curl ... | $(python3 -c "...")的写法完全错误。$(...)会先执行Python命令(此时无stdin输入直接报错),再将空结果作为命令执行,导致curl输出无法传递给Python。 - HTTP2协议兼容性问题:Ubuntu默认curl启用HTTP2,与Cloudflare API交互时触发协议错误,导致无有效JSON输出。
- 变量边界模糊:
$OPTARG.emailtesting.co.uk会被Shell解析为$OPTARG.emailtesting变量,而非预期的$OPTARG拼接.emailtesting.co.uk。 - Shell变量侵入Python代码:Python代码用双引号包裹时,Shell会替换其中的
$domainName,破坏正则表达式逻辑。 - 依赖缺失:
addSubDomain函数依赖jq,Ubuntu默认未安装该工具。
修复步骤
1. 修正管道语法
将所有| $(python3 -c "...")改为| python3 -c "...",让curl输出直接流向Python进程。
2. 强制curl使用HTTP1.1
在所有curl命令中添加--http1.1参数,解决HTTP2协议错误:
curl --http1.1 -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" ...
3. 明确变量边界
将$OPTARG.emailtesting.co.uk改为${OPTARG}.emailtesting.co.uk,用大括号限定变量范围。
4. 隔离Shell变量与Python代码
将Python代码改用单引号包裹,需要传递的Shell变量用'"$VARNAME"'形式注入,避免Shell提前替换:
# 原错误写法 re.sub(r'(.+)($domainName)$',r'\1',line) # 修正后 domain = '"$domainName"' re.sub(r"(.+)(" + domain + r")$", r"\1", line)
5. 安装缺失依赖
执行以下命令安装所需工具:
sudo apt update && sudo apt install -y jq python3
修改后的完整脚本
#!/bin/bash # Imported variables source <(grep -E '^\w+=' /root/scripts/variables.sh) ZONE_ID=$zoneID cloudflareAPItoken=$cloudflareAPItoken domainName=$domainName serverName=$servername function help { echo "This is the help test" } findID () { curl --http1.1 -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \ -H "Authorization: Bearer $cloudflareAPItoken" \ -H 'Content-Type: application/json' \ | python3 -c "import sys,json data=json.loads(sys.stdin.read()) if data['success']: for item in data['result']: if item['name']=='${OPTARG}.emailtesting.co.uk': f = open('demofile.txt', 'w') f.write(item['id']) f.close()" } deleteDNS () { curl --http1.1 -X DELETE "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$(cat demofile.txt)" \ -H "Authorization: Bearer $cloudflareAPItoken" \ -H "Content-Type: application/json" \ | python3 -m json.tool; rm demofile.txt } listAllDNS () { curl --http1.1 -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \ -H "Authorization: Bearer $cloudflareAPItoken" \ -H 'Content-Type: application/json' \ | python3 -c 'import sys,json, re data=json.loads(sys.stdin.read()) f = open("dnsLIST.txt", "w") if data["success"]: for dict in data["result"]: if dict["type"] == "A" and dict["name"] != '"$domainName"': f.write(dict["name"] + "\n") else: print("ERROR(" + str(data["errors"][0]["code"]) + "): " + data["errors"][0]["message"]) f.close() fin = open("dnsLIST.txt", "r") fout = open("dnsLISTredone.txt", "w") domain = '"$domainName"' for line in fin: new_line = re.sub(r"(.+)(" + domain + r")$", r"\1", line) new_line = new_line.rstrip("\n") + "\n" fout.write(new_line) fin.close() fout.close() ' } addSubDomain () { curl --http1.1 -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \ -H "Authorization: Bearer $cloudflareAPItoken" \ -H "Content-Type: application/json" \ --data "{\"type\":\"A\",\"name\":\"$OPTARG\",\"content\":\"$serverName\",\"ttl\":120,\"proxied\":false}" | jq } if [[ ${#} -eq 0 ]]; then help exit 1 fi optstring="hd:la:" while getopts ${optstring} arg; do case ${arg} in h) help;; d) findID deleteDNS exit 1 ;; l) listAllDNS;; a) addSubDomain;; ?) echo "Invalid option: -${OPTARG}." exit 2;; esac done
内容的提问来源于stack exchange,提问作者Tim Biermann
相关产品推荐
相关产品推荐

