提问人:Husker 提问时间:11/9/2023 更新时间:11/10/2023 访问量:88
在 bash 脚本中使用字符串参数失败
Using string parameter in bash script failt
问:
我需要创建一些证书,并想为此编写一个小的 bash 脚本。
首先,我在创建自己的 bash 脚本方面没有太多经验。
我想将最重要的值(如计算机名称和密码)作为参数传递。不幸的是,我收到错误:
keytool 错误:java.io.IoException:AVA 格式不正确
该错误表示命令中的字符串未正确解释。 我认为问题是我没有正确处理字符串,但我不明白到底出了什么问题。
如果我在终端中输入这样的命令,它可以正常工作
#!/bin/bash
echo "$1" # servername
echo "$2" # domain
echo "$3" # password
echo
keytool -noprompt -keystore $1.$2.truststore.jks -alias CARoot -import -file ca.cert -storetype jks -storepass $3 -keypass $3
keytool -genkey -noprompt -keyalg RSA -storetype pkcs12 -alias $1.$2 -dname $1'.'$2',O=COMPANY,OU=COMPANY,L=NY,ST=NY,C=us' \
-ext 'SAN=DNS:example1.com,DNS:example2.com'
-keystore $1.$2'.keystore2.jks' -storepass $3 -keypass $3
你能告诉我我做错了什么吗?
答:
-1赞
Vinith_jk_bro
11/9/2023
#1
这是您处理空格和连接字符串的方式。在脚本中传递参数时,需要正确引用变量以处理值包含空格的情况。
请尝试以下修改后的脚本版本:
#!/bin/bash
server_name="$1"
domain="$2"
password="$3"
echo "$server_name"
echo "$domain"
echo "$password"
keytool -noprompt -keystore "$server_name.$domain.truststore.jks" -alias CARoot -import -file ca.cert -storetype jks -storepass "$password" -keypass "$password"
keytool -genkey -noprompt -keyalg RSA -storetype pkcs12 -alias "$server_name.$domain" -dname "$server_name.$domain,O=COMPANY,OU=COMPANY,L=NY,ST=NY,C=us" \
-ext "SAN=DNS:example1.com,DNS:example2.com" -keystore "$server_name.$domain.keystore2.jks" -storepass "$password" -keypass "$password"
此脚本正确引用变量,并确保正确处理文件名和带空格的值。快来试试吧!
评论
0赞
Husker
11/9/2023
我明白你的意思。我已经重建了它,但不幸的是错误仍然存在。第一个命令有效。只有使用第二个命令才会发生错误。
0赞
Husker
11/9/2023
在我看来,bash 在执行命令时省略了“ 。
0赞
Vinith_jk_bro
11/9/2023
该问题似乎与您在第二个 keytool 命令中处理可分辨名称 (DN) 的方式有关。可能是 DN 中的空格导致了问题。
0赞
Vinith_jk_bro
11/9/2023
keytool -genkey -noprompt -keyalg RSA -storetype pkcs12 -alias “$server_name.$domain” \ -dname “CN=$server_name.$domain, O=COMPANY, OU=COMPANY, L=NY, ST=NY, C=us” \ -ext “SAN=DNS:example1.com,DNS:example2.com” \ -keystore “$server_name.$domain.keystore2.jks” -storepass “$password” -keypass “$password”
0赞
knittl
11/9/2023
@Husker不是值的一部分,而是 shell 语法的一部分。如果要求引号成为值的一部分,则必须写成 或 。"
"\"...\""
'"..."'
0赞
Ed Morton
11/10/2023
#2
试试这个,使用正确的引号,正确的换行符,并将缺少的添加到选项字符串中。CN=
-dname
keytool -genkey -noprompt -keyalg RSA -storetype pkcs12 -alias "$1.$2" \
-dname "CN=$1.$2,O=COMPANY,OU=COMPANY,L=NY,ST=NY,C=us" \
-ext 'SAN=DNS:example1.com,DNS:example2.com' \
-keystore "$1.$2.keystore2.jks" -storepass "$3" -keypass "$3"
调查详情和观察结果如下...
您在评论中告诉我们这有效:
server_name="$1"
domain="$2"
password="$3"
keytool -noprompt -keystore "$server_name.$domain.truststore.jks" -alias CARoot -import -file ca.cert -storetype jks -storepass "$password" -keypass "$password"
您在另一条评论中告诉我们这有效:
keytool -genkey -noprompt \
-keyalg RSA \
-storetype pkcs12 \
-alias server.example.com \
-dname 'CN=server.example.com,O=COMPANY,OU=COMPANY,L=NY,ST=NY,C=US' \
-ext "SAN=DNS:example.com, DNS:example2.com" \
-keystore server.example.com.keystore.jks \
-storepass 'passwort!#' \
-keypass 'passwort!#'
如果上面的第二个带有硬编码值的脚本有效,那么这个使用变量的脚本也必须有效,我们稍后将从脚本参数填充选项:
#!/usr/bin/env bash
the_alias='server.example.com'
the_dname='CN=server.example.com,O=COMPANY,OU=COMPANY,L=NY,ST=NY,C=US'
the_keystore='server.example.com.keystore.jks'
the_pass='passwort!#'
keytool -genkey -noprompt \
-keyalg RSA \
-storetype pkcs12 \
-alias "$the_alias" \
-dname "$the_dname" \
-ext 'SAN=DNS:example.com, DNS:example2.com' \
-keystore "$the_keystore" \
-storepass "$the_pass" \
-keypass "$the_pass"
如果这可行,那么我们只需要映射在不起作用的命令中用作选项的值(从您的问题中复制并每行布置一个,以便与我正在使用的其他脚本进行比较,并修复了缺失的转义):
keytool -genkey -noprompt \
-keyalg RSA \
-storetype pkcs12 \
-alias $1.$2 \
-dname $1'.'$2',O=COMPANY,OU=COMPANY,L=NY,ST=NY,C=us' \
-ext 'SAN=DNS:example1.com,DNS:example2.com' \
-keystore $1.$2'.keystore2.jks' \
-storepass $3 \
-keypass $3
要填充我们从传递给脚本的参数中引入的变量,而不是对它们进行硬编码,这必须有效:
#!/usr/bin/env bash
the_alias="$1.$2"
the_dname="CN=${the_alias},O=COMPANY,OU=COMPANY,L=NY,ST=NY,C=us"
the_keystore="${the_alias}.keystore.jks"
the_pass="$3"
keytool -genkey -noprompt \
-keyalg RSA \
-storetype pkcs12 \
-alias "$the_alias" \
-dname "$the_dname" \
-ext 'SAN=DNS:example.com, DNS:example2.com' \
-keystore "$the_keystore" \
-storepass "$the_pass" \
-keypass "$the_pass"
其中,您将上述内容称为:
./the_script 'server' 'example.com' 'passwort!#'
那么 - 这行不通?如果没有,我提供的上述 2 个脚本中哪一个失败了?
在进行编码时,我注意到,除了失败脚本中缺少引号和行尾缺少的反斜杠之外:-ext
- 你说有效的代码版本使用,而你说的版本不起作用使用(注意
keystore.jks
keystore2.jks
2
) - 同样,对于 vs(注意
的 )。
SAN=DNS:example.com
SAN=DNS:example1.com
1
- 后面的空白字符仅存在于工作选项字符串中。
,
-ext
- 工作脚本中的选项将启动
而在失败的那个中,它没有。
-dname
CN=
这些都有问题吗?
评论
1赞
Husker
11/10/2023
太好了,现在它起作用了,我一定在不断编辑过程中丢失了 DN。非常感谢您的详细回复。
评论
*
?
[...]
!
可以在 Bash 中触发历史扩展(这是您正在使用的,即使您的脚本不需要 bash 并且可以正常工作)sh
set -x
bash -x SCRIPTNAME ...
-ext 'SAN=DNS:example1.com,DNS:example2.com'
-keystore $1.$2'.keystore2.jks' -storepass $3 -keypass $3