关于 Bash 脚本中 Shebang 的趣事
哈喽大家好,我是咸鱼
不知道小伙伴们在写 Bash 脚本或者说看别人的 Bash 脚本的时候有没有注意过脚本的第一行
#!/bin/bash
Bash 脚本的第一行往往以 #! 开头,这一行称作 shebang 行
在 类 UNIX 系统中,shebang 行用来指定脚本的解释器路径,通常出现在第一行,格式如下
#! interpreter_path
shebang 行中开头 #! 字符的作用是告诉操作系统这不是一个普通二进制文件,而是需要通过解释器运行的东西
而这个解释器则通过 #! 字符后面来指定。例如 /bin/bash 表示使用 bash 解释器来执行该脚本文件
下面则是一些 Bash 脚本的 shebang 行,指定了不同的解释器
#! /usr/bin/perl
#! /usr/bin/awk
#! /usr/bin/python
那么这时候小伙伴们可能就会有疑问:我忘了加 shebang 行,脚本为什么还能执行?
如果一个脚本没有添加 shebang 行来指定解释器路径,则默认情况下系统会使用默认的 shell 来执行脚本,系统默认的 shell 可以通过下面的命令来查看
# 一般情况下默认的 shell 为bash
echo $SHELL
现在我们知道了 shebang 行的作用,那么我们现在来编写一个脚本并修改 shebang 行试试
test.sh 内容如下:
#!/bin/bash
echo Hello
先给 test.sh 脚本添加一下执行权限
chmod +x test.sh
接下来我们用几种方式来执行这个脚本

可以看到脚本都成功执行了
下面我们来改一下 shebang 行,将其改成其他命令
#!/usr/bin/ls -l
echo Hello
然后我们分别用几种方式来执行这个脚本

上面脚本执行的结果是不是看的一脸懵逼,说实话我一开始看到的时候也是很懵
我们先来看下这四种脚本执行方式的区别
- bash tesh.sh
这种方式执行脚本的原理是将 test.sh 作为参数传给 bash 解释器(命令)来执行,而不是 test,sh 自己来执行
这种方式执行脚本不需要给脚本文件添加执行权限、不需要写 shebang 行指定解释器路径,因为脚本是作为参数被传给 bash 来执行
- sh test.sh
这种执行脚本的方式跟上面的方式原理一样,都是将脚本作为参数传进去,只不过是这个方式用的是 sh 解释器(命令),而不是 bash
- /root/test.sh
这种是通过绝对路径去执行脚本,通过绝对路径来执行脚本就需要脚本拥有执行权限
当使用绝对路径来执行脚本时,操作系统需要知道该脚本文件所使用的解释器类型,这就需要依靠脚本文件中的 shebang 行
实际上你用绝对路径执行脚本的时候,如果里面定义了 shebang 行(例如 #! /bin/bash)
那么实际上跟下面的命令是一样的
/bin/bash /root/test.sh
在执行脚本的时候,操作系统会读取脚本的 shebang 行
如果你的 shebang 行是其他 Linux 命令而不是解释器,那么就会导致操作系统将你的 shebang 行当作命令,而你的脚本则是命令的参数
就好比上面的例子,我将 shebang 行改成了 #! /usr/bin/ls -l ,当我执行脚本的时候其实就是下面这样的
/usr/bin/ls -l /root/test.sh
这样会导致脚本无法执行
- ./test.sh
这种是通过相对路径去执行脚本,跟上面用绝对路径执行脚本方式是一样的,只不过区别是一个是相对路径一个是绝对路径
总结:
- shebang 行通常出现在 UNIX 系统的脚本当中,用来指定脚本的解释器路径,出现在第一行,以
#!开头 - 如果脚本里面没有定义 shebang 行,系统会去找默认的解释器,默认解释器用
echo $SHELL查看 - 用 bash 或者 sh 命令执行脚本的时候,其实是把脚本作为参数传给 bash 或 sh 命令了,这时候脚本可以不添加执行权限、可以不需要 shebang 行
- 如果用绝对路径或者相对路径的方式来执行脚本,需要脚本拥有执行权限,如果 shebang 行定义的不是解释器而是其他命令,就会导致脚本无法执行
附上参考链接:Shebang Shenanigans :: Linus Karlsson
关于 Bash 脚本中 Shebang 的趣事的更多相关文章
- grep 查找bash脚本中的注释代码
出于安全性的考虑,不建议在bash脚本中注释掉不使用的代码.也就是说如果某段代码不使用了,那么应该删除掉,而不是简单地注释掉.假如你突然意识到这一点,而以前并没有遵从这个原则,现在需要找出脚本中的注释 ...
- 如何在Bash脚本中引入alias
更多精彩内容,请关注微信公众号:后端技术小屋 alias的使用 在日常开发中,为了提高运维效率,我们会用alias(命令别名)来定义命令的简称.比如在~/.bash_profile中添加: alias ...
- bash 脚本中分号的作用
在Linux bash shell中,语句中的分号一般用作代码块标识 1.单行语句一般要用到分号来区分代码块.比如: weblogic@pmtest:/$if [ "$PS1" ] ...
- Bash脚本中的操作符
一.文件測试操作符 假设以下的条件成立将会返回真. -e 文件存在 -a 文件存在 这个选项的效果与-e同样. 可是它已经被"弃用"了, 而且不鼓舞使用. -f 表示这个文件是一个 ...
- Bash 脚本中的 set -euxo pipefail
有些开发人员会用Bash来实现很复杂的功能,就像使用别的高级语言一样.他可能觉得自己很牛逼但其他人早就想锤爆他了,Bash的可读性和可维护性远远低于任何高级语言.更要命的是,Bash并没有方便的调试工 ...
- 详解在bash脚本中如何获取自身路径
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 这是stac ...
- bash脚本中的普通数组和关联数组
1. 普通数组 bash支持一维数组(不支持多维数组),并且没有限定数组的大小.类似与C语言,数组元素的下标由0开始编号.获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于0. ...
- linux 环境下bash脚本中找不到命令
mr.sh: line 1: HADOOP_CMD: command not found mr.sh: line 4: INPUT_FILE_PATH: command not found mr.sh ...
- bash脚本中使用选项 getopts
原文链接 : http://note.youdao.com/noteshare?id=0cf08484c7308c763726e63e9a638ff5&sub=EF6A110E2F3345E6 ...
- Linux下shell脚本中信号捕获和函数练习脚本之ping一个网段
该脚本主要的目的是练习在Linux bash脚本中捕获信号,顺便练习一下函数的使用,还有就是终止一个正在运行的程序后,该程序打开的文件的后续处理问题等等!脚本功能: ping一个网段内的IP,检测哪 ...
随机推荐
- k8s configmap 配置分离
ConfigMap ConfigMap用于保存配置珊数据的键值对,可以用来保存单个属性,也可以用来保存配置文件.一张图解释 上图就是整个ConfigMap的生命周期以及使用方式, ConfigMap的 ...
- pip安装报错 cannot uninstall a distutils installed project
sudo pip install --ignore-installed xxx 在安装jupyter notebook的时候,遇到了这个问题,于是上网搜索,搜到了靠谱答案github解决方案 sudo ...
- 3.javaweb-servlet
1. 设置编码 tomcat8之前,设置编码: 1)get请求方式: //get方式目前不需要设置编码(基于tomcat8) //如果是get请求发送的中文数据,转码稍微有点麻烦(tomcat8之前) ...
- Class 'dmstr\web\AdminLteAsset' not found
Yii2出现 Class 'dmstr\web\AdminLteAsset' not found 报错 1.检查下是不是vendor从其他地方复制过来的 2.检查根目录composer.json 中 ...
- Oracle-账户被锁:The account is locked
Oracle-账户被锁:The account is locked cmd-->sqlplus--> 管理员登录:system@ORCL 密码:1 然后输入:alter user kjb( ...
- python调用adb shell
最近在用python做一个小工具,自动执行一些adb shell命令,使用subprocess.Popen来实现. 不过遇到个问题就是执行adb shell后就无法执行后面adb shell里的命令了 ...
- Tcp网络模型
要摸清网络,那么第一步肯定是要清楚网络协议的分层结构,用上帝视角来看网络. 对于同一台设备上的进程间通信,有很多种方式,比如有管道.消息队列.共享内存.信号等方式,而对于不同设备上的进程间通信,就需要 ...
- Neo4j学习(3)--JavaAPI
Neo4j Java操作 1. Neo4j Java Driver方式操作 使用该方式对数据进行操作时,必须先将Neo4j的服务启动起来. 从官方下载neo4j的Java驱动:https://neo4 ...
- Python学习笔记--图像的进一步学习
演示地图的可视化的实现 示例: 设置全局选项 可以设置出不同的颜色,不会显得很干巴: 国内地图: 那么,我们应当如何找到相对应的颜色的编号呢? 基本步骤: 前往ab173.com网站 然后在,前端那里 ...
- 再次打开Spring界面,多处报错
分享一下经历 在我再次打开Srpring之后,打算解决一下"历史遗留问题",发现多处标红(挺崩溃的)! 就比如这句话,刚才就是不亮: 毕竟我上次的应用还是很顺利的,所以也就没有第一 ...