需要简化更新文件

时间:2014-05-14 09:09:06

标签: bash awk

我有一个脚本可以测试服务器是否已启动并正在运行,如果向下写入日志文件中的多长时间 脚本工作正常,但我喜欢写更少的写作来加快速度 就像现在一样,它为每个测试的服务器编写完整的日志文件 可以将信息存储在某个变量或数组中,然后写入一次。

#!/bin/bash

STATUS="/usr/local/server.info"
LOG="/var/log/servers_up_log"

# What server to monitor
SRV=(SR1 SR2 SR3)

# Test if log file exists, if not create it.
if [[ ! -f "$LOG" ]]; then
    >"$LOG"
fi      

for UC in ${SRV[*]}; do

    # Test if server is already in log, if not add it.
    if ! grep -q $UC "$LOG" ; then
        echo "$UC|0" >> "$LOG"
    fi

    isup=$(awk -F\| '$1==test {if ($2~/connected/) print "1"; else print "0"}' test="$UC" "$STATUS")

    if [[ $isup = 1 ]]; then
        #if server is up, add "0" to log file
        awk -F\| '$1==test {$2=0}1' OFS=\| test="$UC" "$LOG" > tmp && mv tmp "$LOG"
        else
        #if server is down for first time update log file
        if [[ $(awk -F\| '$1==test {print ($2==0?0:1)}' test="$UC" "$LOG") = 0 ]]; then
            awk -F\| '$1==test {$2=date}1' OFS=\| test="$UC" date="$(date +"%Y/%m/%d %T")" "$LOG" > tmp && mv tmp "$LOG"
        fi

    fi

done

STATUS是保存服务信息的文件 LOG是写入状态的文件,它看起来像这样:

SR1|0
SR2|2014/05/12 20:25:05
SR3|0

如果其0启动并运行。日期显示何时下降

SRV数组不是这样的,它是从文件中读取的动态数量的服务器 我刚刚添加了三台服务器来查看该程序的样子。


所以程序就是这样的:
测试LOG文件是否存在,如果不存在空文件。

然后为SRV中的每个服务器:
查看它是否在LOG文件中,如果没有,请添加0,服务器向上。
然后在STATUS文件中查看是否已连接

如果已连接,请将LOG文件中的服务器标记设置为0
如果未连接,请将LOG文件中服务器的标志设置为日期,
但仅限于之前的0,以防止更新日期。

正如您在awk部分中看到的那样:

$1==test {$2=0}1

它为每个服务器写入整个LOG文件,因此对于许多服务器,它会多次写入LOG文件。而且不仅每次运行一次脚本。

2 个答案:

答案 0 :(得分:0)

使用use-array-variable-in-awk中的提示。我只显示了我修改过的脚本部分:

if [[ $isup = 1 ]]; then
    #if server is up, add "0" to log file
    #awk -F\| '$1==test {$2=0}1' OFS=\| test="$UC" "$LOG" > tmp && mv tmp "$LOG"
    keys+=($UC); values+=(0)  # storing the server name and the value to be stored in arrays
else
    #if server is down for first time update log file
    if [[ $(awk -F\| '$1==test {print ($2==0?0:1)}' test="$UC" "$LOG") = 0 ]]; then
        #awk -F\| '$1==test {$2=date}1' OFS=\| test="$UC" date="$(date +"%Y/%m/%d %T")" "$LOG" > tmp && mv tmp "$LOG"
        keys+=($UC); values+=(1) 
    fi
fi

然后在for循环之后添加这个awk命令:

awk -v ks="${keys[*]}" -v vs="${values[*]}" -v date="$(date +"%Y/%m/%d %T")" '
    BEGIN{ split(ks, keys, / /); split(vs, values, / /);
    FS="|"; OFS="|"; }
    {
        for (i in keys) {
            if(keys[i] == $1) { $2 = values[i]; break; }
        };
        if ($2 == 1) { $2 = date }
    }
    1
' $LOG > tmp && mv tmp $LOG

因此,我们创建了两个数组keysvalueskeys存储服务器名称,values存储我们要针对这些服务器写入的值。在最后的awk命令中,我们从bash数组创建awk数组。有关解释,请参阅use-array-variable-in-awk

这里的一个问题是values不能有空格,我们的日期格式有一个空格。我使用了一个简单的“1”来表示该值必须是一个日期,然后用新的awk命令中的日期值替换。

awk中的for循环只是遍历keys数组,如果此数组中的servername与$1匹配,则它使用当前索引从values中查找相应的值阵列。此外,如果值为“1”,我们使用日期值。

答案 1 :(得分:0)

我这样做:

awk -v date="$(date +"%Y/%m/%d %T")" -v srv="${SRV[@]}" '
BEGIN {
    FS=OFS="|"
    split(srv,srvArr,/ /)
}
NR==FNR {
    for (i=1; i in srvArr; i++) {
        if ($1 == srvArr[i]) {
            prevStatus[i] = $2
        }
    }
    next
}
{
    for (i=1; i in srvArr; i++) {
        if ($1 == srvArr[i]) {
            currStatus[i] = $2
        }
    }
}
END {
    for (i=1; i in srvArr; i++) {
        # Test prev and curr status arrays and print
        # whatever you need to for each combination.
        prev = prevStatus[i]
        curr = currStatus[i]
        if (prev == "") {
            if (curr == "") {
            }
            else if (curr == "connected") {
            }
            else {
            }
        }
        else if (prev == "connected") {
           etc...
        }
    }
}
' "$LOG" "$STATUS" > tmp && mv tmp "$LOG"

改变"已连接"如果/在适当的时候为1。必要时使用日期变量。如果你需要附加到日志文件而不是覆盖它,请附加tmp而不是mv-ing等等。