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 天前
logstash教程
运维
chen9451 天前
k8s集群部署vector日志采集器
运维
chen9451 天前
aws ec2部署harbor,使用s3存储
运维
轻松Ai享生活1 天前
5 节课深入学习Linux Cgroups
linux
christine-rr1 天前
linux常用命令(4)——压缩命令
linux·服务器·redis
三坛海会大神5551 天前
LVS与Keepalived详解(二)LVS负载均衡实现实操
linux·负载均衡·lvs
東雪蓮☆1 天前
深入理解 LVS-DR 模式与 Keepalived 高可用集群
linux·运维·服务器·lvs
qq_264220891 天前
LVS负载均衡群集和LVS+Keepalived群集
运维·负载均衡·lvs
乌萨奇也要立志学C++1 天前
【Linux】进程概念(二):进程查看与 fork 初探
linux·运维·服务器
雨落Liy1 天前
Nginx 从入门到进阶:反向代理、负载均衡与高性能实战指南
运维·nginx·负载均衡