如何在Bash中为OpenSSL -config传递多行字符串并修复命令错误
原本使用的OpenSSL命令:
openssl req -new \ -key $OUTPUT_DIRECTORY/certificate.pem \ -reqexts SAN \ -config <(cat ssl_default.conf \ <(printf "\n[SAN]\nsubjectAltName=DNS:$HOSTNAME")) \ -out $OUTPUT_DIRECTORY/certificate.csr
我理解<(cat ssl_default.conf)部分会读取ssl_default.conf文件内容并传递给-config参数,同时通过printf命令添加额外配置行。
为了把整个配置写成Bash字符串,方便提前通过变量完成多处替换,我修改成了以下代码:
CONFIG=$(cat << EOF [ req ] default_bits = 4096 distinguished_name = req_distinguished_name req_extensions = req_ext prompt = no [ req_distinguished_name ] commonName = $HOSTNAME [ req_ext ] subjectAltName = @alt_names [SAN] subjectAltName=DNS:$HOSTNAME EOF ) openssl req -new \ -key $OUTPUT_DIRECTORY/certificate.pem \ -reqexts SAN \ -config <(echo -n "$CONFIG") -out $OUTPUT_DIRECTORY/certificate.csr
但运行时出现错误:line 57: -out: command not found,也就是openssl命令只解析到-config部分,-out被当成了新命令。
请问:
- 如何正确将多行字符串传递给
-config选项? - 为什么必须使用
<(...),不能直接写成... -config "my config here" -out ...?
一、修复当前命令的错误
你遇到的-out: command not found错误,本质是命令换行时的语法问题:在-config <(echo -n "$CONFIG")这一行末尾没有加反斜杠\,导致Bash认为OpenSSL命令到这里就结束了,下一行的-out被当作独立命令执行。
只需要给-config那一行补上末尾的反斜杠即可:
openssl req -new \ -key $OUTPUT_DIRECTORY/certificate.pem \ -reqexts SAN \ -config <(echo -n "$CONFIG") \ # 补上反斜杠,标记命令未结束 -out $OUTPUT_DIRECTORY/certificate.csr
另外,也可以用管道配合标准输入的方式传递配置:把配置字符串通过管道传给OpenSSL,同时指定-config /dev/stdin让它从标准输入读取配置内容:
echo -n "$CONFIG" | openssl req -new \ -key $OUTPUT_DIRECTORY/certificate.pem \ -reqexts SAN \ -config /dev/stdin \ -out $OUTPUT_DIRECTORY/certificate.csr
二、为什么不能直接用-config "my config here"?
OpenSSL的-config参数要求接收的是配置文件的路径,而不是配置内容本身。
<(...)是Bash的进程替换语法,它会在后台创建一个临时的匿名管道(或临时文件,取决于系统),把括号内命令的输出写入这个临时对象,然后返回该对象的路径给-config参数。这样OpenSSL就像读取普通配置文件一样读取到了你的字符串内容。
如果直接传字符串-config "my config here",OpenSSL会把这个字符串当作文件名去系统中查找,自然找不到对应的文件,就会抛出文件不存在的错误。
内容的提问来源于stack exchange,提问作者nullromo

