bash lesson of the day

So I’m running a command in a for loop in bash:

SECONDS=1
for i in 1 2 3 4; do
../my_test -S "${SECONDS}"
done

And for some damn reason, the test runs for 1 second on the first loop, then 2 seconds on the second loop, then 4 seconds on the next, etc. WTF?

Ten minutes of debugging output later, I finally type “man bash”:

SECONDS
Each time this parameter is referenced, the  number  of  seconds
since  shell  invocation is returned.  If a value is assigned to
SECONDS, the value returned upon subsequent  references  is  the
number  of seconds since the assignment plus the value assigned.
If SECONDS is unset, it loses its special properties, even if it
is subsequently reset.

Geez.

9 thoughts on “bash lesson of the day”

  1. The “unset to lose special properties” is a common mechanism in bash. Some scripts will attempt to future-proof themselves by explicitly unsetting all their vars at the very beginning before using them. I just try to stick to lower case.

  2. Ah, magic shell variables. I vaguely recall being bitten by something like that in the past – like Gomijacogeo, I tend to avoid upper-case variable names as a result.

  3. I think you may have missed the point – I was using SECONDS as a regular ol’ variable and was totally unaware that it was a special builtin varialbe.

  4. Yeah, I’d like to think I got it at least.

    I was, without explicitly stating, moving on from the “ya got bit in an interesting way” to “how do some people avoid getting bit again” because being bit the 2nd time is almost never interesting.

    One way would be to memorize the list of magic bash variables and hope more don’t get added. Way two was the clear em all as just a rote programming style. Way three was to hopefully avoid the namespace altogether and hope they never intrude.

    I learned the lesson from the other direction. I was reading a script and wondered why the heck someone went through all the trouble of unsetting every variable.

    P.S. Hello. I’m John. I do Infiniband driver development. Decided to follow your blog because of the occasional nifty links and git ponderings.

  5. But why was it in upper case, then (which by convention is reserved for environment variables)? I’d assumed you were deliberately aiming for the special variable, purely because of the upper case. If you’d wanted a shell variable, then use lower case. In this case, it would even have prevented the problem (albeit more by luck than judgement!)

  6. Great topic

    That was interesting and the comments were as well. It is nice that you have a blog now. I was not convinced and so I wrote this to see what happened. Then I read man bash and accepted it. I see errors in the manuals even now as “man” is not always well maintained.

    #!/bin/bash
    SECONDS=1
    for (( i=1; $i < = 10; i++ ))
    do
    sleep 2
    echo $i,”${SECONDS}”
    done

Comments are closed.