Perl中system命令多行插值字符串执行报错问题排查
问题
原本用Perl的system命令执行单行命令能正常运行:
system("keytool -exportcert -rfc -alias client -file /foo/bar/certificate.pem -keystore $keystorepath -storepass \$(cat /foo/bar/password ) -v");
为提升可读性将命令拆分为多行字符串后执行,出现报错:
my $cmd = qq { keytool -exportcert -rfc -alias client -file /foo/bar/certificate.pem -keystore $keystorepath -storepass \$(cat /foo/bar/password ) -v }; system($cmd);
报错信息:
Use "keytool -?, -h, or --help" for this help message Use "keytool -command_name --help" for usage of command_name. Use the -conf <url> option to specify a pre-configured options file. sh: line 1: -exportcert: command not found sh: line 2: -rfc: command not found sh: line 3: -alias: command not found sh: line 4: -file: command not found sh: line 5: -keystore: command not found sh: line 6: -storepass: command not found
原因与解决方法
原因
你用qq{}定义的多行字符串里,每行结尾的换行符会被shell当成命令分隔符。shell先执行了不带任何参数的keytool(所以输出帮助信息),之后把-exportcert、-rfc这些参数当成独立的新命令去执行,自然会提示“命令未找到”。
解决方案
有两种可行的解决方式:
方式一:转义换行符
在每行末尾添加反斜杠\(Perl里要写两个\\,因为会先解析一次转义),告诉shell这行命令还没结束:
my $cmd = qq { keytool \\ -exportcert \\ -rfc -alias client \\ -file /foo/bar/certificate.pem \\ -keystore $keystorepath \\ -storepass \$(cat /foo/bar/password ) -v }; system($cmd);
方式二:用数组构建命令(推荐)
将命令和参数放到数组中,system会直接执行命令而不通过shell,既保留可读性,又避免shell解析带来的问题。注意这里要改用Perl的qx()函数获取密码内容,因为数组模式下无法使用shell的命令替换:
my @cmd = ( 'keytool', '-exportcert', '-rfc', '-alias', 'client', '-file', '/foo/bar/certificate.pem', '-keystore', $keystorepath, '-storepass', qx(cat /foo/bar/password), '-v' ); system(@cmd);
内容的提问来源于stack exchange,提问作者Jim
相关产品推荐
相关产品推荐

