0

It's my Bash script homework, I am confused about the output of my programs. Suppose I need to use script debugger.sh to invoke script program.sh until the second one failed, and capture all the output of program.sh

user@user-machine:~$ cat program.sh
#!/usr/bin/env bash

n=$(( RANDOM % 100 ))

if [[ n -eq 42 ]]; then
    echo "Something went wrong"
    >&2 echo "The error was using magic numbers"
    exit 1
fi

echo "Everything went according to plan"

user@user-machine:~$ cat debugger.sh
#! /bin/bash

touch info.txt
count=0

while [ 0 -eq 0 ]
do
    ./program.sh > info.txt
    if [ $? -eq 1 ]
    then
    echo "failed at stage $count" > info.txt
    break
    fi
    ((count++))
done

When I type command ./debugger.sh in my Bash shell, the result I expect:

user@user-machine:~$ ./debugger.sh
Something went wrong
user@user-machine:~$ cat info.txt
Everything went according to plan
Everything went according to plan
........
The error was using magic numbers
failed at stage....

But the actual result is:

user@user-machine:~$ ./debugger.sh
The error was using magic numbers
user@user-machine:~$ cat info.txt
failed at stage 199

I can't figure out where some output goes. Why "The error was using magic numbers" appears on my terminal, I think it should be redirected to the info.txt file. And the "Everything went according to plan" just vanish. It's so weird, can someone explain? My English is not so good, hope you guys understand. I'm really grateful to you guys.

  • Rather than `while [ 0 -eq 0 ]; ... break;` it would make sense to loop as long as the program is successful. In other words, just write `while ./program.sh; do : $((count++)); done > info.txt; echo "Failed after $count successful runs";` – William Pursell Jul 12 '22 at 16:50

1 Answers1

1

There are many unrelated errors here.

You are comparing the string n to 42, not the variable $n, so of course that will always fail.

You are overwriting the output file on each iteration, so you are overwriting the diagnostics from all previous iterations.

There are various other stylistic issues, many of which http://shellcheck.net/ will diagnose and often propose fixes for.

Your script uses Bash-only syntax in several places, so your question should not really be tagged ; see also Difference between sh and bash

All diagnostic messages are printed to standard error, and include the name of the responsible script.

Also, Why is testing “$?” to see if a command succeeded or not, an anti-pattern?

Here is a refactoring to hopefully address most of these issues.

#!/usr/bin/env bash

n=$(( RANDOM % 100 ))

if [[ $n -eq 42 ]]; then
    echo "$0: Something went wrong" >&2
    >&2 echo "$0: The error was using magic numbers"
    exit 1
fi

echo "Everything went according to plan"

The refactored debugging loop collects the results from every run. The log file includes the count, and captures both standard output and standard error.

#! /bin/bash

warn () {
    echo "$0: $*" >&2
}
die () {
    warn "$*"
    exit 1
}

count=0

# notice change
while true
do
    warn "run $count"
    ./program.sh ||
    die "failed at stage $count"
    ((count++))
done >info.txt 2>&1
tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Thanks! You really help a lot. But I run few experiment both on `if [[ $n -eq 42 ]]` and `if [[ n -eq 42 ]]`. Then I get the same result, maybe It's a style problem. But It will cause error if we just use a single square bracket instead of two like `if [ n -eq 42 ]`. – Grenic Mars Jul 13 '22 at 02:18
  • I try a lot and still can't figure out what cause the problem before your answer. But things becoming clear now. Thank you sir. – Grenic Mars Jul 13 '22 at 02:23
  • For those who don't understand 2>&1 well like me, this article may help. [Understanding Shell Script's idiom: 2>&1](https://www.brianstorti.com/understanding-shell-script-idiom-redirect/) – Grenic Mars Jul 13 '22 at 02:27
  • 1
    You're right, `[[`...`]]` provides an arithmetic context so the dollar sign is optional. TIL! – tripleee Jul 13 '22 at 04:57