In shell scripts one specifies language interpreter on shebang(#!
) line. As far as I know, it is recommended to use #!/usr/bin/env bash
because env
is always located in /usr/bin
directory while location of bash
may vary from system to system. However, are there any technical differences if bash
is started directly with /bin/bash
or through env
utility? In addition, am I correct that if I do not specify any variables for env
, the bash
is started in unmodified environment?
2 Answers
In one sense, using env
could be considered "portable" in that the path to bash
is not relevant (/bin/bash
, /usr/bin/bash
, /usr/local/bin/bash
, ~/bin/bash
, or whatever path) because it is specified in the environment. In this way, a script author could make his script easier to run on many different systems.
In another sense, using env
to find bash
or any other shell or command interpreter is considered a security risk because an unknown binary (malware) might be used to execute the script. In these environments, and sometimes by managerial policy, the path is specified explicitly with a full path: #!/bin/bash
.
In general, use env
unless you know you are writing in one of these environments that scrutinize the minute details of risk.
When Ubuntu first started using dash
, some time in 2011, many scripts were broken by that action. There was discussion about it on askubuntu.com. Most scripts were written #!/bin/sh
which was a link to /bin/bash
. The consensus was this: the script writer is responsible for specifying the interpreter. Therefore, if your script should always be invoked with BASH, specify it from the environment. This saves you having to guess the path, which is different on various Unix/Linux systems. In addition, it will work if tomorrow /bin/sh
becomes a link to some other shell like /bin/newsh
.
Another difference is that the env
method won't allow the passing of arguments to the interpreter.
-
2Regarding
env
as a security risk to findbash
. Do you mean that if I use#!/usr/bin/env bash
shebang, then bash is searched from my $PATH and for example if my $PATH is "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" and I have a malware namedbash
in/usr/local/sbin
directory(/usr/local/sbin/bash
is executed instead of/usr/bin/bash
because/usr/local/sbin
is before/usr/bin
in $PATH), then this is a security risk?– MartinCommented Jun 4, 2015 at 8:17 -
5Yes, but of more concern, the user's PATH could place the malware first in the PATH. Not every system is so rigorously scrutinized, but, for example, consider a system that has mission-critical services running in an environment where threats could be launched from anywhere. In some environments, like any organization under the DoD, an Information Assurance Officer may flag it while scrutinizing a system that is being tested for its Authority to Operate. Not all vulnerabilities are known, and specifying a full path mitigates the FUD. Commented Jun 4, 2015 at 11:22
-
2
Apart from that using /usr/bin/env
is somewhat slower there is no difference, if you start a program which such a shebang. (Unless /bin/bash
doesn't exists but bash
is somewhere (else) in the PATH)
env
has the possibility to modify the environment of the invoked command, but that can only be used when env
is started from the commandline, with in shebang line (depending on the OS) the options cannot be specified.
The source of env
is rather small so you can verify what it is doing if you are familiar with C. Since execvp
is used to call the program to be executed. There will not even be an env
parent process if you inspect the process tree.
-
So in a nutshell
/usr/bin/env bash
, is exactly the same as to search forbash
from $PATH?– MartinCommented Jun 4, 2015 at 8:31