如何正确运行Shell脚本
by CUNOE, August 8, 2023
起因
我的一位朋友在 Ubuntu 通过 sh test.sh
运行一个 Shell 脚本时解释器弹出如下错误:
> test.sh: 12: Syntax error: "(" unexpected
对于这个问题,我直接让他通过 bash test.sh
来执行这个脚本便正常运行了。
下面将解释为什么在 Ubuntu 通过 sh test.sh
运行一个 Shell 脚本时解释器弹出 Syntax error
。
在查阅了相关资料后,可以发现现在的 Ubuntu 将 sh
这个命令通过符号链接到 /bin/dash
,故这位朋友通过 sh test.sh
运行脚本时实际上是执行了 /bin/dash test.sh
这个命令,而 /bin/dash
这个解释器的语法和该脚本使用的 /bin/bash
解释器的语法并不一致,导致了解释器报语法错误。
当我们遇到这种情况时应该如何解决呢?下面将记录我对执行 Shell 脚本的理解。
运行 Shell 脚本的方式
下面将以
test.sh
脚本为例
通过可执行文件方式执行
这是一种常用的执行方式,你需要为脚本添加可执行权限,执行方式如下:
chmod +x test.sh
./test.sh
这里需要注意不要遗漏了
./
,否则系统会去PATH
里寻找有没有叫test.sh
的可执行程序,而只有/bin
、/sbin
、/usr/bin
等目录在PATH
里,当前脚本所在目录通常不在PATH
里,所以写成test.sh
是会找不到命令的,要用./test.sh
告诉系统说,就在当前目录找。
通过这种方式执行的 Shell 脚本,系统会读取脚本第一行的 #!
标记后定义的 解释器
来执行该脚本。
不知道什么是
#!
标记的请向下👇🏻翻
作为解释器参数执行
直接运行解释器,其参数就是 Shell 脚本的文件名,如
/bin/bash test.sh
通过这种方式执行的 Shell 脚本,系统将会忽略脚本第一行的 #!
标记后定义的 解释器
,而使用你选择的解释器来执行,本例中即为 /bin/bash
。
Shell 脚本头的 #! (shebang) 标记
基础知识
首先,#!
标记是一个约定的标记。
一个正经的 Shell 脚本一般都会在其第一行的位置添加 #!
标记,并在后方跟随该脚本使用的 解释器
,例如常见的 /bin/bash
或 /bin/sh
。
这个标记将在通过 ./test.sh
方式执行时告诉系统内核需要调用的 解释器
。
如果标记后跟随的是 /bin/bash
,则作为可执行文件执行该脚本时实际执行的命令为 /bin/bash test.sh
; 如果标记后跟随的是 /bin/cat
,则作为可执行文件执行该脚本时实际执行的命令为 /bin/cat test.sh
#!/usr/bin/env 又是什么鬼?
在一些脚本里面,你可能会遇到标记为 #!/usr/bin/env bash
的脚本,这种用法实际上是使用了 Unix 系统里的 env
功能。
在使用 /usr/bin/env bash
时,将会在 PATH
里寻找 bash
解释器,而后根据寻找到的第一个 bash
解释器来执行该脚本。这种使用方法将增加脚本的 可移植性
,防止某些系统的 解释器
不在 /bin
文件夹下导致的无法找到 bash
而执行不了脚本。
这种使用方式可以用于编写 python
、nodejs
等脚本,即使用 #!/usr/bin/env python3
、#!/usr/bin/env node
。
一定要用 #! 标记吗?
是的,为了自己,也为了他人!