When sh is a symlink to bash or dash, bash limits itself to POSIX-compliance, so it should be 100% compatible with sh?

284

Solution 1

No, if /bin/sh is a symlink to bash bash enters just posix mode - from man bash:

When invoked as sh, bash enters posix mode after the startup files are read.

If you now search for posix mode at the bash manpage you'll see that some shell builtins like time or source behave differently. That is all. bashishms like writing function before declaring a function or using source instead of . still will work but the commands may behave differently.

So if /bin/sh is a symlink to /bin/bash all typical bashishms still work.

For a pretty extensive list of differences in the Posix mode have a look at the bash reference manual.

Solution 2

There seems to be some confusion around the Bourne shell. The Bourne shell was Unix shell decades ago, in the pre-POSIX days. Nowadays "sh" is an implementation or another of a shell that implements the POSIX specification, among which we have bash, pdksh, AT&T ksh, newer Almquist shells and their derivatives that have been made POSIX compliant (including the "sh" of some BSDs, other BSDs sh being based on pdksh and Debian ash (dash)). Even zsh has a mode in which it is mostly POSIX conformant.

The Bourne shell is not POSIX compliant, and can't be found on many system nowadays. Where the Bourne shell is found or where it's not, there will always be a "sh" that is POSIX compliant (and will not be the Bourne shell), generally in /bin while a notable (annoying) exception is Solaris.

Note that before the Bourne shell, and we're talking over 30 years ago, "sh" was the Thompson shell. We're not writing scripts compatible with the Thompson shell anymore. Similarly, we should stop thinking of "sh" as the Bourne shell.

Now "sh" is a specification, not many sometime incompatible variants of an implementation. That makes it a lot easier to write portable scripts. Just follow the specification.

That goes for "sh" and all the standard utilities (sed, cut, tr...)

Share:
284

Related videos on Youtube

Tamer Fahmy
Author by

Tamer Fahmy

Updated on September 18, 2022

Comments

  • Tamer Fahmy
    Tamer Fahmy over 1 year

    My application is near real time data buffering application.

    I,m using net. TCP bindings to send complex objects.

    buffering data through different call-back functions to the client.

    as much as i enable certain events the application slow down and converted to be none real time.

    any one can help to the optimal way to make real time data buffering to multiple clients with large complex objects in WCF ???

  • user1115057
    user1115057 almost 12 years
    So I guess the best thing to do is to test all script in the checkbashism tool. I heard that some distro, like Debian and Ubuntu (need confirmation for this one) had their bin/sh now symlink to dash. Does dash is compatible with the bourn shell? If yes, then at least all Debian and Ubuntu shell script should be fine under FreeBSD.
  • sunnysideup
    sunnysideup almost 12 years
    @user1115057 only shell scripts with /bin/sh as shebang. A shell script still can explicitly use /bin/bash. Anyway most shell scripts probably will run fine under /bin/sh but the problem will be the user tools, e.g. most shell script expect GNU userland which will probably be more of a problem than just some syntax error. I also added a link to the bash reference which lists the different behavior in posix mode
  • user1115057
    user1115057 almost 12 years
    Ok from what I read, BSD use ash as their bin/sh, while Debian & Ubuntu use dash. If those shell are compatible, it mean I wont have anymore issue with shebang #!/bin/sh. But as you said, there will be other issue related to the userland...
  • sunnysideup
    sunnysideup almost 12 years
    @user1115057 dash is also not perfect, e.g wiki.ubuntu.com/DashAsBinSh/#echo anyway most shell scripts are rather simple and can be ported quite easily…good luck
  • user1115057
    user1115057 almost 12 years
    But dash and ash are compatible right?
  • sunnysideup
    sunnysideup almost 12 years
    @user1115057 should be as dash is an descendant of ash - wikipedia page about dash - BUT i don't know if they are a 100% compatible. What are you trying to do? In general user space will be much more problematic, if everything fails you can still just run bash for your script but user space may be a little bit more complicated
  • Richard Fortune
    Richard Fortune over 11 years
    Dash and FreeBSD sh (and BusyBox sh) are not 100% compatible, but for most practical purposes you'll have trouble finding the differences. You're much more likely to have compatibility problems due to different systems differing in the utilities that your shell scripts invoke. If you are really interested in the nitty-gritty details, prepare yourself for a lot of reading, and here is a place to begin: in-ulm.de/~mascheck/various/ash
  • Richard Fortune
    Richard Fortune over 11 years
    +1 for "write to the specification." But sadly that's often not enough for portability. For example, what if one wants to use egrep-style patterns in sed? The specification doesn't provide for this. On systems with Gnu-based utilities (or BusyBox), you use sed -r. On systems with BSD-based utilities, you use sed -E. FreeBSD's sed accepts both, but Mac OS X's only accepts -E. And so on and so on.
  • Stéphane Chazelas
    Stéphane Chazelas over 11 years
    That's beside the point. The specification doesn't provide it, so you can't use it portably/POSIXly. If you use BREs, that will work on all POSIX conformant systems, that's a guarantee given by POSIX, that's why it's useful. Outside of POSIX as you say, there's no hope as seds either don't support ERE or support it with a different option or different ERE syntax. Note that EREs are less capable than BREs (only the syntax is extended in EREs to save you some typing. EREs can be translated to BREs, the contrary is not true (BRE's \(...\)\1 has no translation in standard EREs).
  • Richard Fortune
    Richard Fortune over 11 years
    I realize that (POSIX) EREs lack backreferences; in fact I've participated in editing that part of the standard. It's not correct that POSIX EREs are strictly less capable than BREs, since the in the current standard, alternation is not defined for BREs. However, I'm not aware of any regex engine which doesn't honor \| for BREs. I'm all for writing as portably as possible. I was only making the (I thought widely appreciated) observation that this can be painful, and sometimes writing to POSIX is simply not possible. Somewhere have links that exhibit many such perversions; will look for them.
  • Stéphane Chazelas
    Stéphane Chazelas over 11 years
    good point about alternation, I forgot about that and stand corrected. With sed, it's unlikely to be blocking though as you can use several expressions to match the alternate regexps. There's awk in the standard toolchest that can be used if EREs are needed. I very rarely find myself by the standard toolchest, and when I do, it's generally cases where another language like perl is more appropriate, but I do see your point (though I still think it's beside the point in this thread about writing portable scripts)
  • Richard Fortune
    Richard Fortune over 11 years
    An example I thought of offhand: shebang lines (at the top of every shell script) aren't specified in POSIX. Also, I'm not sure I've ever used a system that was 100% POSIX compliant. For example, POSIX says you can include newlines inside ${VAR:=stuff...here} but many shells don't let you, you have to put quotes around stuff...here.
  • Richard Fortune
    Richard Fortune over 11 years
    Yeah, EREs with sed isn't an ideal example, it was just off-the-cuff. I agree also we're straying from the main topic. And I think we're both fans of portability.
  • mklement0
    mklement0 over 9 years
    The one notable bashism that is not available when running as sh (or with bash --posix) is process substitution (<(...)).
  • Max Coplan
    Max Coplan over 4 years
    I came across today and found this very perplexing. If /bin/sh is a symlink to /bin/bash, HOW does /bin/bash know it was called with /bin/sh?? As an example, if I run ln -s /usr/bin/bash ./foo and run ./foo it will be regular bash. If I ln -s /usr/bin/bash ./sh and run ./sh it will run in POSIX mode. How does bash know how it was called??