Find the answer to your Linux question:
Results 1 to 8 of 8
Hey all. I'm new to here, not new to bash, written a lot of scripts but typically they're quite simple. I'll do my best to describe what I'm trying to ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Oct 2012
    Posts
    6

    Bash Advice on how to act on continually updated timestamp


    Hey all. I'm new to here, not new to bash, written a lot of scripts but typically they're quite simple.

    I'll do my best to describe what I'm trying to do. So I've got this script which monitors a local port for events from my motion sensors at home from an interface hooked up to my computer.

    Every time the motion sensor sees some action it updates the variable m1_seen to the current time. What I want it is to add a condition where IF timestamp greater than 1 hour ago, do some action.

    The issue is this current while read only loops when there is input from /dev/tcp/localhost/1099. Of course if there is no motion events, the script doesnt loop, so I dont get a chance to perform an action.

    I was thinking somehow I need to send this variable's value off to another script/loop, and this loop would check every minute to compare m1_seen to current time and perform an action. Any advice? I hope I'm being descriptive.

    Code:
    exec 6<>/dev/tcp/localhost/1099
    
    while read <&6
    do
            if [[ "$REPLY" =~ .*RF.*HouseUnit.*M1.*On.* ]]
            then
                    echo "M1 Last Seen: $m1_seen" >&1;
                    echo "pl a10 bright 10" >&6; #understanding this line is of no consequence
                    m1_seen=`date +%H:%M`;
            elif
            then 
                 # <do something else>
           fi
    done

  2. #2
    Linux Engineer
    Join Date
    Apr 2012
    Location
    Virginia, USA
    Posts
    889
    Set up a cron job to run every so often.
    The script doesn't need to loop, because the cron job will take care of that.
    You can schedule cron jobs for every minute, but it sounds like every 5-10 minutes should be adequate for you.

    Anyway, that's how I would do it, because it's a small amount of code and it's simple.

  3. #3
    Linux Newbie
    Join Date
    Jun 2012
    Location
    SF Bay area
    Posts
    167
    Some variation on this might work... The systems I have access to don't expose things like "/dev/tcp/locahost/1099" but I'm assuming from your script that you can read from them. So if "tail -f" works on that "file" then this approach should work.

    It basically throws two processes in the background and maps both their output to one pipe which the main code reads. So you'll get updates from your monitoring software and a timer in the same queue.


    Code:
    #!/bin/bash
    
    typeset -i last_event curr_time
    
    last_event=$(date +"%s")
    
    # -- longest time the script will wait before alerting, in seconds.  Set to 1 hour here
    MAX_STALE=$(( 60 * 60 ))
    
     (
        tail -f /tmp/test-file.log &
        while [ 1 ]
        do
            echo "TIME"
            sleep 5
        done
     ) | \
     while read line
     do
            if [ "${line}" != "TIME" ]
            then
                    last_event=$(date +'%s')
    
    # -- put the rest of the monitoring log procesing here...
    echo "$(date) ${line}"
    
            fi
    
            curr_time=$(date +"%s")
            diff=$(( ${curr_time} - ${last_event} ))
    
            if [ "${diff}" -gt ${MAX_STALE} ]
            then
                    echo "$(date) stale, no updates"
                    last_event=${curr_time}
            fi
    done

  4. #4
    Just Joined!
    Join Date
    Oct 2012
    Posts
    6
    Quote Originally Posted by mizzle View Post
    Set up a cron job to run every so often.
    The script doesn't need to loop, because the cron job will take care of that.
    You can schedule cron jobs for every minute, but it sounds like every 5-10 minutes should be adequate for you.

    Anyway, that's how I would do it, because it's a small amount of code and it's simple.
    Thanks but I don't think that works. How does the cron job know the value of the m1_seen variable which is continually updated by my current script?

  5. #5
    Just Joined!
    Join Date
    Oct 2012
    Posts
    6
    Hey sorry thanks for the effort but this wont work. /dev/tcp/localhost/1099 is a socket or whatever it's called, you can't tail it. AND I need to retain STDIN/STDOUT redirection so I can write to this socket where need be.

    You're proposing to tail it and do a while loop around it. My script is redirecting STDIN from that socket and doing a while loop around it. SO to me my method should accomplish relatively the same thing but better/more reliably.

    However I'm wondering if I can use your pipe example to pipe one loops output into another's.

    basic example:

    Code:
    (exec 6<>/dev/tcp/localhost/1099
    while read <&6; do echo "something"; done)|while read state;
    do 
    if [ $state ] etc etc etc;
    fi
    done
    The issue with that is I need to eventually do this on multiple states, multiple sensors. I could just write this state to a database or a log and have a separate script act on that. But I was hoping to avoid disk for something this minor.

  6. #6
    Linux Newbie
    Join Date
    Jun 2012
    Location
    SF Bay area
    Posts
    167
    The Linux systems I have access to don't support "exec 6<>/dev/tcp/localhost/1099" as a way to gain access to the socket which another process setup and it sending data to. In fact I don't know of a simple, straightforward way for a shell script to connect to "port 1099 on localhost" without actually running a TCP stack based client. So if your system has a cool trick for just mapping file decriptor "6" to a socket and then you can read/write to it I can't help with that part of things.

    But I can explain how the script I suggested works in case parts of that approach could be adapted for your use.

    The basic idea is to create three chunks of code that run somewhat independently of each other, and combine the output from two of them for the third one to read. That just let's you have a "timekeeper" that injects data into the queue that the main processing code reads. And here's how that breaks down into a template.

    ( CODE#1 & CODE#2 ) | while read line; do CODE#3; done

    The parens group whatever happens in the into a single unit which can then be piped to the third piece of code. And ending CODE#1 with "&" throws that chunk of code into a background process to allow CODE#2 to operate independently. That's how the "timekeeper" can periodically add data to the queue for CODE#3, which will break the potentially very long time between iterations when there are no events for CODE#1 to report.

  7. #7
    Just Joined!
    Join Date
    Oct 2012
    Posts
    6
    I'm just using regular old ubuntu, there's not special going on here. I'm running a service on that system and reading that local port. You can do this with anything. You could read port 80 for example. It's standard stuff.

    What I'm doing does allow you to read and write to that port.

    I understand what youre script is doing. But it wont work on devices. I could use the template's premis to do what I want, you might have given me an idea.

  8. #8
    Just Joined!
    Join Date
    Oct 2012
    Posts
    6
    Set up a cron job to run every so often.
    The script doesn't need to loop, because the cron job will take care of that.
    You can schedule cron jobs for every minute, but it sounds like every 5-10 minutes should be adequate for you.

    Anyway, that's how I would do it, because it's a small amount of code and it's simple.
    IF i was to use this method the closest thing I could think of instead of hard assigning crons is to use the command 'at' to set crons and 'atrm' to remove crons. In other words set a cron a half hour from now, if the sensor goes off within that time, remove that 'at' job with 'atrm' and create a new one a half hour from the current time. At base, it's a simple solution but there are accounting problems because I would have to keep track of all the jobs created so I know which ones to remove.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •