0

What's the difference between exporting SHELL="/bin/bash" and SHELL="bash"? I previously had export SHELL="bash" in my .bashrc. It seemed to work. $($SHELL) spawned a subshell, but ssh with public key authentication gave the error: Shell "bash" is not executable: No such file or directory

1 Answers1

1

$($SHELL) spawned a subshell

Yes, because in a shell $SHELL (or better "$SHELL") expands to /bin/bash or bash in your case, an both spawn Bash.

Side note: When you use $($SHELL), the output coming from the new shell will be executed after the shell exits because this is how the command substitution ($( … )) works. Command substitution makes little sense here and it's not needed to show your point.

Your point seems to be: when SHELL="bash", "$SHELL" runs Bash, yet some other tool (SSH server?) complains.

It's not clear what tool complains. And you did not tell us if SHELL is tampered with on the client side or on the server side. There is no mcve in the question. It's also not clear why you need to set SHELL in .bashrc. I'm not going to investigate any of these.

I'm going to tell you about SHELL and the difference between /bin/bash and bash in general.

The purpose of the SHELL environment variable is to point to the shell you want to use. Various software can use the variable (if set) to try to run your chosen shell for whatever reason. The difference you observed occurs because some programs rely on the PATH environment variable, some don't.

The reliance on PATH works as follows. There's a string that "encodes" what executable to run. E.g. the string may be /bin/bash, foo/bash or bash. There are two cases:

  1. If the string contains / then the string itself is interpreted as an absolute path (e.g. /bin/bash) or a relative path (e.g. foo/bash) to the executable.
  2. If the string does not contain / (e.g. bash) then it only specifies the basename of the executable. The rest of the path (i.e. directory component(s)) comes from PATH. Basically it's the first directory specified in PATH that contains an executable with the specified basename. Depending on PATH, bash can be resolved as /bin/bash, /home/you/bin/bash, ./bash (rarely) or not at all (giving you command not found or similar error).

Shells rely on PATH, therefore in a shell bash (typed literally or appearing from the expansion of $SHELL or whatever) finds /bin/bash or /some/other/path/to/bash in a sanely configured system.

Tools that don't rely on PATH treat the string as a path (pathname). This makes no difference for a string containing /. It makes a huge difference for a string not containing /. If the string is bash and it's interpreted directly as a path, it's equivalent to ./bash which means "file named bash in the current working directory".

Whatever gave you the error apparently retrieved the content of the SHELL variable and used it as a path without relying on the PATH variable.

This was the right thing to do. Note POSIX specifies SHELL as:

This variable shall represent a pathname of the user's preferred command language interpreter.

Investigate "pathname" and "pathname resolution", these do not rely on PATH. Any tool that uses the SHELL variable shall treat its content directly as a pathname.

When SHELL="bash", in a shell "$SHELL" runs Bash only because $SHELL expands like any other variable and then bash is treated like any other command not containing /. So it's kinda incidental.

If I interpret the POSIX documentation right, you should use SHELL="bash" only if you mean SHELL="./bash". Even if you mean this, it's better to use a path with /, so the mechanics in a shell where PATH can be used does not interfere with how SHELL shall be interpreted.

Most likely you don't want ./bash. You want /bin/bash so use exactly this.