1

I would like to develop portable /bin/sh scripts, but my environment links /bin/sh to /bin/bash. Even when running in --posix mode, /bin/bash still handles some non-portable features like [[ and $(). I am (now) aware that these are bash extensions not portable, but I don't know what other syntax I'm using that isn't always available.

Is there a free implementation of /bin/sh which rejects non-portable constructs that I could use to test whether my scripts don't use any bash-isms?

meustrus
  • 227
  • 4
    $() is not a bashism. dash might be a good option, but also has at least a few non-sh caveats. – jesse_b Jun 21 '18 at 21:49
  • I was under the impression that backticks `` were the only /bin/sh-compatible way to do what you can do with $() in bash. Is $() part of POSIX then? – meustrus Jun 21 '18 at 21:56
  • 5
  • 1
    But only a few shell implementations (e.g. new ksh93 and bosh) implement $(...) correctly. See: https://www.in-ulm.de/~mascheck/various/cmd-subst/ This is because it is not easy to parse $(...) correctly as you need a recursive parser. – schily Jun 21 '18 at 23:16
  • This question relies upon the erroneous premise that using a particular shell is the only way to check for non-portable shell constructs. How can I check scripts for non-portable shell constructs? What tools can help me? is a question that would have garnered more comprehensive pointers towards the actual goal. But we've already had questions like that for years now, at https://unix.stackexchange.com/questions/9997/ , https://unix.stackexchange.com/questions/24146/ , and the like. – JdeBP Jun 24 '18 at 20:34
  • Using a shell that rejects non-portable constructs would be the easiest way to discover bugs. A linter would be only slightly less convenient. A list of documented rules is extremely error-prone. But I admit my question definitely conflates /bin/sh with POSIX. As an example, according to lintsh (which asking this question helped me to find), $() is not portable despite being POSIX because Solaris outright refuses to recognize it, in addition to the potential issues @schily alluded to. – meustrus Jun 25 '18 at 18:57
  • Since any even small feature in bosh may be configured at compile time (check Makefile), you could e.g. create a shell variant that does not permit enhancements. – schily Jun 25 '18 at 19:40

1 Answers1

2

How about bosh the POSIXified Bourne Shell:

It still has some extensions but they are well documented:

http://schilytools.sourceforge.net/man/man1/bosh.1.html

It is faster than dash and a bit slower than ksh93 which makes it the second fastest shell.

Note that dash does not support multi byte characters and thus is only useful for small embedded systems.

BTW: bosh allows to fine grained configure the behavior. The Solaris-10 compatible osh is compiled from the same source as bosh. Have a look at Makefile. When I have some time, I may have a look whether I could create a preconfigured Makefile for that purpose.

Update: During the past days, I created a new compile variant of "bosh" and call it "pbosh". It will be included in the next scheduled schilytools snapshot that will most likely be published on June 29 or July 2 2018.

"pbosh" is a shell that is intended to test shell scripts for portability.

It does not implement extensions on POSIX and thus would fail, in case that a shell feature beyond the POSIX standard is used.

Please keep in mind that a script that works with "pbosh" still may fail with other shells as POSIX has some features unspecified. One example is the way how pipelines are created. "pbosh" implements the optimized method and moreover runs the rightmost program from a pipe inside the shell process in case that this is a shell builtin. As a result, it is most likely that all pipes that work with "pbosh", will also work with "ksh93" but still may fail with e.g. "bash".

If you like to check whether your script is portable to the SVr4 Bourne Shell as present on e.g. Solaris 10, it is recommended to check whether it also runs with another compile variant of "bosh" from schilytools called "osh". This is a portable version of the Solaris 10 SVr5 Bourne Shell.

Note: in order to make "pbosh" halfway useful, persistent aliases are not disabled by default. You may either test your scripts with other shells in addition, or edit the Makefile and comment out the lines with:

CPPOPTS +=      -DDO_GLOBALALIASES      # Include persistent aliases in ~/.globals 
CPPOPTS +=      -DDO_LOCALALIASES       # Include persistent aliases in .locals 

Then call "make clean all" to recompile "pbosh" with persistent aliases disabled.

schily
  • 19,173