1

I want to increment a counter in a while loop, and once that loop is complete, echo out the counter. The $COUNTER should only increment if $DATE >= $SINCE

   last -f /var/log/btmp |
while read line; do
    set -- $line
    [[ $1 == "$CURRENTUSER" ]] || continue
    [[ $(date -d "$4 $5 $6 $7" +%Y%m%d%H%M%S) -ge $SINCE ]] && echo "FAILED LOGIN $line" && ((COUNTER+=1))
    echo $COUNTER //echos 1, 2 etc
done

echo "Top counter:"$COUNTER //echos 0 
1
  • Tagged as bash, so the next approach is not suitable as an answer: Start your script with #!/bin/ksh Commented Jul 25, 2014 at 12:36

3 Answers 3

1

Your problem is with this line:

[[ $(date -d "$4 $5 $6 $7" +%Y%m%d%H%M%S) -ge $since ]] && echo "$line && COUNTER=$[$COUNTER +1]"

You will want something like:

[[ $(date -d "$4 $5 $6 $7" +%Y%m%d%H%M%S) -ge $since ]] && echo "$line" && ((COUNTER+=1))

If you want to display and increment, then:

[[ $(date -d "$4 $5 $6 $7" +%Y%m%d%H%M%S) -ge $since ]] && echo "$line $((COUNTER+=1))"
Sign up to request clarification or add additional context in comments.

7 Comments

That works for my echo in the while loop, but the echo of $COUNTER afterwards still prints 0
Hmm. that's strange. I tested here and it works fine: ( COUNTER=0; line="dog"; for i in $(seq 1 3); do echo "$line $((COUNTER+=1))"; done; echo "COUNTER $COUNTER" ) output is: dog 1 dog 2 dog 3 COUNTER 3
@Kiksy Where is the input for your while loop? You should have something line done < file_to_read.txt Also, you don't really have the // for comments in the file do you? That is not a valid bash comment. Use # instead.
Try: echo "Top counter: $COUNTER" and get rid of the // change to # for comments.
outputs 2,2,2,2,2 TOPCOUNTER:0
|
0

Issue was one of scope. Piping into the while means the $COUNTER goes out of scope. A good explanation is http://mywiki.wooledge.org/BashFAQ/024

Solution was from Chris's comment on this post:

http://www.edwardawebb.com/linux/scope-issue-bash-loopsenter link description here

COUNTER=0

STDOUT=$(last -f /var/log/btmp)

        while read line; do
            set -- $line
            [[ $1 == "$CURRENTUSER" ]] || continue
            [[ $(date -d "$4 $5 $6 $7" +%Y%m%d%H%M%S) -ge $SINCE ]] && echo "FAILED LOGIN $line" && ((COUNTER+=1))
        done <<EOF

        $STDOUT
        EOF

        echo "counter:$COUNTER"

Comments

0

Pipes commands are executed each in their own sub-shell. Variables modifications are confined in that sub-shell, and will not propagate back to the parent shell.

Using bash, a common workaround to avoid that pitfall is to use process substitution :

while read line; do
    set -- $line
    [[ $1 == "$CURRENTUSER" ]] || continue
    [[ $(date -d "$4 $5 $6 $7" +%Y%m%d%H%M%S) -ge $SINCE ]] && echo "FAILED LOGIN $line" && ((COUNTER+=1))
    echo $COUNTER //echos 1, 2 etc
done < <(last -f /var/log/btmp)
#    ^^^^^^^^^^^^^^^^^^^^^^^^^^

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.