Bash Shebang 小结
在 shell(Bash 是一种 shell) 中执行外部程序和脚本时,Linux 内核会启动一个新的进程,以便在新的进程中执行指定的程序或脚本。内核知道该如何为编译型的程序做这件事,但是对于脚本程序呢?当 shell 要求内核执行一个脚本文件时,内核是不知道该怎么办的!所以它回应一个 "not executable format file" 的错误消息。Shell 收到这样的消息后会做出类似下面的判断:这不是个编译型程序,那它肯定是一个 shell 脚本;接着就启动一个新的 /bin/sh 副本来这些该程序。
当系统中只有一个 shell(/bin/sh) 时这并没有什么问题。但是当前的系统中一般都存在多个 shell,比如 Bash、Dash等等。因此需要通过一种方式,告诉 Linux 内核应该以哪个 shell 来执行指定的脚本。实时上,这么做有助于执行机制的通用化,让用户可以直接引用任何的程序语言解释器,而不仅仅是一个 shell。具体的方法是通过脚本文件中特殊的第一行来设置:在第一行的开头处使用 #! 这两个字符(英文一般称为 shebang)。
当一个脚本中第一行是以 #! 这两个字符开头时,内核会扫描该行的其余部分,看是否可以找到可以用来执行该脚本文件的解释器。所以这是一种非常通用的做法,因为除了 shell 我们还可以指定其它的解释器,比如:
#!/usr/bin/awk
# 这个脚本是一个 awk 程序
#!/bin/bash
直接指定 shell 的绝对路径是一种经典的写法。这样内核会直接调用你指定的解释器,并把脚本文件作为参数传递给它。这样做的缺点也非常明显,面对多如牛毛的 Linux 发行版,你无法保证所有系统中的 bash 程序都放置在 /bin 目录下。当然其它程序的路径就更无法保证了。
/usr/bin/env 命令
让我们先来了解一下 /usr/bin/env 命令的执行方式,比如下面的命令:
$ env name=value name2=value2 program args
这会使用环境变量和由 name=value 和 name2=value2 指定的值扩展当前环境而形成的环境运行命令 program args。如果不包含任何参数,比如 name=value,那么将传递不经过修改的当前环境。因为 env 是外部命令,所以它并不知道 bash 中的别名,env 只是将程序和参数传递给 exec 调用。
#!/usr/bin/env bash
在了解了 /usr/bin/env 命令之后,让我们来看看 shebang 的另一种写法:
#!/usr/bin/env bash
你会看到越来越多的脚本采用了这种写法。通过 /usr/bin/env 运行命令的好处是可以在当前环境中查找程序的默认版本。这样,就不必在系统上的特定位置查找它,因为这些路径在不同的系统中可能位于不同的位置。只要你指定的解释器程序在你的 PATH 变量中,这种写法就会找到它。当然,这么做的前提是 /usr/bin/env 必须存在。
这种写法也是有缺点的,比如我们可以创建一个名称为 bash 的程序,并把它的路径添加到 PATH 变量的靠前位置,这样就会使用你写的假 bash 程序来执行脚本,而不是真正的 bash 程序,这是一个安全隐患。
个人的理解
#!/usr/bin/env bash 写法
更灵活,可移植性较好,但是有安全风险。
#!/bin/bash 写法
如果只考虑在单一的系统中执行,足够了。
Bash Shebang 小结的更多相关文章
- bash操作小结
刚开始学写bash脚本,发现有很多需要注意的细节问题,在这里记录一下便于记忆: 1. help test 帮助 2. bash提供的数组数据结构,它是以数字为下标的,和C语言从0开始的下一样 参考 ...
- bash学习记录
bash: 管理员: 提示符# 普通用户:提示符$ 环境变量 A=3(变量是指内存空间,A指的是内存空间的名称-变量标示符) PS1 \u@\h:\w\$ \u用户名 \h主机名 \w工作目录的 ...
- WebStorm换主题(护眼)
一.下载喜欢颜色的主题 http://www.phpstorm-themes.com/ 我用的豆沙绿护眼 <scheme name="Solarized Light My" ...
- linux shell攻略学习笔记一 基础篇
1.#!/bin/bash shebang 可以自定义 比如 #!/bin/bash +x 就会打印出执行日志 linux中 \ 代表null \n2\n3” 会转义其中的\n,生成3行数据 $! 保 ...
- Linux 下如何隐藏自己不被发现?
可能在某些情况下,自己运行的程序不想或者不方便被其他人看到,就需要隐藏运行的进程.或者某些攻击者采用了本文介绍的隐藏技术,也可以让大家看到如何进行对抗. 隐藏有两种方法: kernel 层面,不对用户 ...
- Linux Shell 学习笔记 00
1.Bash = Bourne Again SHell 2.终端提示符: #普通用户 username@hostname$ #管理员用户 root@hostname# 3.shell脚本通常是一个以s ...
- BASH 命令以及使用方法小结【转】
1,export VAR=... 这个命令在Shell下直接运行可以使之后运行的脚本也知道这个VAR.但是如果 这个命令在脚本中运行,那么不影响脚本以外的参数.举个例子,如果在一个脚本运行之前没有 V ...
- linux bash & profile &bash_profile 小结
login 方式:: su - oracle 依次 /etc/bash.bashrc———— /home/$user/.bashrc ———— /ect/profile ———— /home/$use ...
- BASH 命令以及使用方法小结
最近工作中需要写一个Linux脚本,用到了很多BASH命令,为了防止以后忘记,在这里把它们一一记下来.可能会比较乱,随便看看就好了.如果有说的不对的地方也欢迎大家指正. 1,export VAR=.. ...
随机推荐
- weblogic系列漏洞整理 -- 3. weblogic 后台提权
目录 三. weblogic 后台提权 0. 思路分析 1. 利用过程 2. 提示和技巧 一.weblogic安装 http://www.cnblogs.com/0x4D75/p/8916428.ht ...
- C#操作Exchange配置
1.客户端配置:运行gpedit.msc进入本地组策略管理器,计算机配置>管理模版>Windows组件>WinRM>WinRM客户端启用允许未加密通信:启用受信任的主机并添加e ...
- lvm管理卷之缩减卷大小
最近刚刚装好了一个系统,但是因为没有分好区,导致home分区过大,所以想把home分区的一大半移动到根分区里面. 1.先说一下我的环境. 安装的是centos6版本的系统,使用的默认文件系统是ext4 ...
- VRS——备忘
1.所有版本VRS,注释掉m_ChisauarePRN参数 2.注释掉所有的MODULE_GNSSMonitor_ID,暂时用不到.但是会造成basestation崩掉. n.RegisterStat ...
- 移除元素的golang实现
给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成 ...
- C#用默认浏览器打开特定网址的几种方法
方法一:从注册表中读取默认浏览器可执行文件路径 private void button1_Click(object sender, EventArgs e) { //从注册表中读取默认浏览器可执行文件 ...
- 转://SQL PROFILE
我们经常会碰到一些线上的SQL问题,因为执行计划不对,可能需要添加HINT才能解决.但是添加HINT就意味着需要修改应用代码.一般一个应用代码的修改.测试及发布,可能需要两三个工作日才可完成.咱们数据 ...
- 水题,P1789 【Mc生存】插火把 (暴力即可)
#include<cstdio> #define maxn int(1e4) bool dp[maxn][maxn]; int n; void f1(int x, int y) { dp[ ...
- ORB-SLAM2(4) 离线双目数据测试
官网 https://github.com/raulmur/ORB_SLAM2 1从http://www.cvlibs.net/datasets/kitti/eval_odometry.php下载数据 ...
- QT 13 窗口屏幕设置大小与居中显示
<pre name="code" class="cpp">#include "mainwindow.h" #include &l ...