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博客

相关推荐
观测云10 分钟前
端到端观测分析:从前端负载均衡到后端服务
运维·前端·负载均衡
davysiao19 分钟前
深度解析 Let‘s Encrypt 证书申请:从核心概念到实战避坑指南
运维
樂禮41 分钟前
树莓派连接教学
运维
来鸟 鸣间1 小时前
linux下抓包工具--tcpdump介绍
linux·运维·tcpdump
prettyxian2 小时前
【Linux】基础指令(2)
linux·运维·服务器
就是一顿骚操作2 小时前
Linux 部署以paddle Serving 的方式部署 PaddleOCR CPU版本
linux·r语言·paddle
言之。2 小时前
【Linux】记录一个有用PS1
linux·运维·服务器
楚灵魈3 小时前
[Linux]从零开始的STM32MP157 Buildroot根文件系统构建
linux·arm开发·stm32
fhqlongteng5 小时前
一种动态分配内存错误的解决办法
运维·服务器·网络·c++
yovo15 小时前
Linux权限管理
linux·运维·github