linux脚本中 #!/bin/sh、#!/bin/bash

我们通常看到的脚本文件总是有以下这样的开头:

复制代码
#!/bin/bash

本文解释一下这是什么,以及为什么要写它。

首先解释一下 #! ,因为 #!有个专有的名词,叫 shebang

发音类似中文的 "蛇棒" 。为什么叫 shebang 呢? 首先 # 的英文是 sharp, 而 感叹号 ! 经常被引用为炸弹,炸弹爆炸就是 bang , 所以 sharp+bang,简读为 shebang

后面的 /bin/bash 就比较熟悉了,它是 Bash Shell 的二进制执行文件路径。是 Unix 类操作系统中最常用的 Shell 程序之一。

所以 #!/bin/bash 的作用是:用于指定默认情况下运行指定脚本的解释器

当脚本以 #!/bin/bash 开头时,内核就知道用 /bin/bash 这个可执行文件来解释并运行这个脚本。

下面举个例子来说明下:

一、当脚本中指定脚本解释器为#!/bin/bash、#!/bin/sh时,shell脚本test.sh的执行情况

复制代码
#!/bin/sh

echo "Hello, world!"

# 使用 Bash 特有的语法
if [[ 1 -eq 1 ]]; then
  echo "1 equals 1"
fi

这个脚本使用了bash特有的语法\[ ... ],如果使用 #!/bin/sh 来指定解释器,则会报错:

复制代码
test.sh: 6: test.sh: [[: not found

分以下三种情况执行此test.sh脚本:

1、脚本中指定了#!/bin/sh,且脚本执行时使用sh,则执行时会报错

复制代码
#sh test.sh
Hello, world!
test.sh: 6: test.sh: [[: not found

2、脚本中指定了#!/bin/sh,且脚本执行时使用bash,则执行正常

复制代码
#bash test.sh
Hello, world!
1 equals 1

3、给test.sh添加执行权限后再执行,也报错

复制代码
#chmod +x test.sh
#./test.sh
Hello, world!
./test.sh: 6: ./test.sh: [[: not found

由上可知,当执行脚本时,如果命令中指定了解释器bash、sh,如:bash test.sh,则执行时会忽略脚本中第一行指定的解释器,即#!/bin/sh#!/bin/bash会被忽略,而以bash进行解释脚本。

二、当脚本中未指定解释器时,shell脚本test1.sh的执行情况

复制代码
echo "Hello, world!"

# 使用 Bash 特有的语法
if [[ 1 -eq 1 ]]; then
  echo "1 equals 1"
fi

此脚本第一行未指定任何解释器。

分以下三种情况执行此test1.sh脚本:

1、脚本中未指定解释器,且脚本执行时使用sh,则执行时会报错

复制代码
#sh test1.sh
Hello, world!
test.sh: 6: test.sh: [[: not found

2、脚本中未指定解释器,且脚本执行时使用bash,则执行正常

复制代码
#bash test1.sh
Hello, world!
1 equals 1

3、给test1.sh添加执行权限后再执行,执行正常

复制代码
#chmod +x test1.sh
#./test1.sh
Hello, world!
1 equals 1

由上可知,当执行脚本时,如果命令中指定了解释器bash、sh,如:bash test.sh,则执行时以bash进行解释脚本;如果命令中未指定解释器bash、sh,如:./test.sh,则执行时会以系统默认的解释器进行解释,而bash是 Unix 类操作系统中最常用的 Shell 程序之一。

通过 echo $0 可查看系统默认的脚本解释器,如以下是我的ubuntu系统默认的解释器:

复制代码
#echo $0
bash

三、当脚本中指定解释器为:#!/bin/cat,即将cat 命令将成为 shell 的解释器,则shell脚本test2.sh的执行情况

复制代码
#!/bin/cat
echo "Hello, world!"

# 使用 Bash 特有的语法
if [[ 1 -eq 1 ]]; then
  echo "1 equals 1"
fi

分以下三种情况执行此test2.sh脚本:

1、脚本中未指定解释器,且脚本执行时使用sh,则执行时会报错

复制代码
#sh test2.sh
Hello, world!
test.sh: 6: test.sh: [[: not found

2、脚本中未指定解释器,且脚本执行时使用bash,则执行正常

复制代码
#bash test2.sh
Hello, world!
1 equals 1

3、给test2.sh添加执行权限后再执行,执行正常

复制代码
#chmod +x test2.sh
#./test2.sh
#!/bin/cat

echo "Hello, world!"

# 使用 Bash 特有的语法
if [[ 1 -eq 1 ]]; then
  echo "1 equals 1"
fi

这意味着现在这个脚本将使用 cat 命令运行并显示脚本的内容。它将输出脚本所有内容。

由上面的三种情况可知:

1、当执行脚本的方式为:./test.sh时,如果脚本中未指定shebang解释器,则以系统默认的解释器进行解释执行;如果脚本中指定了shebang解释器,则以指定的解释器进行解释执行。

2、当执行脚本的方式为:bash test.sh时,不管脚本是否指定了shebang解释器,都会被忽略,而以bash作为解释器进行解释执行``。

参考:

为什么 shell 脚本的开头要写 #!/bin/bash - 知乎

【Linux】#!/bin/sh与#!/bin/bash,区别是什么,结合代码举例说明以及常见的异常情况处理-CSDN博客

相关推荐
日晨难再1 小时前
C语言&Python&Bash&Tcl:全局变量和局部变量
c语言·python·bash·tcl
LZZ and MYY1 小时前
RTS 在windows和Linux之间ShareMem
linux·运维·服务器
aningx1 小时前
openSUSE Leap 16.0 运行 sunshine 报错的解决方法
linux
爱学习的徐徐1 小时前
Linux 基础IO
linux·服务器
zt1985q2 小时前
本地部署源代码管理解决方案 Bitbucket Data Center 并实现外部访问
运维·服务器·数据库·网络协议·postgresql·源代码管理
xiaobobo33302 小时前
面向对象:linux内核中函数转数据的用法
linux·面向对象·隔离·函数指针绑定
极客先躯2 小时前
高级java每日一道面试题-2026年01月18日-实战篇[Docker]-如何清理仓库中的旧镜像?
java·运维·docker·容器
姓刘的哦2 小时前
C++软件架构设计思路
linux
ModestCoder_2 小时前
windows/ubuntu解决挂梯子但是codex reconnecting五次的问题
linux·windows·ubuntu
禹凕2 小时前
Linux基础——环境
linux·运维·服务器·ubuntu