Linux usr bin bash

What is the difference between «#!/usr/bin/env bash» and «#!/usr/bin/bash»?

When I consulted the env man page, I get this definition:

 env - run a program in a modified environment 

Who can tell me why this question is closed, » related to programming or software development» isen’t ?

This question should not have been marked as off-topic. It just needs 5 people with above a score of 3000 to mark it as «on-topic» and it can be reopened. It is a question — specifically about programming.

I’m shocked. Shocked to find that Linux documentation is rife with tautologies. xkcd.com/703 git-man-page-generator.lokaltog.net

One major difference is that, depending on the system, #!/usr/bin/bash won’t work. On my system (Ubuntu 17.04), bash is /bin/bash , and there is no /usr/bin/bash . The distinction between /bin and /usr/bin is largely arbitrary. And just to add to the frivolity, most systems put the env command in /usr/bin , but that’s not guaranteed.

6 Answers 6

Running a command through /usr/bin/env has the benefit of looking for whatever the default version of the program is in your current environment.

This way, you don’t have to look for it in a specific place on the system, as those paths may be in different locations on different systems. As long as it’s in your path, it will find it.

One downside is that you will be unable to pass more than one argument (e.g. you will be unable to write /usr/bin/env awk -f ) if you wish to support Linux, as POSIX is vague on how the line is to be interpreted, and Linux interprets everything after the first space to denote a single argument. You can use /usr/bin/env -S on some versions of env to get around this, but then the script will become even less portable and break on fairly recent systems (e.g. even Ubuntu 16.04 if not later).

Another downside is that since you aren’t calling an explicit executable, it’s got the potential for mistakes, and on multiuser systems security problems (if someone managed to get their executable called bash in your path, for example).

#!/usr/bin/env bash #lends you some flexibility on different systems #!/usr/bin/bash #gives you explicit control on a given system of what executable is called 

In some situations, the first may be preferred (like running python scripts with multiple versions of python, without having to rework the executable line). But in situations where security is the focus, the latter would be preferred, as it limits code injection possibilities.

Читайте также:  Mr robot theme linux

@KeithThompson : Incorrect info.. You can pass options to the underlying interpreter using /usr/bin/env!

@GauravAgarwal: Not on my system. A script containing just this single line: #!/usr/bin/env echo Hello complains: /usr/bin/env: echo Hello: No such file or directory . Apparently it treats echo Hello as a single argument to /usr/bin/env .

@AndréLaszlo: The env command certainly allows arguments to be passed to the command. The issue is the semantics of the #! line, and that depends on the kernel. Recent Linux kernels do allow things like #!/usr/bin/env command args , but older Linux kernels and other systems don’t.

Using #!/usr/bin/env NAME makes the shell search for the first match of NAME in the $PATH environment variable. It can be useful if you aren’t aware of the absolute path or don’t want to search for it.

Excellent answer. Explains succinctly what the env shebang does, rather than saying «chooses the program based on your system configuration»

Here is the situation I encountered. When I run the command «./script.sh» with «#!/usr/bin/env bash» in the first line of script.sh, it gives a feedback of «-bash: ./tools/dist_train.sh: Permission denied». When I run the command «bash ./script.sh». It can work well. Could you tell me why «#!/usr/bin/env NAME» doesn’t work.

@EricKani: Most likely your «./script.sh» does have its executable flag unchecked (so you can’t execute it on its own). «bash ./script.sh» happily accepts non-executable script files. (Solution: chmod +x ./script.sh )

If the shell scripts start with #!/bin/bash , they will always run with bash from /bin . If they however start with #!/usr/bin/env bash , they will search for bash in $PATH and then start with the first one they can find.

Why would this be useful? Assume you want to run bash scripts, that require bash 4.x or newer, yet your system only has bash 3.x installed and currently your distribution doesn’t offer a newer version or you are no administrator and cannot change what is installed on that system.

Of course, you can download bash source code and build your own bash from scratch, placing it to ~/bin for example. And you can also modify your $PATH variable in your .bash_profile file to include ~/bin as the first entry ( PATH=$HOME/bin:$PATH as ~ will not expand in $PATH ). If you now call bash , the shell will first look for it in $PATH in order, so it starts with ~/bin , where it will find your bash . Same thing happens if scripts search for bash using #!/usr/bin/env bash , so these scripts would now be working on your system using your custom bash build.

Читайте также:  Линукс ссылки на файлы

One downside is, that this can lead to unexpected behavior, e.g. same script on the same machine may run with different interpreters for different environments or users with different search paths, causing all kind of headaches.

The biggest downside with env is that some systems will only allow one argument, so you cannot do this #!/usr/bin/env , as the systems will see as one argument (they will treat it as if the expression was quoted) and thus env will search for an interpreter named . Note that this is not a problem of the env command itself, which always allowed multiple parameters to be passed through but with the shebang parser of the system that parses this line before even calling env . Meanwhile this has been fixed on most systems but if your script wants to be ultra portable, you cannot rely that this has been fixed on the system you will be running.

It can even have security implications, e.g. if sudo was not configured to clean environment or $PATH was excluded from clean up. Let me demonstrate this:

Usually /bin is a well protected place, only root is able to change anything there. Your home directory is not, though, any program you run is able to make changes to it. That means malicious code could place a fake bash into some hidden directory, modify your .bash_profile to include that directory in your $PATH , so all scripts using #!/usr/bin/env bash will end up running with that fake bash . If sudo keeps $PATH , you are in big trouble.

E.g. consider a tool creates a file ~/.evil/bash with the following content:

#!/bin/bash if [ $EUID -eq 0 ]; then echo "All your base are belong to us. " # We are root - do whatever you want to do fi /bin/bash "$@" 

Let’s make a simple script sample.sh :

#!/usr/bin/env bash echo "Hello World" 

Proof of concept (on a system where sudo keeps $PATH ):

$ ./sample.sh Hello World $ sudo ./sample.sh Hello World $ export PATH="$HOME/.evil:$PATH" $ ./sample.sh Hello World $ sudo ./sample.sh All your base are belong to us. Hello World 

Usually the classic shells should all be located in /bin and if you don’t want to place them there for whatever reason, it’s really not an issue to place a symlink in /bin that points to their real locations (or maybe /bin itself is a symlink), so I would always go with #!/bin/sh and #!/bin/bash . There’s just too much that would break if these wouldn’t work anymore. It’s not that POSIX would require these position (POSIX does not standardize path names and thus it doesn’t even standardize the shebang feature at all) but they are so common, that even if a system would not offer a /bin/sh , it would probably still understand #!/bin/sh and know what to do with it and may it only be for compatibility with existing code.

Читайте также:  Virtualbox установить плагин linux

But for more modern, non standard, optional interpreters like Perl, PHP, Python, or Ruby, it’s not really specified anywhere where they should be located. They may be in /usr/bin but they may as well be in /usr/local/bin or in a completely different hierarchy branch ( /opt/. , /Applications/. , etc.). That’s why these often use the #!/usr/bin/env xxx shebang syntax.

Источник

What is the difference if I start bash with «/bin/bash» or «/usr/bin/env bash»? [duplicate]

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 2

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.

Источник

Оцените статью
Adblock
detector