11

I am installing a huge program, which has its resources as an rpm file. It stuck at the line of

#!/bin/sh
SCITEGICPERLBIN=`dirname $0`
SCITEGICPERLHOME=`dirname $SCITEGICPERLBIN`
if [ $SCITEGICPERLHOME == "." ]

Apparently, sh work for bash in Red Hat Linux with this syntax, but it gives the error of unexpected operator in Ubuntu.

I cannot change the script to bash as the script comes from the rpm package. I can extract and repack the rpm package, but there might be many of such scripts.

Is there a way to change the shell default to treat #!/bin/sh as bash or anything else, which can handle the [ operator?

  • 5
    The only thing wrong is the == that should be =. That, and that the variable expansions should be double quoted. – Kusalananda May 8 '18 at 11:29
  • 4
    [ is not an operator, but a builtin command that is called test. The unexpected operator is == and this should be replaced by = because it is not POSIX compliant. – schily May 8 '18 at 11:34
  • The second only thing that is wrong is that $SCITEGICPERLHOME should be quoted. – l0b0 May 8 '18 at 19:35
  • 11
    You should complain to the author of the program. If they use #!/bin/sh, they should make sure they only use POSIX shell features, not bash extensions. This programmer is very sloppy. He should either fix his code or use #!/bin/bash. – Barmar May 8 '18 at 19:44
  • For people wondering about other similar issues here is a list of "Bashisms". Also see this question. – Captain Man May 8 '18 at 23:00
20

There are multiple programs that implement the language of /bin/sh. On Ubuntu, /bin/sh is dash, which is designed to be fast, to use a small amount of memory, and doesn't support much more than the minimum expected from /bin/sh. On RHEL, /bin/sh is bash, which is slower and uses more memory but has more features. One of these features is the == operator for the [ conditional syntax. Dash supports [, which is a basic sh feature, but it doesn't have the == operator which is a bash (and ksh and zsh) extension.

You can switch your system to using bash. On Ubuntu, /bin/sh is a symbolic link to dash. You can make it a symbolic link to bash instead. Current versions of Debian and Ubuntu (and derivatives) make this an installation option of dash. To change it, run

sudo dpkg-reconfigure dash

and answer “yes” to keep dash as /bin/sh or “no” to switch to bash.

You can keep bash as /bin/sh, but it'll make your system a bit slower. It's even conceivable that some system script is incompatible with bash, although that's unlikely since bash is mostly a superset of dash.


For distributions which don't have an interface to choose between implementations of /bin/sh, here's how to switch to bash.

sudo ln -s bash /bin/sh.bash
sudo mv /bin/sh.bash /bin/sh

Keep a terminal open and check that you can still run some sh scripts after that. If you mess up this command, it'll make your system unusable. (By the way, the reason I used the multiple commands above rather than the straightforward-looking sudo ln -sf bash /bin/sh is that ln -sf is not atomic. In the admittedly unlikely case your computer crashed during this operation, you'd need to boot from rescue media to restore it. In contrast, mv is atomic.)

To restore dash as /bin/sh:

sudo ln -s dash /bin/sh.dash
sudo mv /bin/sh.dash /bin/sh

Note that if sh is /bin/bash by default on your distribution, switching to dash may cause scripts to fail, because bash has many more features than dash. Bash scripts should start with #!/bin/bash, and scripts starting with #!/bin/sh should not use bash-specific features, but distributions that ship with bash as /bin/sh may use bash-specific features in #!/bin/sh scripts that are specific to that distribution (it's ok as long as there's no expectation that users can switch to dash as /bin/sh and there's no expectations that these scripts work on another distribution).

  • In my not so humble opinion, if some script fails when /bin/sh is Bash, it's a bug either in the system (the package with the script), or in Bash's sh-mode. Like Stephen says, the system explicitly allows for setting /bin/sh back to Bash, via dpkg-reconfigure. It's also mentioned as a possibility in the Ubuntu wiki on this matter: wiki.ubuntu.com/DashAsBinSh – ilkkachu May 8 '18 at 11:50
  • 5
    @ilkkachu Yes, if a script fails if /bin/sh is bash, it's a bug. However, bugs happen. I recommend sticking to the default if you're not capable and willing to diagnose such bugs because other people have tested it for you. I used dash as /bin/sh before it was officially supported on Debian, but this was a risk I took, knowing that I'd be able to cope if something happened. – Gilles May 8 '18 at 11:55
  • Note that manually overridden symlinks will be restored to whatever configuration is stored in debconf the next time dash is updated; admittedly this won’t happen often (if at all, in a given release) for systems running Debian stable. – Stephen Kitt Sep 11 '18 at 19:17
36

To switch sh to bash (instead of dash, the default), reconfigure dash (yes, it’s somewhat counter-intuitive):

sudo dpkg-reconfigure dash

This will ask whether you want dash to be the default system shell; answer “No” (Tab then Enter) and bash will become the default instead (i.e. /bin/sh will point to /bin/bash).

  • 1
    Your solution is indeed the most reasonable one, but I accepted another answer because of detailed descriptions clarifying the issue. Sorry for any inconvenience. – Googlebot May 8 '18 at 11:52
  • @Googlebot no need to apologise, choosing the accepted answer is the asker’s privilege. And I got a gold badge out of it ;-). – Stephen Kitt May 9 '18 at 14:34

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.