Gradle exec命令行:参数拆分与合并的区别及问题解析
Gradle exec任务参数拆分与合并传递的差异分析
核心差异本质
Gradle的commandLine方法参数传递遵循以下规则:
- 拆分传递(多字符串参数):每个字符串会被操作系统作为独立的命令行参数直接传给目标进程,不会做任何解析或拆分。比如
commandLine 'a', 'b c',目标进程会收到两个参数:a和b c(包含空格的完整单个参数)。 - 合并传递(单字符串参数):只有当目标程序是
cmd /c、bash -c这类命令行解释器时,合并后的字符串才会被解释器按照命令行规则(引号、空格拆分)解析成多个参数;如果直接传给普通程序(如mysql),整个字符串会被当成单个参数,程序无法正确识别。
你的MySQL调用案例分析
失败写法的问题
exec { commandLine 'cmd', '/c', "mysql -u root -p123456", "-e \"create database foo\"" }
这里Gradle给cmd.exe传递的参数是:/c、mysql -u root -p123456、-e "create database foo"。cmd.exe不会重新解析每个参数内部的引号,而是直接把这两个参数原样传给mysql,最终mysql收到的参数是:
-uroot-p123456-e "create database foo"(整个带引号的字符串作为单个参数)
MySQL的-e选项需要后面跟一个独立的SQL命令参数,它会把-e "create database foo"当成一个完整选项,认为SQL命令是带引号的"create database foo",这不符合SQL语法规范,导致执行失败。
成功写法的原因
exec { commandLine 'cmd', '/c', "mysql -u root -p123456 -e \"create database foo\"" }
这里Gradle只给cmd.exe传递一个合并后的命令字符串:mysql -u root -p123456 -e "create database foo"。cmd.exe会按照命令行规则解析这个字符串,拆分出独立的参数传给mysql:
-uroot-p123456-ecreate database foo(不带引号的SQL命令)
此时mysql能正确识别-e选项和对应的SQL命令,自然可以正常执行创建数据库的操作。
更可靠的替代写法
完全跳过cmd /c,直接拆分所有参数传递给mysql,避免命令行解释器的解析歧义:
exec { commandLine 'mysql', '-u', 'root', '-p123456', '-e', 'create database foo' }
这种写法每个参数独立传递,Gradle原样传给mysql,兼容性更好,逻辑也更清晰。
内容的提问来源于stack exchange,提问作者eastwater
相关产品推荐
相关产品推荐

