循环通过While read分隔shell脚本中的字符串



我有一个名为test的json文件。我想解析id, name和not_after的值,然后放入条件来验证not_after不应该超过60天。

vi test.json

{
"id" : 10001,
"name" : "Test Client Name",
"type" : "PKCS12",
"provider" : "SunJSSE",
"password" : "1111111",
"url" : "data:application/xxxx-xxx,1234567890987",
"entry" : [ {
"alias" : "example.com,
"type" : "PrivateKeyEntry",
"algorithm" : "EC",
"subject" : "C=CA, ST=ON, L=Toronto, O=Techonology, OU=example, CN=example.com",
"issuer" : "C=US, O=example Lab, CN=ExampleCA",
"not_before" : "Fri, 21 Aug 2020 19:44:26 GMT",
"not_after" : "Sun, 21 Aug 2022 19:44:26 GMT",
"tn_auth_list" : [ {
"spc" : "AA001"
} ]
} ],
"created_date" : "Thu, 20 Aug 2020 04:38:16 GMT"
}{
"id" : 10002,
"name" : "client-02",
"type" : "PKCS12",
"provider" : "SunJSSE",
"password" : "1111111",
"url" : "data:application/xxxx-xxx,1234567890987",
"customer_id" : 12002,
"entry" : [ {
"alias" : "example.com",
"type" : "PrivateKeyEntry",
"algorithm" : "EC",
"subject" : "C=US, ST=CA, L=San Ramon, O=Five9, OU=example, CN=example.com",
"issuer" : "C=US, O=example Lab, CN=ExampleCA",
"not_before" : "Tue, 2 Jun 2020 12:15:36 GMT",
"not_after" : "Thu, 2 Jun 2022 12:15:36 GMT",
"tn_auth_list" : [ {
"spc" : "ZZ001"
} ]
} ],
"created_date" : "Mon, 14 Dec 2020 21:42:35 GMT"
}
如果只给出.entry[],则jq的输出不能被认为是一个字符串,因此条件不能正常工作。我可以得到完美的not_after输出。需要一些帮助,while read不应该破坏names字符串,它应该考虑名称作为单个字符串。
cat test.json | jq -r '.name, .entry[].not_after' | while read name expirydate; do
echo certname=$name
echo expiryday=$expirydate
not_after="${expirydate}"
echo expirydate=$not_after
condition=$(( $(date +%s) + $((60*24*60*60)) ))
echo condition=$condition
not_after_in_seconds=$(date -d "$not_after" +%s)
# echo not_after_in_seconds: $not_after_in_seconds
# echo not_after_in_date: $(date -d @$not_after_in_seconds)
if [ $condition -ge $not_after_in_seconds ]
then
echo Certificate name : $certname will be expire in 60 days, Expiration Date = $not_after
else
echo No issues for 60 days
fi
done

输出:

certname=Test
expiryday=Client Name
expirydate=Client Name
condition=1661241563
date: invalid date 'Client Name'
./dummy.sh: line 15: [: 1661241563: unary operator expected
No issues for 60 days
certname=Sun,
expiryday=21 Aug 2022 19:44:26 GMT
expirydate=21 Aug 2022 19:44:26 GMT
condition=1661241563
Certificate name : will be expire in 60 days, Expiration Date = 21 Aug 2022 19:44:26 GMT
certname=client-02
expiryday=
expirydate=
condition=1661241563
Certificate name : will be expire in 60 days, Expiration Date =
certname=Thu,
expiryday=2 Jun 2022 12:15:36 GMT
expirydate=2 Jun 2022 12:15:36 GMT
condition=1661241563
Certificate name : will be expire in 60 days, Expiration Date = 2 Jun 2022 12:15:36 GMT

预期输出:

Certificate name : Test Client Name will be expire in 60 days, Expiration Date = 21 Aug 2022 19:44:26 GMT
Certificate name : client-02 will be expire in 60 days, Expiration Date = 2 Jun 2022 12:15:36 GMT

我们可以使用| @sh引用JSON数组供shell计算:

jq -r '[.name, .entry[].not_after ] | @sh' test.json

给:

'Test Client Name' 'Sun, 21 Aug 2022 19:44:26 GMT'
'client-02' 'Thu, 2 Jun 2022 12:15:36 GMT'

现在我们有一个包含四个独立单词的列表。我们可以使用eval将其存储在bash数组中。

示例脚本:

#!/bin/bash
eval "a=($(jq -r '[.name, .entry[].not_after ] | @sh'))"
for ((i=0; i<${#a[@]}; i+=2)); do
name=${a[i]} expiry=${a[i+1]}
expiry_epoch=$(date -d "$expiry" +%s)
now_epoch=$(date +%s)
days_left=$(( (expiry_epoch - now_epoch) / 86400 ))
if ((days_left == 0)); then
echo "$name: warning: expires today"
elif ((days_left < 0)); then
echo "$name: EXPIRED $((days_left*-1)) days ago"
elif ((days_left < 60)); then
echo "$name: warning: expires in $days_left" days
else
echo "$name: $days_left days left"
fi
done

使用如:expiry-script < test.json

正确计算剩余天数并不总是那么简单。这个脚本截断了当前的日期(即日期)。4.9天变成4天)。这可能是理想的,但如果时区有夏令时,每年一个小时也是错误的。夏时制导致一天有23小时,这意味着一天在不应该被截断的时候被截断了。

另一种不存在这个问题的方法是四舍五入到最近的一天:

printf -v days_left %.0f 
"$(echo "scale=1; ($expiry_epoch - $now_epoch)/86400" | bc)"

这是一个不同的方法。四舍五入可以避免DST问题。

相关内容

  • 没有找到相关文章

最新更新