18

When I run a Centos 7 Docker Image like this

docker run -it centos:7 bash

Running something which is uses Process Substitution is fine (as expected, as Bash supports Process Substitution since the beginning of time - Bash 1.4.x actually).

For example:

while IFS= read -r test; do echo $test; done < <(cat anaconda-post.log)

But when I switch to /bin/sh the same code doesn't work anymore

/bin/sh
while IFS= read -r test; do echo $test; done < <(cat anaconda-post.log)
sh: syntax error near unexpected token `<'

Although /bin/sh seems to be Bash

/bin/sh --version
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

But then why doesn't process substitution work anymore? Other non-POSIX features seems to work, though

echo ${PATH//:/ }
/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin
8
  • 3
    Either way, you don't have use process substitution at all. Just use input redirection, while IFS= read -r test; do echo $test; done < anaconda-post.log
    – Inian
    Commented Sep 9, 2021 at 6:08
  • 5
    Note that you seem to have invoked /bin/bash --version instead of /bin/sh --version.
    – Kusalananda
    Commented Sep 9, 2021 at 6:44
  • 1
    I cannot reproduce your example using centos:7 (8652b9f0cb4c).
    – muru
    Commented Sep 9, 2021 at 7:04
  • 1
    @ImHere 4.2.46(2)-release (x86_64-redhat-linux-gnu).
    – muru
    Commented Sep 9, 2021 at 8:20
  • 11
    Don't use bashisms if you use /bin/sh. Or don't use /bin/sh if you want to use bashisms. - "Although /bin/sh seems to be Bash" - Never rely on that; it may work now, but it may not work in the future, or on another system.
    – marcelm
    Commented Sep 9, 2021 at 15:30

4 Answers 4

34

Yes, bash, when called as sh, runs in POSIX mode, disabling all its bash only features. From the manual - Invoked with name sh

If Bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well

$ ls -lrth /bin/sh
lrwxrwxrwx. 1 root root 4 Aug 26  2018 /bin/sh -> bash
$ /bin/bash -c 'set -o | grep posix'
posix           off
$ /bin/sh -c 'set -o | grep posix'
posix           on

with posix mode enabled, non-standard features like process substitution won't be enabled. See Bash POSIX Mode to see its complete behavior running in the mode.

From release 5.1 of the shell, process substitutions are available in POSIX mode.

5
  • @Kusalananda ... unstable repo? Well, debian stable is bullseye, and it seems to be using 5.1 (What can I say?). The source comes from Chet anyway: ftp.cwru.edu/pub/bash
    – user232326
    Commented Sep 9, 2021 at 8:13
  • 1
    @Kusalananda Some attribution might be appropriate, don't you think? Now my answer is irrelevant. :-(
    – user232326
    Commented Sep 9, 2021 at 8:20
  • 1
    Supporting process substitution doesn't make a shell non-POSIX compliant as the behaviour for cmd <(cmd2) is unspecified per POSIX. In newer versions of bash, process substitution is not disabled when in POSIX mode (you'd still not want to use process substitution in sh scripts) Commented Sep 9, 2021 at 12:19
  • 2
    In any case, bash certainly does not disable all its extensions (most of them including process substitution are copied from other shells, so not bash only) when in POSIX mode. Commented Sep 9, 2021 at 12:20
  • 1
    unfortunately i don't remember any specific lingering feature, but it disables nearly all bash features, there are some things it doesn't actually disable (don't remember anything specific, maybe it was even a bug, hopefully someone else here knows)
    – hanshenrik
    Commented Sep 10, 2021 at 13:39
9

Some options are disabled on bash's POSIX mode. Which gets activated when bash is called as sh. From the bash manual page:

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

But in version 5.1 process substitution got re-enabled in POSIX mode

So, for present versions (you are using 4.2 from your now erased self-answer) process substitution works even if bash is called as sh.

5

What is /bin/sh? We're talking about Unix legacy here! A bit of history:

sh is the Bourne Shell, it was released in 1979 in the Version 7 Unix release. It gained popularity with the publication of The Unix Programming Environment by Brian Kernighan and Rob Pike—the first commercially published book that presented the shell as a programming language in a tutorial form.

ksh, the Korn shell originally written by David Korn, was based on the original Bourne Shell source code, it was a middle road between the Bourne shell and csh the C shell. Its syntax was chiefly drawn from the Bourne shell, while its job control features resembled those of the C shell. The functionality of the original Korn Shell was used as a basis for the POSIX shell standard.

bash is the 'Bourne Again SHell'. Bash syntax is a superset of the Bourne shell syntax. Bash syntax includes ideas drawn from the Korn Shell and the C shell such as command line editing, the history command, the directory stack, the $RANDOM and $PPID variables, and POSIX command substitution syntax $(…).

dash is the 'Debian Almquist shell'. It's main priority is POSIX compatibility.

Using hardlinks from bash or dash to sh are used to confine their behaviour to the POSIX standard.

2
  • As far as I've understood, systems where sh would be the legacy Bourne shell and not some POSIX sh compatible one are rather rare.
    – ilkkachu
    Commented Sep 10, 2021 at 13:39
  • Debian Bullseye has sh - symbolic link to dash. The current version of dash is in the process of being changed to conform with the POSIX 1003.2 and 1003.2a specifications for the shell. This version has many features which make it appear similar in some respects to the Korn shell, but it is not a Korn shell clone (see ksh(1)). Only features des‐ ignated by POSIX, plus a few Berkeley extensions, are being incorporated into this shell. Commented Jul 12, 2022 at 15:00
3

An additional point - on Centos 7, sh is a symlink to bash. There is no separate binary for sh .

[root@work ~]# ls -la `which sh`
lrwxrwxrwx. 1 root root 4 Jun 16  2020 /usr/bin/sh -> bash
[root@work ~]# ls -la /bin/sh
lrwxrwxrwx. 1 root root 4 Jun 16  2020 /bin/sh -> bash

[root@work ~]# rpm -qf /usr/bin/sh /bin/sh
bash-4.2.46-34.el7.x86_64

bash, dash, busybox and likely other shells can check the command line they were started with, and will pretend to be something-else like plain sh if that's how they were called. This symlink lets that happen.

You can always expect /bin/sh to be there, and to be a basic shell.

1
  • 1
    Important as downstream distros might alias it to dash. Internally bash can detect the name it was invoked as. The root account might use sh as a default shell, you can change this, but there are reasons for these things.
    – mckenzm
    Commented Sep 9, 2021 at 23:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .