Question

I am learning bash shell and I'm a beginner.
Now, I have a script named for_test

#!/bin/bash
var1=3
until [ $var1 -eq 0 ]
do
    echo "Outer loop: $var1"
    var2=1
    while [ $var2 -lt 5 ]
    do
        var3=`echo "scale=4; $var1 / $var2" | bc`
    echo "    Inner loop:$var1 / $var2 = $var3"
    var2=$[ $var2 + 1 ]
    done
    var1=$[ $var1 - 1 ]
done >> temp.log.txt

When I exec it in the terminal, it works well.

Outer loop: 3
    Inner loop:3 / 1 = 3.0000
    Inner loop:3 / 2 = 1.5000
    Inner loop:3 / 3 = 1.0000
    Inner loop:3 / 4 = .7500
Outer loop: 2
    Inner loop:2 / 1 = 2.0000
    Inner loop:2 / 2 = 1.0000
    Inner loop:2 / 3 = .6666
    Inner loop:2 / 4 = .5000
Outer loop: 1
    Inner loop:1 / 1 = 1.0000
    Inner loop:1 / 2 = .5000
    Inner loop:1 / 3 = .3333
    Inner loop:1 / 4 = .2500

But when I exec like this:

at -f for_test 11:10

When the time has come, the script is executed, but I get an infinite loop.
Here's the log.

Outer loop: 3
    Inner loop:3 / 1 = 3.0000
    Inner loop:3 / 1 = 3.0000
    Inner loop:3 / 1 = 3.0000
    ……

And I found $var2 always equals 1.

What do I do wrong?


My ubuntu version and bash version.

$ uname -a
Linux android_su 2.6.35-32-generic #67-Ubuntu SMP Mon Mar 5 19:39:49 UTC 2012 x86_64 GNU/Linux


$ bash --version
GNU bash, version 4.1.5(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

@konsolebox
The second command works fine. Thanks.
But why does the first command not work? I'm still confuesd.
First and second commands are all executed with /bin/sh.

$ at -f for_test 14:16
warning: commands will be executed using /bin/sh
job 22 at Thu Aug 29 14:16:00 2013

$ echo "/bin/bash /home/android_su/android/source/linux_learned/for_test" | at 14:19
warning: commands will be executed using /bin/sh
job 23 at Thu Aug 29 14:19:00 2013
Was it helpful?

Solution 2

Try to use internal functions instead as PATH is not always defined in crontabs and likes:

#!/bin/bash
var1=3
until (( var1 == 0 ))
do
    echo "Outer loop: $var1"
    var2=1
    while (( var2 < 5 ))
    do
        var3=$(echo "scale=4; $var1 / $var2" | bc)
        echo "    Inner loop:$var1 / $var2 = $var3"
        (( ++var2 ))
    done
    (( --var1 ))
done >> temp.log.txt

Make sure you run your script as bash as well like this:

echo "/bin/bash /path/to/script.sh" | at 11:10

Or

at 11:10 <<EOF
/bin/bash /path/to/script.sh
EOF

OTHER TIPS

When using at -f the commands in the script are parsed as if you typed them in. That means that #!/bin/bash is just a comment and does not cause your script to execute under bash. As at would have told you if you had not used -f:

$ at 0900
warning: commands will be executed using /bin/sh

The problem with using /bin/sh is that true Bourne shell does not support the math extensions you are using like $[ 1 + 2 ]. Those were introduced by ksh (afaik) and are now available in bash. Some people may se different results with their system /bin/sh because not all systems use the same sh. Some just use bash but there are more Bourne-like variants such as ash and probably whatever shell is in busybox.

You just need to make a wrapper that calls your script (just a file with /path/to/script in it) and use that file as the input to at -f

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top