关于 Bash 脚本中 Shebang 的趣事

yizhihongxing

哈喽大家好,我是咸鱼

不知道小伙伴们在写 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

接下来我们用几种方式来执行这个脚本
关于 Bash 脚本中 Shebang 的趣事
可以看到脚本都成功执行了

下面我们来改一下 shebang 行,将其改成其他命令

#!/usr/bin/ls -l
echo Hello

然后我们分别用几种方式来执行这个脚本
关于 Bash 脚本中 Shebang 的趣事
上面脚本执行的结果是不是看的一脸懵逼,说实话我一开始看到的时候也是很懵

我们先来看下这四种脚本执行方式的区别

  • 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

原文链接:https://www.cnblogs.com/edisonfish/p/17379964.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:关于 Bash 脚本中 Shebang 的趣事 - Python技术站

(0)
上一篇 2023年5月7日
下一篇 2023年5月8日

相关文章

  • 从面试官角度观察到的程序员技能瓶颈(突破瓶颈的建议)

    从面试官角度观察到的程序员技能瓶颈 在面试程序员的过程中,面试官往往能够从面试者的表现中观察出一些技能方面的瓶颈。以下是一些面试官可能会注意到的技能瓶颈,以及突破这些瓶颈的建议: 缺乏扎实的编程基础 在面试中,面试官可能会发现面试者对编程基础的掌握不够扎实,表现为对语言基础、代码规范、算法等方面的理解不够深入,也没有做到看到一道题目就能想到对应的算法实现(如…

    Linux 2023年5月24日
    00
  • CentOS8 安装 jdk8 / java8的教程(推荐)

    下面是CentOS8安装jdk8/java8的教程: 安装OpenJDK 8 在CentOS 8的默认仓库中,可以找到OpenJDK 8的软件包,可以使用以下命令进行安装: sudo dnf install java-1.8.0-openjdk-devel 下载和安装可能需要一些时间,安装完成后,使用以下命令验证Java安装是否成功: java -versi…

    Linux 2023年5月14日
    00
  • [linux] C语言Linux系统编程-做成守护进程

    守护进程: 必须是init进程的子进程,运行在后台,不与任何控制终端相关联。 通过以下步骤成为守护进程 1.调用fork()创建出来一个新的进程,这个新进程会是将来的守护进程 2.在新守护进程的父进程中,调用exit(),为了守护进程的爷爷进程确认父进程结束 3.在新守护进程中,调用setsid(),使得该进程有一个新的进程组和新的会话,保证了该进程不与控制…

    Linux 2023年4月13日
    00
  • 详解搭建ubuntu版hadoop集群

    详解搭建Ubuntu版Hadoop集群 Hadoop是一个分布式计算框架,能够快速处理海量数据。本文将介绍如何在Ubuntu上搭建Hadoop集群。 环境准备 在开始搭建之前,我们需要准备以下环境: 3台Ubuntu Server,分别作为Master和两个Slave JDK 1.8 Hadoop 3.3.1 安装JDK Hadoop运行需要JDK的支持。我…

    Linux 2023年5月24日
    00
  • Linux系统SSH免密码登陆远程服务器的技巧

    让我来给您讲解一下“Linux系统SSH免密码登陆远程服务器的技巧”的完整攻略。 1. 生成公钥和私钥 SSH连接远程服务器时,往往需要输入密码,但是我们可以通过生成公钥和私钥的方式进行SSH的免密码登陆。 1.1. 在本地生成RSA公钥和私钥 在本地生成公私钥对,可以使用以下命令: ssh-keygen -t rsa 命令执行后,会提示输入文件保存路径和加…

    Linux 2023年5月14日
    00
  • 浅谈Linux的虚拟内存

    浅谈 Linux 的虚拟内存 什么是虚拟内存 虚拟内存是计算机操作系统为了让物理内存的使用更加高效而设计的一种技术。它使得应用程序在使用内存时,感觉自己独占了整个系统的物理内存,从而大大提高了内存的使用效率。 与传统的内存管理方式不同,虚拟内存通过在系统启动时分配给每个进程可供其使用的虚拟地址空间,在程序运行时将虚拟地址转换为物理地址,从而使得内存的管理更加…

    Linux 2023年5月24日
    00
  • IO多路复用

    IO多路复用 1.IO多路复用的概念 单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力。 2.为什么出现IO多路复用 服务器需要维护N多个与客户端之间的socketfd;并且在receive之前需要知道数据知否出现—》组件IO多路复用技术出现—》解决检测服务器端N多个fd的状态 Tcp是有连接的,Udp是无连接—》上述情况出现在T…

    Linux 2023年4月10日
    00
  • linux下inotify的使用

      有时候我们需要检测某个目录下文件或者子目录的改动状况,如添加、删除、以及更新等,Linux系统上提供了inotify来完成这个功能。inotify是在版本2.6.13的内核中首次出现,现在的发行本应该都包含这个系统调用了。 下面的描述中的文件如无特别说明包括文件以及目录 使用inotify的第一步就是调用inotify_init()创建一个inotify…

    Linux 2023年4月12日
    00
合作推广
合作推广
分享本页
返回顶部