To run a non-executable sh
script, use:
(要运行不可执行的sh
脚本,请使用:)
sh myscript
To run a non-executable bash
script, use:
(要运行不可执行的bash
脚本,请使用:)
bash myscript
To start an executable (which is any file with executable permission);
(启动可执行文件(任何具有可执行权限的文件);)
you just specify it by its path: (你只需按路径指定:)
/foo/bar
/bin/bar
./bar
To make a script executable, give it the necessary permission:
(要使脚本可执行,请为其提供必要的权限:)
chmod +x bar
./bar
When a file is executable, the kernel is responsible for figuring out how to execte it.
(当文件可执行时, 内核负责确定如何执行它。)
For non-binaries, this is done by looking at the first line of the file. (对于非二进制文件,可以通过查看文件的第一行来完成。)
It should contain a hashbang
: (它应该包含一个hashbang
:)
#! /usr/bin/env bash
The hashbang tells the kernel what program to run (in this case the command /usr/bin/env
is ran with the argument bash
).
(hashbang告诉内核要运行什么程序(在这种情况下,使用参数bash
运行命令/usr/bin/env
)。)
Then, the script is passed to the program (as second argument) along with all the arguments you gave the script as subsequent arguments. (然后,脚本将作为后续参数传递给程序(作为第二个参数)以及您为脚本提供的所有参数。)
That means every script that is executable should have a hashbang .
(这意味着每个可执行的脚本都应该有一个hashbang 。)
If it doesn't, you're not telling the kernel what it is , and therefore the kernel doesn't know what program to use to interprete it. (如果没有,你就不会告诉内核它是什么,因此内核不知道用什么程序来解释它。)
It could be bash
, perl
, python
, sh
, or something else. (它可能是bash
, perl
, python
, sh
或其他东西。)
(In reality, the kernel will often use the user's default shell to interprete the file, which is very dangerous because it might not be the right interpreter at all or it might be able to parse some of it but with subtle behavioural differences such as is the case between sh
and bash
). ((实际上,内核通常会使用用户的默认shell来解释文件,这非常危险,因为它可能根本不是正确的解释器,或者它可能能够解析其中的一些但是具有微妙的行为差异,例如sh
和bash
之间的情况)。)
A note on /usr/bin/env
(/usr/bin/env
上的注释)
Most commonly, you'll see hash bangs like so:
(最常见的是,你会看到像这样的哈希爆炸:)
#!/bin/bash
The result is that the kernel will run the program /bin/bash
to interpret the script.
(结果是内核将运行program /bin/bash
来解释脚本。)
Unfortunately, bash
is not always shipped by default, and it is not always available in /bin
. (不幸的是,默认情况下bash
并不总是出货,并且在/bin
并不总是可用。)
While on Linux machines it usually is, there are a range of other POSIX machines where bash
ships in various locations, such as /usr/xpg/bin/bash
or /usr/local/bin/bash
. (在Linux机器上通常是,有一系列其他POSIX机器,其中bash
在不同的位置发货,例如/usr/xpg/bin/bash
或/usr/local/bin/bash
。)
To write a portable bash script, we can therefore not rely on hard-coding the location of the bash
program.
(因此,为了编写可移植的bash脚本,我们可以不依赖于对bash
程序的位置进行硬编码。)
POSIX already has a mechanism for dealing with that: PATH
. (POSIX已经有了一个处理它的机制: PATH
。)
The idea is that you install your programs in one of the directories that are in PATH
and the system should be able to find your program when you want to run it by name. (我们的想法是,您将程序安装在PATH
中的一个目录中,并且当您希望按名称运行程序时,系统应该能够找到您的程序。)
Sadly, you cannot just do this:
(可悲的是,你不能这样做:)
#!bash
The kernel won't (some might) do a PATH
search for you.
(内核不会(有些人可能)为您进行PATH
搜索。)
There is a program that can do a PATH
search for you, though, it's called env
. (有一个程序可以为你做一个PATH
搜索,但它叫做env
。)
Luckily, nearly all systems have an env
program installed in /usr/bin
. (幸运的是,几乎所有系统都在/usr/bin
安装了一个env
程序。)
So we start env
using a hardcoded path, which then does a PATH
search for bash
and runs it so that it can interpret your script: (所以我们使用硬编码路径启动env
,然后对bash
进行PATH
搜索并运行它以便它可以解释你的脚本:)
#!/usr/bin/env bash
This approach has one downside: According to POSIX, the hashbang can have one argument .
(这种方法有一个缺点:根据POSIX,hashbang可以有一个参数 。)
In this case, we use bash
as the argument to the env
program. (在这种情况下,我们使用bash
作为env
程序的参数。)
That means we have no space left to pass arguments to bash
. (这意味着我们没有空间将参数传递给bash
。)
So there's no way to convert something like #!/bin/bash -exu
to this scheme. (所以没有办法将#!/bin/bash -exu
这样的东西转换成这个方案。)
You'll have to put set -exu
after the hashbang instead. (你必须在set -exu
之后放置set -exu
。)
This approach also has another advantage: Some systems may ship with a /bin/bash
, but the user may not like it, may find it's buggy or outdated, and may have installed his own bash
somewhere else.
(这种方法还有另一个优点:某些系统可能附带/bin/bash
,但用户可能不喜欢它,可能会发现它有缺陷或过时,并且可能已在其他地方安装了自己的bash
。)
This is often the case on OS X (Macs) where Apple ships an outdated /bin/bash
and users install an up-to-date /usr/local/bin/bash
using something like Homebrew. (在OS X(Macs)上经常出现这种情况,其中Apple发布了过时的/bin/bash
,用户使用Homebrew之类的东西安装了最新的/usr/local/bin/bash
。)
When you use the env
approach which does a PATH
search, you take the user's preference into account and use his preferred bash over the one his system shipped with. (当你使用执行PATH
搜索的env
方法时,你会考虑用户的偏好并使用他喜欢的bash而不是他的系统附带的bash。)