简体   繁体   English

Bash脚本中的时间变量

[英]Time Variables in Bash Scripting

If I have 3 different scripts to run at various times each time a file is written to, how would a bash script be written to run a specific script only at a specific time. 如果每次有3个不同的脚本在每次写入文件时都在不同的时间运行,那么如何编写bash脚本以仅在特定的时间运行特定的脚本。 This is not as simple as a cron job (though cron could probably swap out the .sh file based on time), I am looking for the time variables. 这并不像cron作业那么简单(尽管cron可能会根据时间交换出.sh文件),但我正在寻找时间变量。

For instance: 例如:

If 9am-11:30 am run scriptA.sh if file.txt is changed. 
If 11:30am-5:45pm run scriptB.sh if file is changed.
If 5:46pm-8:59am run scriptC.sh if file is changed.

I asked a similar question but I don't think I was clear enough about the variables I am seeking or how to define them.. 我问了类似的问题,但我对所要查找的变量或如何定义它们的了解不够清楚。

I see there are two issues. 我看到有两个问题。 1, how to determine if the current hour is within a particular range. 1,如何确定当前小时是否在特定范围内。 2, how to determine if a file has been modified, recently. 2,如何确定文件是否最近被修改。

Here's how I would approach that: 这是我的处理方式:

#!/bin/bash

now=$( date +%s )
current_hour=$( date +%H )
file_mod=$( ls -l --time-style=+%s file.txt | awk '{print $(NF-1)}' )
file_age=$(( $now - $file_mod ))

if [[ $current_hour -gt 9 ]] && \
   [[ $current_hour -lt 11 ]] && \
   [[ $file_age -lt 3600 ]]
then
    ./scriptA.sh
fi

Here I'm using the bash operators for numeric comparison: -gt, -lt 在这里,我使用bash运算符进行数字比较:-gt,-lt

For greater granularity with time, you would need to compute the amount of time since midnight. 为了获得更精细的时间,您需要计算自午夜以来的时间。 Perhaps something like: 也许像这样:

hour=$( date +%H )
min=$( date +%M )
minutes=$( echo "( 60 * $hour ) + $min" | bc -l )

eleven_thirty=$( echo "( 60 * 11 ) + 30" | bc -l )

The traditional tool for comparing time stamps to determine whether work needs to be performed or not is make . 比较时间戳来确定是否需要工作,进行或不进行传统的工具是make Its default behavior is to calculate a dependency chain for the specified target(s) and determine whether any of the dependent files have changed; 它的默认行为是为指定目标计算一个依赖链,并确定是否有任何依赖文件已更改。 if not, the target does not need to be remade. 如果不是,则不需要重新设定目标。 This is a great tool for avoiding recompilation, but it easily extends to other tasks. 这是避免重新编译的好工具,但很容易扩展到其他任务。

In concrete terms, you'd create a flag file (say, .made ) and specify it as dependent on your file . .made ,您将创建一个标志文件(例如.made )并将其指定为依赖于您的file Now, if file has changed, .made needs to be recreated, and so make will run the commands you specify to do so. 现在,如果file已更改, .made需要重新创建.made ,因此make将运行您指定的命令。 In this scenario, we would run a simple piece of shell script, then touch .made to communicate the latest (successful) run time to future runs. 在这种情况下,我们将运行一个简单的Shell脚本,然后touch .made以将最新的(成功的)运行时间传达给将来的运行。

What remains is for the recipe to run different commands at different times. 剩下的是配方可以在不同的时间运行不同的命令。 My approach to that would be a simple case statement. 我的解决方法是简单的case陈述。 Notice that make interprets dollar signs, so we need to double those dollar signs which should be passed through to the shell. 注意, make解释美元符号,因此我们需要将应传递给外壳的美元符号加倍。

.made: file
    case $$(date +%H:%M) in \
        09:* | 10:* | 11:[0-2]? ) \
            scriptA.sh ;; \
        11:[3-5]? | 1[2-6]:* | 17:[0-3]? | 17:4[0-5]) \
            scriptB.sh;; \
        17:4[6-9] | 17:5? | 1[89]:* | 2?:* | 0[0-8]:* ) \
            scriptC.sh;; \
    esac
    touch $@   # $@ expands to the current target

The entire case statement needs to be passed as a single logical line to the shell, so we end up with those pesky backslashes to escape the newlines. 整个case语句需要作为一条逻辑行传递到shell,因此我们以那些讨厌的反斜杠结束以换行。

Also notice that make is picky about indentation; 还要注意, make对于缩进很挑剔; each (logical) line in the recipe should be preceded by a literal tab character. 配方中的每一行(逻辑行)都应以文字制表符开头。

The default behavior of make is to run the first target in the file; make的默认行为是运行文件中的第一个目标。 this Makefile only contains one target, so make is equivalent to make .made . Makefile仅包含一个目标,因此make等同于make .made

Also notice that make cares about exit codes; 还要注意, make有关退出代码的烦恼; if scriptA , scriptB , or scriptC could exit with a non-zero exit status, that is regarded by make as a fatal error, and the .made file will not be updated. 如果scriptAscriptBscriptC可以以非零退出状态退出(被make视为致命错误),并且.made文件将不会更新。 (You can easily guard against this , though.) (不过,您可以轻松地对此加以防范 。)

Well, since Bash variables can store string or integer only, "date" variables are just a string manipulations, like example below: 好吧,由于Bash变量只能存储stringinteger ,因此“ date”变量只是字符串操作,如以下示例所示:

hours=`date +%H`
minutes=`date +%M`
sum=$(($hours + $minutes))
digit=`echo $sum | sed -e 's/\(^.*\)\(.$\)/\2/'` # counts total digits

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM