ant命令传参值带美元符被转义导致执行不达预期

背景

gitlab流水线自动执行sql,使用的是 python 脚本里通过 os.system 包执行 ant 命令行方式进行调用,python 对传参进行一些处理,然后拼接命令cmd传入 os.system;

传参中,有个参数是数据库密码,DBA在创建数据库用户时,密码是随机生成的,有时候会包含美元符“$”,美元符在shell中调用 ant 命令行会被当成一个变量,导致密码不对,连接数据库被拒绝,无法执行sql。

原代码逻辑如下:

self.cmd='ant -f '+self.excutesqlxml+' -Ddriver=\"'+driver+'\" -Durl=\"'+url+'\" -Duserid=\"'+us+'\" -Dpw=\"+pw+'\" -Dlogfile=\"'+logfile+'\" -Dlistpath=\"'+self.listpath+'\" -Dsqlfile=\"'+linesql.replace('\n','')+'\" -Dencoding=\"'+self.dbencoding+'\" -Donerror_type=\"'+self.onerrortype+'\" -Ddelimiter='+delimiter+' -Dkeepformat='+keepformat
result=os.system(self.cmd)

对应报错如下:
file

处理方案

1、使用单引号“‘”

在 shell 中使用单引号能阻止对 $ 符号等特殊符号的解释

2、使用反斜杠“\”转义符

处理后的代码如下:

# 将密码字符串中的美元符前增加反斜杠
if "$" in pw:
    pw=pw.replace("$","\$")

# 将 -Dpw= 的值,从双引号替换为单引号
self.cmd='ant -f '+self.excutesqlxml+' -Ddriver=\"'+driver+'\" -Durl=\"'+url+'\" -Duserid=\"'+us+'\" -Dpw=\''+pw+'\' -Dlogfile=\"'+logfile+'\" -Dlistpath=\"'+self.listpath+'\" -Dsqlfile=\"'+linesql.replace('\n','')+'\" -Dencoding=\"'+self.dbencoding+'\" -Donerror_type=\"'+self.onerrortype+'\" -Ddelimiter='+delimiter+' -Dkeepformat='+keepformat

print self.cmd
result=os.system(self.cmd)

重新运行流水线,问题解决,可正常执行sql。

补充

自动执行生产sql,因生产库密码的安全性,所以通过 GitLab CICD环境变量配置,通过 python 的 os.environ.get('prod_db_password') 来获取,再注入 ant 命令执行,获取密码的方式和上面从配置文件获取不一样。

file

当密码包含 $ 符号时,获取该变量值,value 中的 $ 符号后面都被当成了一个环境变量从系统中获取,再返给密码值了;
如: AAA$BBB,通过 python 获取到的是 AAA(不是python原因,是GitLab自身环境变量的机制),需要在 GitLab 里配置成 AAA$$BBB(两个刀乐符);
官方文档
file