【问题标题】:shell Script NO lines are append from input file using time stamp使用时间戳从输入文件追加 shell 脚本 NO 行
【发布时间】:2020-04-09 13:29:38
【问题描述】:

输入文件是/var/log/error.log

 Apr 7 05:58:05 ip-172-31-19-169 kernel: BIOS-provided physical RAM map: critical     
 Apr 7 09:21:12 ip-172-31-19-169 kernel: BIOS-provided physical RAM map: critical     
 Apr 7 13:05:57 ip-172-31-19-169 kernel: BIOS-provided physical RAM map: critical

我的脚本

#!/bin/ksh

d1=$(date --date="-50 min" "+%b %_d %H:%M")

d2=$(date "+%b %_d %H:%M")

while read line; do

    [[ $line > $d1 && $line < $d2 || $line =~ $d2 ]] && echo $line | egrep -wi '[Cc]ritical' >> /mnt/dinesh/ksh-scripts/draft/text.txt

done < /var/log/error.log

在运行我的脚本时,系统时间大约是13:06:05

所以根据脚本,/mnt/dinesh/ksh-scripts/draft/text.txt 文件应该有我的error.log 的最后一个条目,但是mnt/dinesh/ksh-scripts/draft/text.txt 中没有附加任何行。

谁能帮我解决这个问题。

【问题讨论】:

  • 欢迎来到 SO。正确的问题格式将帮助您获得答案。对于代码,您可以使用编辑器中的 {} 图标。确保阅读编辑器中的可用帮助。我为你做了,第一个是免费的 :-)
  • 你做了什么调试?前任。在您的行内,您是否尝试仅使用echo $line?删除 grep,您将看到是否有任何一行。然后添加 grep,看看你是否得到 [Cc]ritical 行,...这将允许你调试你的 [[ ]] 条件。
  • @Nic3500。感谢您对我的问题进行更改。是的,我已经删除了 grep,只是使用 echo $line 来检查输出。但是,输出仍然是空的
  • 我修复了这些问题。 1. 在输入文件中。当前系统日期未修改。

标签: linux bash shell ksh


【解决方案1】:

代码逻辑的根本问题是使用字符串比较来比较日期。在字符串比较中,Apr 17 小于 Apr 2 并且 Feb 1 小于 Jan 1

相反,POSIX shell 中的模式是将日期转换为自 1970-01-01 00:00:00 UTC 以来的秒数,也称为“纪元”。

对于date 命令,以这种秒格式给出时间的方法是将FORMAT 设置为+%s,例如date +%s

ksh 中有一个printf 格式说明符T,用于将字符串(例如从日志文件中读取的行)转换为自纪元以来的秒数。见https://www.unix.com/302701867-post4.html?s=860f6c21431fa69ef9e083161f93739d

这是您重写的脚本,通过将比较转换为秒来解决逻辑错误:

#!/bin/ksh
ERROR_LOG=/tmp/error.log
FILTERED_ERROR_LOG=/tmp/text

now_secs=$(date "+%s")
start_secs=$(date --date="-30000 min" +%s)

while read line; do
    # Below stderr is redirected since I can't figure out how to get just the first part
    # of the date parsed skipping the other stuff after that.
    # Even though there is warning printed, the time comes out parsed correctly
    line_secs=$(printf "%(%#)T" "$line" 2>/dev/null)

    if (( $line_secs > $start_secs && line_secs < now_secs || line_secs == now_secs )); then
        echo $line | egrep -wi '[Cc]ritical' >> $FILTERED_ERROR_LOG
    fi
done < $ERROR_LOG

一些附加说明。

您似乎更广泛地可能希望了解此类调试此类问题。如您所见,在 StackOverflow 上询问这样一个非常具体的问题可能不会引起其他人的兴趣,因此可能需要一段时间才能得到任何有意义的响应。

基本跟踪选项是-x。让我们在上面的脚本上运行它:

ksh -x /tmp/bug.ksh
+ ERROR_LOG=/tmp/error.log
+ FILTERED_ERROR_LOG=/tmp/text
+ date +%s
+ now_secs=1587473181
+ date '--date=-30000 min' +%s
+ start_secs=1585673181
+ 0< /tmp/error.log
+ read line
+ printf '%(%#)T' 'Apr 7 05:58:05 ip-172-31-19-169 kernel: BIOS-provided physical RAM map: critical'
+ 2> /dev/null
+ line_secs=1586253485
+ (( 1586253485 > 1585673181 && line_secs < now_secs || line_secs == now_secs ))
+ egrep -wi '[Cc]ritical'
+ echo Apr 7 05:58:05 ip-172-31-19-169 kernel: BIOS-provided physical RAM map: critical
+ 1>> /tmp/text
+ read line
+ printf '%(%#)T' 'Apr 7 09:21:12 ip-172-31-19-169 kernel: BIOS-provided physical RAM map: critical'
+ 2> /dev/null
+ line_secs=1586265672
+ (( 1586265672 > 1585673181 && line_secs < now_secs || line_secs == now_secs ))
+ egrep -wi '[Cc]ritical'
+ echo Apr 7 09:21:12 ip-172-31-19-169 kernel: BIOS-provided physical RAM map: critical
+ 1>> /tmp/text
+ read line
+ printf '%(%#)T' 'Apr 7 13:05:57 ip-172-31-19-169 kernel: BIOS-provided physical RAM map: critical'
+ 2> /dev/null
+ line_secs=1586279157
+ (( 1586279157 > 1585673181 && line_secs < now_secs || line_secs == now_secs ))
+ egrep -wi '[Cc]ritical'
+ echo Apr 7 13:05:57 ip-172-31-19-169 kernel: BIOS-provided physical RAM map: critical
+ 1>> /tmp/text
+ read line

我以几种方式更改了您的代码,以便更容易调试和查看问题。将您想做的事情附加到日志文件中,作为if 中的单独语句而不是&amp;&amp; 条件的一部分,在类似上面的跟踪中,您会看到它显示为单独的线。特别是当你看到:

+ egrep -wi '[Cc]ritical'
+ echo Apr 7 05:58:05 ip-172-31-19-169 kernel: BIOS-provided physical RAM map: critical

我们知道测试成功了。如果您想知道时间测试是否因为第一部分(时间不够新)或第二部分(时间太新)或与第三部分不匹配(现在时间)而失败,那么将这些放入他们自己的ifelse 将允许跟踪显示。

但是我已经做了一些其他的事情来简化调试。虽然 使用(( $line_secs &gt; $start_secs )) ksh 之类的构造会发出警告:

/tmp/bug.ksh: warning: line 14: variable expansion makes arithmetic evaluation less efficient

因为它更喜欢更有效的(( line_secs &gt; start_secs )),所以通过使用$ 添加额外的替换,您将在跟踪中看到比较的值。这可能会帮助您找出哪个部分失败了。

如果您已经知道这一点并尝试过,那么我认为如果您带着如上所示的跟踪来到 StackOverflow,您会得到更多的回应,然后问题会缩小到“为什么这个比较失败? "并且您可能会更快地获得更多回复。

最后,我要提到的是,我已经为比 2014-12-24、zshbash 更新的现代 ksh93 编写了调试器。但是,当我在 kshdb 上尝试上述示例时,它失败了,我不知道为什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-26
    • 1970-01-01
    • 2011-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多