3

My apologies as this has to be a question others have asked but it seems google proof. I'm trying to figure out what shell is being invoked as I have met an inconsistency. My script doesn't work if I sudo, but does work if I sudo bash. Yet when I sudo echo $0, it says bash.

cpu=$(cat /proc/cpuinfo | grep Revision | cut -d' ' -f 2-);
if [[ "a22082" = $cpu || "a02082" = $cpu ]]; then
    echo 'do stuff';
fi

If I specify the command interpreter with #!/bin/sh it still fails but being more specific #!/bin/bash it does.

I (now) know that [[ is bash specific but despite the response it doesn't seem like sudo's default shell is bash.

Peter Oehlert
  • 16,368
  • 6
  • 44
  • 48
  • `sudo echo $(SHELL)` ? Perhaps that might help – Ed Heal Jun 14 '16 at 16:41
  • 1
    Wait, I'm assuming that `sh` and `bash` aren't the same shell. Why would you expect it to work when you're specifying the wrong shell? – Hasturkun Jun 14 '16 at 16:42
  • 2
    I always found it personally to me to put `#!/bin/sh` for the shebang and found it better practice to put the exact shell to use. – jgr208 Jun 14 '16 at 16:43
  • @Hasturkun `sh` says use the default system shell, `bash` says to use the bash shell – jgr208 Jun 14 '16 at 16:43
  • @EdHeal, I just tried to do this on Mac OS (the question's about Linux, but still), and bash seems to execute `$(SHELL)` _before `sudo`_ as I first got `-bash: SHELL: command not found` and only then - a prompt to input a password. So I guess that bash is running `$(SHELL)` without `sudo`. – ForceBru Jun 14 '16 at 16:44
  • 1
    @jgr208: `sh` is a Bourne Shell (compatible) shell, `bash` is the Bourne Again Shell, which has it's own features. See http://stackoverflow.com/a/5725402 . My point is that if you're using `bash` features, use `#!/bin/bash` – Hasturkun Jun 14 '16 at 16:45
  • Perhaps I should have put some quotes in – Ed Heal Jun 14 '16 at 16:45
  • Perhaps `sudo env` or `sudo set` – Ed Heal Jun 14 '16 at 16:46
  • 2
    just put shebang like `#!/bin/bash` or `#!/usr/bin/env bash` at the beginning of your script and everything will work. – sotona Jun 14 '16 at 17:10

2 Answers2

15

Short answer: There is no default interpreter. Your script needs a shebang line #!/bin/bash at the top.

Long answer: sudo does not run a shell. It runs the command you pass it directly, no intermediate shell. If you want a shell you need to explicitly pass it one.

sudo echo $0

This command is misleading due to $0 being expanded by your shell before sudo is called. It's printing your current $0, not the value of $0 inside the sudo'd environment.

Let's compare some commands:

  • sudo ls

    This executes the /bin/ls executable directly. There's no shell involved. The following commands will show when the distinction comes into play.

  • sudo ls /root/*

    The current shell expands the glob. If you can't access /root/ then the glob isn't expanded and you get ls: cannot access /root/*: No such file or directory.

  • sudo 'ls /root/*'

    This attempts to execute a program called ls /root/*. Literally, it's named * in the root sub-directory of ls  (ls with a trailing space). It fails with sudo: ls /root/*: command not found.

  • sudo ls '/root/*'

    This runs /bin/ls and passes it the literal string /root/*. There's no glob expansion. It fails with ls: cannot access /root/*: No such file or directory.

  • sudo bash -c 'ls /root/*'

    This executes /bin/bash and has it interpolate the ls /root/* command-line, expanding the glob. This one, finally, works, because we have an explicit shell to expand the glob, and we're doing the expansion within sudo instead of outside of it.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
5

To complement John Kugelman's helpful answer by addressing the more general question implied by the post's title:

On a side note: It's best to always start your scripts with a shebang line to explicitly control what shell it is run by.

sudo doesn't run a shell by default, but can be made to run one with either of the following options:

  • -s (non-login shell)
    • uses the shell specified via the $SHELL environment variable, if defined, otherwise the shell defined in the user's password database entry (/etc/passwords)
  • -i (login shell, always uses the shell from the user's )
    • uses the shell defined in the user's password database entry

In other words: sudo uses the current user's default shell, unless, for -s only, overridden via $SHELL.

See man sudo for details.

mklement0
  • 382,024
  • 64
  • 607
  • 775