2

I have a bash script which will be called by /bin/sh on a Solaris machine. When I run the script as /bin/sh ./solarisSh, it works. When I source the same script, it fails.

I know bash and Bourne Shell are almost nothing alike. This is not my question.

My question is: Why does Solaris /bin/sh behave so differently when sourcing a file versus just plain executing a file?

Here are the data...

ns2 ~/tmp 560> env -i /bin/sh -x
$ uname -a
+ uname -a 
SunOS ns2 5.7 Generic_106541-15 sun4m sparc SUNW,SPARCstation-10
$ cat ./solarisSh
+ cat ./solarisSh 

[ ! "$BASH" ] && {
    >&2 echo "ERROR: $0 is a Bash script.  Exiting."
    return 1 2> /dev/null || exit 1
}

haveRootPriv() {
    local idCmd=/usr/bin/id
    local euid
    local uid

    [[ $OHM_OS == "SunOS" ]] && idCmd=/usr/xpg4/bin/id
    if (( ( $( $idCmd -ru) == 0 ) || ( $( $idCmd -u) == 0 ) )); then
       echo 1
       return 0
    fi
    echo 0
    return 1
}
$ /bin/sh -x ./solarisSh 
+ /bin/sh -x ./solarisSh 
+ [ !  ] 
+ echo ERROR: ./solarisSh is a Bash script.  Exiting. 
ERROR: ./solarisSh is a Bash script.  Exiting.
+ return 1 
$ . ./solarisSh 
+ . ./solarisSh 
syntax error: `$' unexpected
$ 

The ERROR: ./solarisSh is a Bash script. Exiting. is what I was expecting when I sourced the file. What I got was the syntax error: `$' unexpected.

To recap the question: Why does Solaris /bin/sh behave so differently when sourcing a file versus just plain executing a file?

I guess I have a second question, too (sorry): Why doesn't -x work when sourcing a file?

Thanks.
-Erik

  • It appears that sourced files are fully parsed before execution, and scripts are not. Why, I don't know, and maybe nobody does. – Michael Homer Sep 11 '17 at 3:09
4

Deleting the $(...) command substitution removes the failure for me on 5.10. That suggests that what you're seeing is the effect of . parsing the entire file before it executes, and encountering an error at that unsupported syntax. By contrast, the script is being parsed line-by-line, so it exits before the syntax error is noticed.

Experimentally, you can insert other syntax errors and see the same behaviour: . fails early, and sh executes up to the malformed line.

Why? I don't know. It doesn't seem to be specifically documented anywhere I can find. The man page just says for .:

 . filename

     Read and execute commands from filename and return.  The
     search path specified by PATH is used to find the direc-
     tory containing filename.

The documentation for <<word says "shell input is read up to ...", which perhaps implies minimalistic parsing, but I don't see anything explicit anywhere. Line-by-line parsing is quite common for shell scripts in general, and it's what Bash does in both cases, for example.

Why doesn't -x work when sourcing a file?

It does work, as long as commands actually do start executing. Nothing is printed during the parsing phase.


For this specific example, using ` ... `-style command substitution would work, but the real script is probably more complex.

  • This seems to explain the behavior of both the sourcing and the -x. Rats. I was able to work around the whole mess by using an eval<<'bashScript', but the resulting script seemed both sick, and wrong. Thanks, Michael Homer, for your help understanding this matter! – Erik Bennett Sep 11 '17 at 4:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.