Bash shebang {`#!`}
1. Bash
The Bourne shell (sh
) is a shell command-line interpreter for computer operating systems.
Bash is a Unix shell and command language written by Brian Fox for the GNU Project as a free software replacement for the Bourne shell (sh
).
Bash 是一个命令处理器,通常运行于文本窗口中,并能执行用户直接输入的命令。
The shell’s name is an acronym for Bourne Again Shell, a pun on the name of the Bourne shell (sh
) that it replaces and the notion of being “born again”.
Bash 是 Bourne shell 的后继兼容版本与开放源代码版本,它的名称来自 Bourne shell (sh
) 的一个双关语 Bourne Again SHell。
pun [pʌn]:n. 双关语 vi. 使用双关语
操作系统支持 Shell 的类型:
(base) yongqiang@yongqiang:~$ cat /etc/shells
# /etc/shells: valid login shells
/bin/sh
/bin/bash
/bin/rbash
/bin/dash
/usr/bin/tmux
/usr/bin/screen
(base) yongqiang@yongqiang:~$
Bash 的绝对路径:
(base) yongqiang@yongqiang:~$ which bash
/bin/bash
(base) yongqiang@yongqiang:~$
2. shebang
In computing, a shebang is the character sequence consisting of the characters number sign and exclamation mark (#!
) at the beginning of a script. It is also called sharp-exclamation, sha-bang, hashbang, pound-bang, or hash-pling.
shebang 是一个由井号和叹号构成的字符序列 #!
,其出现在文本文件的第一行的前两个字符。
The shebang line is usually ignored by the interpreter, because the #
character is a comment marker in many scripting languages; some language interpreters that do not use the hash mark to begin comments still may ignore the shebang line in recognition of its purpose.
由于 #
符号在许多脚本语言中都是注释标识符,shebang 的内容会被这些脚本解释器自动忽略。在 #
字符不是注释标识符的语言中,解释器也可能忽略以 #!
开头的首行内容,以提供与 shebang 的兼容性。
The name shebang for the distinctive two characters may have come from an inexact contraction of SHArp bang or haSH bang, referring to the two typical Unix names for them. Another theory on the sh
in shebang is that it is from the default shell sh
, usually invoked with shebang.
shebang 的名字来自于 SHArp bang or haSH bang 的缩写,指代 shebang 中 #!
两个符号的典型 Unix 名称。在 Unix 术语中,井号通常称为 sharp, hash or mesh;而叹号则常常称为 bang。
contraction [kənˈtrækʃn]:n. 收缩,缩小,(肌肉的) 收缩,挛缩,子宫收缩,词的缩约形式
bang [bæŋ]:v. 猛敲,砸,(把 ...) 砰的关上,猛摔,砰地一扔,碰撞,和 (女性) 性交 n. 突然的巨响,(对身体部位的) 猛撞,猛敲,猛击,叹号 adv. 正好,完全地 int. (表示枪声等巨响) 砰
2.1. Syntax
The form of a shebang interpreter directive is as follows:
#!interpreter [optional-arg]
in which interpreter is generally an absolute path to an executable program. The optional argument is a string representing a single argument. White space after #!
is optional.
shebang 由 #!
开头,即井号和叹号。在 #!
开头字符之后,可以有 0 个,1 个或多个空白字符,后接解释器的绝对路径,用于调用解释器。
#!
字符称为 shebang,后接脚本解释器,脚本解释器一般是 /bin/sh
或 /bin/bash
。
#!/bin/sh
或者
#!/bin/bash
Interpreter directives allow scripts and data files to be used as commands, hiding the details of their implementation from users and other programs, by removing the need to prefix scripts with their interpreter on the command line.
解释器指令允许脚本和数据文件充当系统命令,无需在调用时由用户指定解释器,从而对用户和其它程序隐藏其实现细节。
exclamation [.eksklə'meɪʃ(ə)n]:n. 感叹,感叹词,感叹语
#!
is followed by /usr/bin/env
, followed by the desired command without full path, as in this example:
#!/usr/bin/env sh
This mostly works because the path /usr/bin/env
is commonly used for the env
utility, and it invokes the first sh
found in the user’s $PATH
, typically /bin/sh
.
使用 #!/usr/bin/env sh
脚本解释器名称是一种常见的在不同平台上都能正确找到解释器的办法。
如果脚本解释器不放在目录 /bin
,则脚本就无法执行了。为了保险起见,可以写成 #!/usr/bin/env bash
,使用 env
命令 (总是在 /usr/bin
目录),返回 Bash 可执行文件的位置。
2.2. env
(user command) - run a program in a modified environment (在修改后的环境中运行命令)
env
命令用于显示系统中已存在的环境变量,以及在定义的环境中执行指令。env
命令只使用 -
作为参数选项时,隐藏了选项 -i
的功能。若没有设置任何选项和参数时,则直接显示当前的环境变量。
environment,env:环境变量
env
命令总是指向 /usr/bin/env
文件,/usr/bin/env
二进制文件总是在目录 /usr/bin/
。
#!/usr/bin/env NAME
的意思是,让 shell 查找 $PATH
环境变量里面第一个匹配的 NAME
。如果不知道某个命令的具体路径,或者希望兼容其他用户的机器,请使用这种写法。
#!/usr/bin/env bash
返回 bash
可执行文件的位置,前提是 bash
的路径是在 $PATH
里面。
env
命令的参数如下:
-i, --ignore-environment
: start with an empty environment (开始一个新的空的环境)
-u, --unset=NAME
: remove variable from the environment (从当前环境中删除指定的变量)
-C, --chdir=DIR
: change working directory to DIR
-0, --null
: end each output line with NUL
, not newline
--help
: display this help and exit
--version
: output version information and exit
- 系统的环境变量
(base) yongqiang@yongqiang:~$ env
...
CONDA_EXE=/home/yongqiang/miniconda3/bin/conda
CONDA_PREFIX=/home/yongqiang/miniconda3
USER=yongqiang
PWD=/home/yongqiang
HOME=/home/yongqiang
CONDA_PYTHON_EXE=/home/yongqiang/miniconda3/bin/python
NAME=yongqiang
...
(base) yongqiang@yongqiang:~$
(base) yongqiang@yongqiang:~$ echo ${NAME}
yongqiang
(base) yongqiang@yongqiang:~$
(base) yongqiang@yongqiang:~$ echo ${SHELL}
/bin/bash
(base) yongqiang@yongqiang:~$
(base) yongqiang@yongqiang:~$ env | egrep -i "pwd|hosttype"
HOSTTYPE=x86_64
PWD=/home/yongqiang
(base) yongqiang@yongqiang:~$
- 从当前环境中删除指定的变量
$ env -u USER
- 定义指定的环境变量
在新的环境中定义变量,定义多个变量用空格隔开,格式为“变量名=值”。临时设置环境变量,常用于设置环境变量 PATH
。
$ env NAME=root
- 新建一个不带任何环境变量的 shell
$ env -i /bin/sh
2.3. Examples
Some typical shebang lines:
#!/bin/sh
- Execute the file using the Bourne shell, or a compatible shell, assumed to be in the/bin
directory#!/bin/bash
- Execute the file using the Bash shell#!/usr/bin/pwsh
- Execute the file using PowerShell#!/usr/bin/env python3
- Execute with a Python interpreter, using theenv
program search path to find it#!/bin/false
- Do nothing, but return a non-zero exit status, indicating failure.
For example, if a script is named with the path path/to/script
, and it starts with the following line, #!/bin/sh
, then the program loader is instructed to run the program /bin/sh
, passing path/to/script
as the first argument.
#!/bin/sh
作为行开头,程序加载器运行程序 /bin/sh
,传递 path/to/script
作为第一个参数。
3. yongqiang
脚本 (script) 是包含一系列命令的文本文件。shell 读取脚本,依次执行里面的所有命令,脚本的好处是可以重复使用。
- 工作区
/home/yongqiang/bash_work
(base) yongqiang@yongqiang:~$ mkdir bash_work
(base) yongqiang@yongqiang:~$ cd bash_work/
touch
命令创建一个空文件bash_script.sh
(base) yongqiang@yongqiang:~/bash_work$ touch bash_script.sh
(base) yongqiang@yongqiang:~/bash_work$ ll
total 0
drwxr-xr-x 1 yongqiang yongqiang 512 Apr 23 22:18 ./
drwxr-xr-x 1 yongqiang yongqiang 512 Apr 23 22:16 ../
-rw-r--r-- 1 yongqiang yongqiang 0 Apr 23 22:18 bash_script.sh
(base) yongqiang@yongqiang:~/bash_work$
#!
指定解释器的绝对路径/bin/bash
(base) yongqiang@yongqiang:~/bash_work$ vim ./bash_script.sh
(base) yongqiang@yongqiang:~/bash_work$
(base) yongqiang@yongqiang:~/bash_work$ cat ./bash_script.sh
#!/bin/bash
echo "Yongqiang Cheng!"
(base) yongqiang@yongqiang:~/bash_work$
- 添加执行权限并执行
阅读权限 (r
):允许查看文件内容
写入权限 (w
):允许修改文件内容
执行权限 (x
):允许运行编程文件或脚本
脚本需要有执行权限,才可以执行。脚本的权限通常设为 755
(拥有者有所有权限,其他人有读和执行权限) 或者 700
(只有拥有者可以执行)。
# 所有用户赋予执行权限
$ chmod a+x bash_script.sh
# 所有用户赋予读权限和执行权限
$ chmod a+rx bash_script.sh
$ chmod 755 bash_script.sh
# 脚本拥有者赋予读权限和执行权限
$ chmod u+rx bash_script.sh
(base) yongqiang@yongqiang:~/bash_work$ chmod a+x ./bash_script.sh
(base) yongqiang@yongqiang:~/bash_work$
(base) yongqiang@yongqiang:~/bash_work$ ./bash_script.sh
Yongqiang Cheng!
(base) yongqiang@yongqiang:~/bash_work$
shebang
行不是必需的,但是建议加上。如果缺少 shebang
行,就需要手动将脚本传给解释器。脚本是 bash_script.sh
,有 shebang
行的时候,可以直接调用执行。
$ ./bash_script.sh
bash_script.sh
是脚本文件名,通常使用 .sh
后缀名,不过这不是必需的。
如果没有 shebang
行,就只能手动将脚本传给解释器来执行。下面的执行方式不需要在第一行指定解释器信息。
(base) yongqiang@yongqiang:~/bash_work$ /bin/bash bash_script.sh
Yongqiang Cheng!
(base) yongqiang@yongqiang:~/bash_work$
$ /bin/sh ./bash_script.sh
或者
$ bash ./bash_script.sh
脚本调用时,需要指定脚本的路径 (/path/bash_script.sh
)。如果将脚本放在环境变量 $PATH
指定的目录中,就不需要指定路径了。因为 Bash 会自动到这些目录中,寻找是否存在同名的可执行文件。在主目录新建一个 ~/bin
子目录,存放可执行脚本,然后把 ~/bin
加入 $PATH
。
export PATH=$PATH:~/bin
上面命令改变环境变量 $PATH
,将 ~/bin
添加到 $PATH
的末尾。将这一行加到 ~/.bashrc
文件里面,重新加载一次 .bashrc
,确保配置生效。
$ source ~/.bashrc
不管在什么目录,直接输入脚本文件名,脚本就会执行。下面的命令没有指定脚本路径,可以正常执行,因为 bash_script.sh
在 $PATH
指定的目录中。
$ bash_script.sh
4. GNU Bourne-Again SHell - bash
GNU Bash
https://www.gnu.org/software/bash/
GNU Bash manual
https://www.gnu.org/software/bash/manual/
Bash Reference Manual
https://www.gnu.org/software/bash/manual/bash.html
GNU Manuals Online
https://www.gnu.org/manual/
The GNU Bourne-Again SHell
https://tiswww.case.edu/php/chet/bash/bashtop.html
Bash is the GNU Project’s shell - the Bourne Again SHell. This is an sh
-compatible shell that incorporates useful features from the Korn shell (ksh
) and the C shell (csh
). It is intended to conform to the IEEE POSIX P1003.2/ISO 9945.2 Shell and Tools standard.
General Commands Manual - BASH
(base) yongqiang@yongqiang:~$ info bash
...
(base) yongqiang@yongqiang:~$ man bash
...
(base) yongqiang@yongqiang:~$ bash --help
GNU bash, version 4.4.20(1)-release-(x86_64-pc-linux-gnu)
Usage: bash [GNU long option] [option] ...
bash [GNU long option] [option] script-file ...
GNU long options:
--debug
--debugger
--dump-po-strings
--dump-strings
--help
--init-file
--login
--noediting
--noprofile
--norc
--posix
--rcfile
--restricted
--verbose
--version
Shell options:
-ilrsD or -c command or -O shopt_option (invocation only)
-abefhkmnptuvxBCHP or -o option
Type `bash -c "help set"' for more information about shell options.
Type `bash -c help' for more information about shell builtin commands.
Use the `bashbug' command to report bugs.
bash home page: <http://www.gnu.org/software/bash>
General help using GNU software: <http://www.gnu.org/gethelp/>
(base) yongqiang@yongqiang:~$
(base) yongqiang@yongqiang:~$ ls -l /usr/share/doc/bash/
total 84
-rw-r--r-- 1 root root 7853 Sep 8 2016 COMPAT.gz
-rw-r--r-- 1 root root 2921 Feb 18 1999 INTRO.gz
-rw-r--r-- 1 root root 27983 Aug 23 2016 NEWS.gz
-rw-r--r-- 1 root root 3702 May 10 2016 POSIX.gz
-rw-r--r-- 1 root root 1693 Jun 7 2019 RBASH
-rw-r--r-- 1 root root 3839 Jun 7 2019 README
-rw-r--r-- 1 root root 1919 Jun 7 2019 README.Debian.gz
-rw-r--r-- 1 root root 1105 Jun 7 2019 README.abs-guide
-rw-r--r-- 1 root root 3021 Jun 7 2019 README.commands.gz
lrwxrwxrwx 1 root root 31 Apr 2 2018 README.md.bash_completion.gz -> ../bash-completion/README.md.gz
-rw-r--r-- 1 root root 1357 Jun 7 2019 changelog.Debian.gz
-rw-r--r-- 1 root root 10231 Jun 7 2019 copyright
-rw-r--r-- 1 root root 727 Jun 7 2019 inputrc.arrows
(base) yongqiang@yongqiang:~$
References
[1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/
[2] Bourne shell, https://en.wikipedia.org/wiki/Bourne_shell
[3] Bash (Unix shell), https://en.wikipedia.org/wiki/Bash_(Unix_shell)
[4] Shebang (Unix), https://en.wikipedia.org/wiki/Shebang_(Unix)
[5] Bash 教程总览, https://www.w3cschool.cn/bashshell/
[6] Bash 脚本教程, https://wangdoc.com/bash/index.html