如何在 while 循环中获取两个日期之间的“天数”。收到无效日期错误

如何在 while 循环中获取两个日期之间的“天数”。收到无效日期错误

我正在尝试获取 2 个日期之间的天数,如果证书在 30 天内过期,则需要发送通知电子邮件。 EndDate 我从美国东部时间 (EST 2022 年 8 月 18 日星期四 18:59:59 EST 2022) 的 .csv 文件调用。

文件sample3.csv包含:

$ cat sample3.csv
CertName,StartDate,EndDate
sslcertificates,Thu Dec 17 19:00:00 EST 2020,Thu Aug 18 18:59:59 EST 2022

我收到类似 /bin/date 的错误:无效日期。有人可以帮忙吗?我是脚本新手。

#! /bin/bash
set +x
date=`/bin/date`
TodayDateSec="$(/bin/date "+%s")"
while IFS=, read -r CertName StartDate EndDate;
do
        if [ -z "$EndDate" ]; then
                echo "$EndDate details not exists"
        else
                echo "Name: $Name; StartDate: $StartDate; EndDate: $EndDate";
                date=`/bin/date`
                EndDateSec="$(/bin/date -d "$EndDate" +'%s')";
                DiffDays="$(( ( EndDateSec - TodayDateSec )/86400 ))"
                echo "***********$DiffDays************"
        if [[ "$DiffDays" -lt 30 ]]; then
                echo "Certificate is going to expire in $DiffDays. Please take required action"

        fi
    fi
done < sample3.csv

下面是输出:

Name: CertName; StartDate: StartDate; EndDate: EndDate
/bin/date: invalid date ‘EndDate’
***********-19195************
Certificate is going to expire in -19195. Please take required action Name: sslcertificates; StartDate: Thu Dec 17 19:00:00 EST 2020; EndDate: Thu Aug 18 18:59:59 EST 2022
/bin/date: invalid date ‘Thu Aug 18 18:59:59 EST 2022’
***********-19195************
Certificate is going to expire in -19195. Please take required action 

答案1

请修改您的脚本以包含一些(简单的)数据有效性检查。命令 date 很可能无法正确理解您正在使用的日期格式。这可能是由多种原因造成的。如果您可以将日期格式化为“2022-08-18T18:59:59”,那么它将更加便携并且更容易被其他程序处理。

#! /bin/bash
set +x

TodayDateSec="$(/bin/date "+%s")"

while IFS=, read -r CertName StartDate EndDate; do
        if [ -z "$EndDate" ]; then
                echo "$EndDate details not exists"
        elif ! /bin/date -d "$EndDate" >/dev/null 2>&1; do
                echo "Invalid date format supplied $EndDate"
        elif 
                EndDateSec="$(/bin/date -d "$EndDate" +'%s')";
                DiffDays="$(( ( EndDateSec - TodayDateSec )/86400 ))"
                echo "***********$DiffDays************"
                if [[ "$DiffDays" -lt 30 ]]; then
                        echo "Certificate is going to expire in $DiffDays. Please take required action"
                fi
        fi
done < sample3.csv

如果您使用的日期格式与date您拥有的命令(或您使用的区域设置)不兼容,您可以尝试使用datefrom busybox

$ busybox date -D '%a %b %d %T %Z %Y' -d 'Thu Aug 18 18:59:59 EST 2022' +'%s'

1660863599

答案2

使用 shell 循环处理文本是一种反模式,请参阅为什么使用 shell 循环处理文本被认为是不好的做法?,以下是如何使用 GNU awk 时间函数更有效地完成脚本正在执行的操作:

$ cat tst.sh
#!/usr/bin/env bash

awk '
    BEGIN {
        FS=","
        secsInDay = 60 * 60 * 24
        curDate = strftime("%Y %m %d")
        secs = mktime(today " 12 0 0")
        today = int( systime() / secsInDay )
    }
    NR == 1 {
        next
    }
    $3 == "" {
        printf "EndDate details not exists\n"
        next
    }
    {
        printf "Name: %s; StartDate: %s; EndDate: %s\n", $1, $2, $3
        split($3,d," ")
        mthNr = (index("JanFebMarAprMayJunJulAugSepOctNocDec",d[2])+2)/3
        secs = mktime(d[6] " " mthNr " " d[3] " 12 0 0")
        endDay = int( secs / secsInDay )
        diffDays = endDay - today
        printf "***********%d************\n", diffDays
    }
    diffDays < 30 {
        printf "Certificate is going to expire in %d days. Please take required action\n", diffDays
    }
' "${@:--}"

尽管这是完成现有脚本正在执行的操作的更好方法,但生成这样的输出的脚本并不是您的完整任务的良好起点if certificate expires in 30 days need to send an notification email.。接受此问题的答案后,提出一个新问题以获得有关如何执行此操作的帮助。

相关内容