【问题标题】:Bash: How can I subtract two time strings using bash?Bash:如何使用 bash 减去两个时间字符串?
【发布时间】:2014-05-19 16:00:53
【问题描述】:

我已经编写了下一个脚本来查找锁定文件的年龄:

#!/bin/bash
now=`date +"%T"`
lock="aggregator.lock"
find . -name $lock -type f
if [ $? != 0 ];
        then
        exit
else
ls -ltrh $lock 2&>/dev/null
fi
if [ $? != 0 ];
        then
        locktime=`ls -ltrh aggregator.lock |awk -F" " '{print $7}'`
else
echo "File not found"
fi

我有两个问题:

  • ls -ltrh aggregator.lock |awk -F" " '{print $7}' 的输出 以 HH:MM 格式而不是 HH:MM:SS 格式给我时间和输出 date +"%T" 以 HH:MM:SS 格式给我时间(根据需要),所以 如何以秒为单位获取文件的修改时间?
  • 我不知道如何在时间之间进行减法...我想做类似$now - $locktime 的操作,以便获得两个变量之间的秒数增量,怎么做?

编辑: 脚本的意思是查找锁定文件存在多长时间... 有这个脚本:

device0="/home/build/aggregator/scripts/aggregator.lock"
if [ -e "$device0" ]
then
echo process is allready running
else

touch $device0
java -Xms6g  -Xmx6g -jar /home/build/aggregator/aggregator-1.0-SNAPSHOT-jar-with-dependencies.jar
rm $device0
fi

创建锁定文件...创建锁定文件的唯一目的是告诉我脚本的运行时间有多长,只是认为也需要此信息,因为我不是查找自上次修改文件以来经过了多长时间。

提前致谢

【问题讨论】:

  • 我根据您的编辑编辑了我的答案。 HTH。

标签: bash shell


【解决方案1】:

要了解文件上次修改的时间,您可以使用

stat -c %Y file 

拥有自the epoch以来时间的最后修改日期,以秒为单位,并且

date +%s 

以相同单位表示当前日期。然后简单地用$(( ... )) 减去它们将为您提供自上次修改文件以来经过的秒数。请注意,Unix 文件系统通常不存储创建日期,仅存储上次访问/更改/修改日期。

要转换回人类可读的格式,请参阅https://stackoverflow.com/a/12199798/2907484

所以基本上:

now=$(date +%s)                          
was=$(stat -c%Y file)      
elapsed=$((now - was))
days=$((elapsed/86400))
hours=$(( (elapsed-days*86400)/3600 ))   
mins=$(( (elapsed-days*86400 - hours*3600)/60 ))
secs=$(( elapsed - days*86400 - hours*3600 - mins*60 )) 

现在您可以根据需要使用echoprintf 格式化输出

printf '%02dd:%02dh:%02dm:%02ds\n' $days $hours $mins $secs

会输出

00d:18h:42m:27s

%02d 格式可能不太适合几天 --- 但你明白了。您也可以轻松添加数周、数年或其他任何内容。

要查看脚本/程序运行的时间,您可以使用 bash 内置命令 time 或实用程序 /usr/bin/time (be sure to not confound them),或者您可以按照此脚本中的想法使用:

was=$(date +%s)
...run your script...
now=$(date +%s) 

并继续如上。

【讨论】:

  • 很好,然后我可以使用expr 进行减法,但是我将如何获得人类可读格式的答案?
  • 不要将expr 用于数学,使用$(())。没有人再使用expr,它的语法很糟糕,而且由于它分叉了一个单独的进程,可能会导致性能问题。
【解决方案2】:

如果你有stat(它是 GNU coreutils 包的一部分,所以你应该在任何 GNU/linux 系统上找到它),那么你可以直接以秒为单位获得文件的修改时间:

stat -c%Y aggregator.lock

请咨询man stat,获取有关文件的完整数据列表,以及相应的格式 (-c) 代码。

这让你可以简单地写,例如:

elapsed=$(( $(date +%s) - $(stat -c%Y aggregator.lock) ))

$(( ... )) 是算术扩展的 bash 语法,请参阅 man bash

【讨论】:

    【解决方案3】:

    如果您需要进行算术运算,最好使用 Unix 时间戳(自 1970 年 1 月 1 日以来经过的秒数)。使用 GNU date 的示例,但可以使用其他版本实现相同的想法。

    now=$(date +%s)
    locktime=$(date +%s --date 13:50:32)
    diff=$(( now - lock time ))
    

    另外,如果可能,最好使用stat 来获取锁定文件的修改时间。

    【讨论】:

      【解决方案4】:

      你可以让find立即输出时间戳,所以试试这样:

      locktime=$(find -maxdepth 1 -name aggregator.lock -printf '%T@')
      now=$(date +%s)
      delta=$(($now - $locktime))
      printf "The file was modified %.0f seconds ago" $delta
      

      【讨论】:

      • 谢谢,我怎样才能以人类可读的格式显示增量?
      • locktime=$(find -maxdepth 1 -name aggregator.lock -printf '%T@') 的输出是 1400166241.0000000000 而不是 1400166241 ,如何解决?
      • @ItaiGanot:现在进行四舍五入
      • 谢谢@Wolph,我要到周日才能检查,我会检查并通知您。
      【解决方案5】:

      我已经编辑了我的脚本,这里是:

      #!/bin/bash
      #file="/home/build/aggregator/scripts/aggregator.lock"
      file="$1"
      
      if [ -e "$file" ]; then 
          now=$(date +%s)                          
          was=$(stat -c%Y $file) 
          elapsed=$((now - was))
          echo $elapsed 
      else
          echo 0
      fi
      

      然后我可以从 Zabbix 运行脚本并获取文件存在的秒数,如果文件不存在,则为“0”:

      [root@zabbix ~]# zabbix_get -s 10.200.X.X -k check.lock[/home/build/aggregator/scripts/aggregator.lock]
      14
      [root@zabbix ~]#
      

      感谢大家的解决方案。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-07
        • 1970-01-01
        • 2013-08-29
        • 2017-06-17
        • 2012-01-13
        • 1970-01-01
        • 2020-10-15
        • 1970-01-01
        相关资源
        最近更新 更多