LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   bash script, understanding variables (https://www.linuxquestions.org/questions/programming-9/bash-script-understanding-variables-599574/)

antis 11-14-2007 09:15 AM

bash script, understanding variables
 
Below is a snippet from a script I'm working on.
Basically it looks at the timestamp in a log file and puts this value into a variable and then prints it.

It's working ok while inside the loop but then, when I'm finished reading the file, the variables are both set to 0.
This is driving me crazy! Can someone please explain to me why this is happening. In this case I expect it to print the last timestamp in the file.

Like everything else the answer is probably quite obvious when you know it :)

Many thanks!


Code:

#! /bin/bash

LOG_FILE="/var/log/auth.log"
LAST_CHECKED_TIMESTAMP=0
TIMESTAMP_ON_LINE=0

RETURN_TAIL_LINES=`wc -l "$LOG_FILE" | awk '{print $1}'`

tail -n $RETURN_TAIL_LINES "$LOG_FILE" | while read line
do
        TIMESTAMP_ON_LINE=`echo $line | awk '{print $1, $2, $3}'`
        LAST_CHECKED_TIMESTAMP=$TIMESTAMP_ON_LINE

        printf "$LAST_CHECKED_TIMESTAMP\n$TIMESTAMP_ON_LINE"
done

printf "\n\n*******\n$LAST_CHECKED_TIMESTAMP\n$TIMESTAMP_ON_LINE\n"


bigearsbilly 11-14-2007 09:50 AM

well, it's an age old bash thing.
the read variables only work in the while loop, annoying isn't it?

you will find that if you run it in ksh it will work.

if you have it that is.

/bin/sh won't work either if on linux as it's bash in drag.

colucix 11-14-2007 09:54 AM

When piping the output of the tail command to the while loop, the loop itself is executed in a subshell. When the loop exits and the subshell execution is terminated, all the variables assigned in the subshell are lost. To avoid this behaviour you can use "process substitution", as in
Code:

while read line; do
        TIMESTAMP_ON_LINE=`echo $line | awk '{print $1, $2, $3}'`
        LAST_CHECKED_TIMESTAMP=$TIMESTAMP_ON_LINE

        printf "$LAST_CHECKED_TIMESTAMP\n$TIMESTAMP_ON_LINE"
done < <(tail -n $RETURN_TAIL_LINES $LOG_FILE)

Have a look at the Advanced Bash Scripting Guide, chapter 22 for a complete explanation of process substitution.

antis 11-14-2007 12:53 PM

Thanks alot for your comments!
Process substitution indeed looks like they way to go for me.

bigearsbilly 11-15-2007 02:32 AM

or /bin/ksh
;)

antis 11-15-2007 04:27 AM

Quote:

Originally Posted by bigearsbilly (Post 2959492)
or /bin/ksh
;)

Possibly maybe perhaps :)
Using ksh for the script was my plan from the beginning but a few date issues made me go with bash instead. That might change before it's finished though...


All times are GMT -5. The time now is 08:41 PM.