Home > Blockchain >  Can't get expected output when I invoke another Bash script in current Bash script
Can't get expected output when I invoke another Bash script in current Bash script

Time:07-13

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.

CodePudding user response:

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
  • Related