【问题标题】:Why range of my variable is limited into "tail -f scope"?为什么我的变量范围仅限于“tail -f 范围”?
【发布时间】:2017-10-25 23:58:15
【问题描述】:

我有注册在线或离线状态的应用程序,它存储在我的 test.log 文件中。状态可以每秒或每分钟更改一次,或者在许多小时内都可以更改。每 15 分钟一次,我需要将实际状态发送到外部机器 [my.ip.address]。在下面的示例中,假设我只需要回显实际状态。

我写了下面的脚本,它正在监视我的 test.log 并将 实际状态存储在 FLAG 变量中。但是我无法将其发送(或回显)到我的外部机器 [my.ip.address],因为 FLAG 未正确保存。 你知道下面的例子有什么问题吗?

#!/usr/bin/env bash

FLAG="OffLine"
FLAG_tmp=$FLAG

tail -f /my/path/test.log | while read line
do
    if [[ $line == *"OnLine"* ]]; then
        FLAG_tmp="OnLine"
    fi

    if [[ $line == *"OffLine"* ]]; then
        FLAG_tmp="OffLine"
    fi

    if [ "$FLAG" != "$FLAG_tmp" ];then
        FLAG=$FLAG_tmp
        echo $FLAG      # it works, now FLAG stores actual true status
    fi

done &

# till this line I suppose that everything went well but here (I mean out of
# tail -f scope) $FLAG stores only OffLine - even if I change it to OnLine 4 lines before.

while :
do
    #(echo $FLAG > /dev/udp/[my.ip.address]/[port])
    echo "$FLAG"     # for debug purpose - just echo actual status. 
                    # However it is always OffLine! WHY?
    #sleep 15*60    # wait 15 minutes
    sleep 2         # for debug, wait only 2 sec
done

编辑: 谢谢大家的回答,但我仍然没有得到解决方案。

@123:我根据您的示例更正了我的代码,但它似乎不起作用。

#!/usr/bin/env bash

FLAG="OffLine"
FLAG_tmp=$FLAG

while read line
do
if [[ $line == *"OnLine"* ]]; then
    FLAG_tmp="OnLine"
fi

if [[ $line == *"OffLine"* ]]; then
    FLAG_tmp="OffLine"
fi

if [ "$FLAG" != "$FLAG_tmp" ];then
    FLAG=$FLAG_tmp
    #echo $FLAG
fi
done & < <(tail -f /c/vagrant_data/iso/rpos/log/rpos.log)

while :
do
    echo "$FLAG"
    sleep 2
done

@chepner:你有一些确切的建议,我该如何解决这个问题?

【问题讨论】:

  • 您介绍的管道 (|) 创建了一个子shell,在子shell中更新的变量反映在父shell中.
  • 好的,但是我该如何处理这个问题呢?也许通过导出它?你有什么建议吗?
  • while;do stuff;done &lt; &lt;(tail -f /my/path/test.log)
  • 进程替换无济于事;您还使用&amp; 在后台进程中运行整个过程。
  • 这不是范围问题,它描述了单个程序中变量的生命周期。这是进程间通信的问题。

标签: bash variables scope


【解决方案1】:

我认为你把它弄得太复杂了。如果您只想向自己发送 OffLine 或 OnLine 的最后状态,您可以尝试这样的操作:

#!/bin/bash

while :
do
    FLAG="$(egrep 'OffLine|OnLine' test.log | tail -1)"

    if [ $(echo "$FLAG" | grep OffLine) ]
    then
        FLAG=OffLine
    else
        FLAG=OnLine
    fi

    echo $FLAG
    sleep 2
done

或者,如果你真的想保留这两个进程,

#!/bin/bash

echo OffLine > status
tail -f test.log | while read line
do
    if [[ "$line" =~ "OffLine" ]] 
    then
        echo OffLine > status
    elif [[ "$line" =~ "OnLine" ]]
    then
        echo OnLine > status
    fi
 done &

 while :
 do
     cat status > /dev/udp/[my.ip.address]/[port])
     sleep 15*60
 done

【讨论】:

  • 希望能亲自见到您,在此郑重的感谢您!你真的保护了我的时间,并给出了如何解决它的好主意。这是完美的解决方案(尤其是第二个写入状态文件的解决方案)。再次感谢您的宝贵时间:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-10
相关资源
最近更新 更多