Calling subscript with sh vs. ksh

I ran into an issue today that I was able to resolve, but I don't quite understand why the resolution worked. I'm wondering if anyone can help me make sense of it.

I have a "kicker" script that calls 4 subscripts on a RHEL 6.9 server. It calls the scripts in sequence checking for a 0 exit code from each before running the next.

Both the kicker script and each of the subscripts were written in kornshell and all start with #!/bin/ksh as the first line.

 #!/bin/ksh 
 sh /opt/scripts/script1.ksh
 rc=$?
 if [[ ${rc} -gt 0 ]]; then
   exit
fi
sh /opt/scripts/script2.ksh
 etc.
 

This worked fine and as expected when running it from the command line, but generated syntax errors from the subscripts when run via a scheduler (Control-M). The syntax errors were like the following:

 /opt/scripts/script2.ksh: line 252: [: -eq: unary operator expected
 /opt/scripts/script2.ksh: command substitution: line 288: unexpected EOF while looking for matching `''
 /opt/scripts/script2.ksh: command substitution: line 289: syntax error: unexpected end of file
 /opt/scripts/script2.ksh: command substitution: line 291: unexpected EOF while looking for matching `''
 /opt/scripts/script2.ksh: command substitution: line 292: syntax error: unexpected end of file
 

The errors made me suspect that it was running using the wrong shell, so I changed the kicker script to call the subscripts using "ksh /opt/scripts/script2.ksh" instead of "sh /opt/scripts/script2.ksh".

The next time the job ran, it ran successfully (both from the command line and through the job scheduler.)

So, while I'm glad my issue is fixed, I'm trying to understand why what I did fixed it.

script2.ksh has #!/bin/ksh at the top. How does that interact with invoking the script using "sh script" vs "ksh script"? Does one override the other? Am I barking up the wrong tree entirely?

Thanks!

Hi,
The line magic number is not considered when the script is calling with a particular shell.

And, in the case of sh, errors seems to be a variable that is empty.

Regards.

Also, since the first line has a space in front of the shebang on the first line, it would not work even if you call the script without specifying a shell when calling the script. The shebang only works if the first two bytes of the file are #!

If you want to call the shell without using the shebang, you need to use the same shell as part of the command to use the script as argument, which in this case is ksh for all scripts. ksh is a different shell than sh .

Thank you for the reply. That is a useful piece of the puzzle. So in this case, when I was calling script2 with the sh it was ignoring the #!/bin/ksh and using sh to run it.

I'm still unclear why it worked correctly when executing the kicker script from the command line, but not through the scheduler. Both ways it would be explicitly calling the subscripts using sh. I would have expected it to fail in both cases. I think there must be something else at play besides the difference between ksh and sh. I agree that the errors are due to the variable it's trying to compare being empty, but not sure why the variable would be empty when running it with sh through the scheduler, but not with sh from the command line and not with ksh from the scheduler. At this point it's working, so I'll just move on. :slight_smile:

Thanks again!

Oh - and to Scrutinizer, thank you also for the reply. In the actual script there isn't the space before the shebang, I must have inadvertently added that while copying and pasting to the post.

Different PATH value causes it to find a different sh, perhaps?

Hi derndingle...
It might be worth using this test site:

ShellCheck � shell script analysis tool

It can cater for sh, dash, bash, ksh and perhaps others now.

'dash' is as near as dammit pure 'sh' and will pluck out the vast majority of coding errors if 'sh' is what you really want.

The errors in your scripts show in a separate window and are very verbose...

Bazza...