Linux中的二进制可执行文件和脚本可执行文件及Shebang

Linux中的二进制可执行文件和脚本可执行文件及Shebang

二进制可执行文件

我们知道,一个C程序经过预处理、编译、汇编、链接就会得到一个二进制可执行文件,这种文件在Linux中叫做ELF文件。比如我们有一个C源代码hello.c

#include <stdio.h>int main(int argc, char** argv){printf("Hello !\n");
}

我们编译得到 hello 文件,并用file命令可以查看到生成的二进制可执行文件的信息:

gcc hello.c -o hello
file hello
# 输出:
# hello: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=cf2738fd1715f096d4b0e0e4b264146b78b454b1, not strippe

确实是ELF文件,我们可以直接执行它:

./hello
# 输出:
# Hello

这是我们常见的,可以理解的,链接后的可执行文件就是可以直接运行,就像我们在Windows上双击打开一个exe文件那样自然。那么,脚本可执行文件又是怎么一回事呢?

脚本可执行文件及Shebang

脚本可执行文件也可以像运行二进制可执行文件那样来直接运行它。我们知道shell、python等属于脚本语言。令我们好奇的是,脚本程序如 train.py 等看上去只是一个文本文件,为什么也能直接被执行呢 ?

我们知道,想要运行一个脚本文件,我们需要指定一个解释器。通常,我们有两种方式来指定脚本文件的解释器:

  1. 在命令行中指定,如bash run.shpython train.py等。
  2. 通过文件中的第一行Shebang指定。在脚本文件的头上,通常会有一行Shebang:#!。比如:#!/bin/bash#!/home/song/bin/python等。

Shebang通常出现在类Unix系统的脚本中第一行,作为前两个字符。在Shebang之后,可以有一个或数个空白字符,后接解释器的绝对路径用于指明执行这个脚本文件的解释器。在直接调用脚本时,系统的程序载入器会分析 Shebang 后的内容,将这些内容作为解释器指令,并调用该指令,将载有 Shebang 的文件路径作为该解释器的参数,执行脚本,从而使得脚本文件的调用方式与普通的可执行文件类似。例如,以指令#!/bin/sh开头的文件,在执行时会实际调用 /bin/sh 程序(通常是 Bourne shell 或兼容的 shell,例如 bash、dash 等)来执行。

由于 # 符号在许多脚本语言中都是注释标识符,这既是偶然,也是必然。Shebang 的内容会被这些脚本解释器自动忽略。 在 # 字符不是注释标识符的语言中,例如 Scheme,解释器也可能忽略以 #! 开头的首行内容,以提供与 Shebang 的兼容性。

实际上,#!两个字符的ASCII码是两个magic字符,当类UNIX操作系统看到一个文件以这两个字符开头,会将这个文件当做是可执行文件,并且按照其后的解释器来执行它(需要有执行权限)。这时,操作系统实际上加载的是 #! 后面跟的那个二进制文件(即解释器),然后将脚本文件的文本内容作为参数传给这个二进制文件。这一点可以通过观察脚本可执行文件运行使得strace结果中的execve来验证。

Shebang的一些具体用法和注意事项:

  1. 如果脚本文件中没有#!这一行,那么执行时会默认采用当前Shell去解释这个脚本(即:SHELL环境变量)。
  2. 如果#!之后的解释程序是一个可执行文件,那么执行这个脚本时,它就会把文件名及其参数一起作为参数传给那个解释程序去执行。
  3. 如果#!指定的解释程序没有可执行权限,则会报错 bad interpreter: Permission denied。如果#!指定的解释程序不是一个可执行文件,那么指定的解释程序会被忽略,转而交给当前的SHELL去执行这个脚本。
  4. 如果#!指定的解释程序不存在,那么会报错 bad interpreter: No such file or directory。注意:#!之后的解释程序,需要写其绝对路径(如:#!/bin/bash),它是不会自动到环境变量PATH中寻找解释器的。要用绝对路径是因为它会调用系统调用execve,这可以用strace工具来查看。
  5. 脚本文件必须拥有可执行权限。可通过chmod +x [filename] 来添加可执行权限。
  6. 当然,如果你使用类似于 bash test.shpython train.py这样的命令来执行脚本,那么#!这一行将会被忽略掉,解释器当然是用命令行中显式指定的解释器。

我们来试一下,先创建一个py文件world.py,并直接写入为:

print('World !')

我们可以通过在命令行指定python解释器来运行,就像我们一直做的那样:

python world.py
# 输出:
# World !

但是,当我们想像运行二进制可执行文件那样来运行它

./world.py
# 输出:
# -bash: ./world.py: Permission denied

首先会受到一条没有执行权限的命令,如上。这很正常,因为我们创建的时候它是一个文本文件嘛。我们通过 chmod 来使得它可执行,并再次尝试运行它:

chmod +x world.py
./world.py
# 输出:
# ./world.py: line 1: syntax error near unexpected token `'World !''
# ./world.py: line 1: `print('World !')'

问题出现了,和我们之前讨论的一样,由于我们没有通过Shebang来指定脚本的解释器,系统默认用了Shell来解释,那我们的python语法自然是不对的。那这时,想要像运行二进制可执行文件那样去运行它,必须请出我们的Shebang来帮忙在文件内指明解释器的绝对路径。更改world.py 为:

#!/home/song/anaconda3/envs/JJ_env/bin/python
print("World")

这时我们再来运行:

./world.py
# 输出:
# World !

就可以了。我们还可以通过 file 命令再来看一下 world.py 的文件信息:

file world.py
# 输出:
# world.py: a /home/song/anaconda3/envs/JJ_env/bin/python script, ASCII text executable

我们看到该文件是一个ASCII text executable,即 ”文本可执行文件“。不同于ELF二进制可执行文件,但也是可执行文件。也就是说,在Linux的世界中,可执行文件不只有ELF一种。

另外,由于Linux系统对后缀名并不严格要求,我们可以直接将world.py改为world,这样也是可以的,然后就可以通过将world这个脚本可执行文件放到PATH环境变量下,从而将world直接作为一个命令来使用啦!具体可参考笔者另一篇介绍Linux常用环境变量的博客。

总结

总结一下:Linux中除了ELF二进制可执行文件之外,还有脚本可执行文件,要想让脚本可执行文件直接像二进制可执行文件一样运行,而不需在命令行中指定解释器,需要在脚本文件头通过Shebang !#来指定解释器的绝对路径。Shebang的一些具体的注意事项在上文中已经指出。另外,通过将可执行文件(二进制、脚本都可)添加到PATH环境变量的可执行文件搜索目录下,可将在命令行中通过命令来直接使用这些可执行文件。

Ref:

https://blog.csdn.net/u012294618/article/details/78427864

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/532732.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pe能用的固态硬盘测试软件,通用pe工具箱教你如何让硬盘4K对齐

昨天小编教大家如何查看电脑硬盘是否4K对齐&#xff0c;马上就有读者告诉小编&#xff0c;查看电脑硬盘是否4K对齐的方法学到了&#xff0c;那么我使用的固态硬盘如何做到4K对齐呢&#xff1f;问的好啊&#xff01;现如今用户对电脑硬件的要求是越来越高。很多用户都不仅仅满足…

[2020-ECCV]PIPAL-a Large-Scale Image Quality Assessment Dataset for Perceptual Image Restoration论文简析

[2020-ECCV] PIPAL: a Large-Scale Image Quality Assessment Dataset for Perceptual Image Restoration 论文简析 论文&#xff1a;https://arxiv.org/abs/2007.12142 代码及数据集&#xff1a;https://github.com/HaomingCai/PIPAL-dataset 概述 本文认为随着图像重建&…

郫都区计算机老师周俊老师,教师节,带你走进郫都教师背后的故事

点击“郫都教育”关注我们&#xff1a;)有这样一群人“师者&#xff0c;所以传道&#xff0c;授业&#xff0c;解惑也”是他们奉献一生的事业“随风潜入夜&#xff0c;润物细无声”是他们培养英才的责任“春蚕到死丝方尽&#xff0c;蜡炬成灰泪始干”是他们追求终生的信仰值此第…

(2021) 18 [代码讲解] 可执行文件

(2021) 18 [代码讲解] 可执行文件 南京大学操作系统课蒋炎岩老师网络课程笔记。 视频&#xff1a;https://www.bilibili.com/video/BV1HN41197Ko?p18 讲义&#xff1a;http://jyywiki.cn/OS/2021/slides/C8.slides#/ 背景 回顾 程序 状态机 状态机执行 状态机上的路径状…

如何学习计算机思维,刘康平:为什么我们每个人都应该学习计算思维?

不久前&#xff0c;微软亚洲研究院资深学术合作经理刘康平应邀在“造就”做了演讲&#xff0c;以下为演讲节选&#xff0c;由“造就”授权转载。刘康平 微软亚洲研究院资深学术合作经理以中国象棋为例&#xff0c;在这样一个棋局上&#xff0c;你怎么用最快的方式找到「将」和「…

链接与加载-NJU-JYY

(2021) 19 [代码讲解] 从零实现动态加载 南京大学操作系统课蒋炎岩老师网络课程笔记。 视频&#xff1a;https://www.bilibili.com/video/BV1N741177F5?p15 讲义&#xff1a;http://jyywiki.cn/OS/2021/slides/C9.slides#/ 背景 回顾&#xff1a; ELF可执行文件 只要能完成…

计算机械功的公式,机械功率计算公式

初中物理公式物理量(单位) 公式 备注 公式的变形速度V(m/S) v S /t (S:&#xff1a;路程&#xff1b; t&#xff1a;:时间 )重力G(N) Gmg (m&#xff1a;质量&#xff1b;g&#xff1a;9.8N/kg或者10N/kg)密度ρ(kg/m3) ρ m&#xff1a;质量/V&#xff1a;体积 (m&#xff1a;…

饥荒联机自建服务器有什么用,联机版饥荒使用专用服务器的好处 | 手游网游页游攻略大全...

发布时间&#xff1a;2016-02-15存档保存位置是?很多玩家对此并不是很了解,不过别着急哟,下面99单机小编就为你带来高玩分享的相关技巧心得攻略,希望大家能喜欢. 联机版的存档与单机版是不同的,由于联机版饥荒建 ...标签&#xff1a;游戏资讯 攻略秘籍发布时间&#xff1a;201…

(2021) 26 [持久化] 持久数据的可靠性:RAID和journaling

(2021) 26 [持久化] 持久数据的可靠性&#xff1a;RAID和journaling 南京大学操作系统课蒋炎岩老师网络课程笔记。 视频&#xff1a;https://www.bilibili.com/video/BV1HN41197Ko?p26 讲义&#xff1a;http://jyywiki.cn/OS/2021/slides/16.slides#/ 背景 回顾 文件系统 …

计算机-p命令,OD(电脑命令)_百度百科

od 命令用途是以指定格式显示文件。常见的文件为文本文件和二进制文件。此命令主要用来查看保存在二进制文件中的值。比如&#xff0c;程序可能输出大量的数据记录&#xff0c;每个数据是一个单精度浮点数。这些数据记录存放在一个文件中&#xff0c;如果想查看下这个数据&…

Linux下编译、链接、加载运行C++ OpenCV的两种方式及常见问题的解决

Linux下编译、链接、加载运行C OpenCV的两种方式及常见问题的解决 在Linux下安装完OpenCV C之后&#xff08;还没有安装的读者请参考Ubuntu 18.04 安装OpenCV C&#xff09;&#xff0c;本文将探索Linux下编译、链接C OpenCV的两种方式&#xff0c;并且给出笔者在初次尝试时遇…

win10无法检验服务器出示的ssl证书,win10系统网站启用ssL安全证书的操作方法

win10系统网站启用ssL安全证书的操作方法?很多win10用户在使用电脑的时候&#xff0c;会发现win10系统网站启用ssL安全证书的的现象&#xff0c;根据小编的调查并不是所有的朋友都知道win10系统网站启用ssL安全证书的的问题怎么解决&#xff0c;不会的朋友也不用担心&#xff…

Linux下构建自己的C++共享库并配合pkg-config生成链接选项

Linux下构建自己的C共享库并配合pkg-config生成链接选项 本文将以C链表的新建、打印操作为例构建自己的共享库&#xff0c;并在实际调试代码时尝试使用。我们在做数据结构题时经常需要将链表打印出来看一下结果&#xff0c;但是并没有一种库函数可以让我们直接调用来打印自己的…

webkitlineclamp css3,-webkit-line-clamp

无标题文档static&#xff1a;对象遵循常规流。top&#xff0c;right&#xff0c;bottom&#xff0c;left等属性不会被应用。 relative&#xff1a; 对象遵循常规流&#xff0c;并且参照自身在常规流中的位置通过top&#xff0c;right&#xff0c;bottom&#xff0c;left属性进…

Linux内核初探

Linux内核初探 内核的组成部分 kernel&#xff1a;内核核心文件&#xff0c;一般为bzp_w_picpath&#xff0c;经过压缩处理的镜像文件&#xff1b;通常内核核心文件保存在/boot/目录下&#xff0c;名称为vmlinuz-version-release kernel object(ko)&#xff1a;内核对象&…

Nplayer本地文件拷到服务器,手把手教你简易NAS构建,手机/平板/智能电视随意调取,家庭存储云共享,有了自己的网络云盘后再也不用担心容量不够了!...

之前嫌键盘侠烦&#xff0c;写这些也没意义所以把账号注销了文章删除了&#xff0c;现在想了想我抗吧12级老蛆还喷不过这帮小兔崽子&#xff1f;换了skt.ruo秽土转生&#xff0c;求喷子和我在各评论对线。特别是匿名dog见一个怼死一个。下面是之前号写的内容原文 -#简介NAS全称…

gdb 入门

gdb 入门 简介 gdb是GNU开源组织发布的一个强大的Linux下的程序调试工具。 一般来说&#xff0c;GDB主要帮助你完成下面四个方面的功能&#xff1a; 1、启动你的程序&#xff0c;可以按照你的自定义的要求随心所欲的运行程序。 2、可让被调试的程序在你所指定的调置的断点…

视频监控系统中的平台服务器,【视频监控主机 网络视频集中管理平台服务器】 - 太平洋安防网...

完善的管理功能管理系统内所有设备的接入及设备权限。设备状态监视。系统资源及用户权限分配及系统抢权管理。电子地图。实现系统内视频流的管理和转发控制。可通过WEB远程管理。强大的报警事件管理功能系统具备完善的报警及处理功能&#xff0c;能根据预先编写事件 处理预案对…

Linux下的CUDA多版本管理

Linux下的CUDA多版本管理 关于CUDA、cuDNN等的简介和安装可参考&#xff1a;显卡、显卡驱动、CUDA、CUDA Toolkit、cuDNN 梳理。 CUDA多版本 有时我们会在一台机器上同时看到多个版本的CUDA&#xff0c;比如nvcc -V和nvidia-smi的输出就可能会不同&#xff1a; 在我们实验室…

电脑显示无法连接sql服务器,他人的电脑为什么无法连接我电脑上的sql sever服务器...

如果SQL2005连接不上&#xff0c;并且服务器上所有与防火相关的东西都关闭了&#xff0c;还是连接不上。进行如下操作:一、为 SQL 启用远程连接1. 单击“开始”&#xff0c;依次指向“程序”、“Microsoft SQL Server 2005”和“配置工具”&#xff0c;然后单击“SQL Server 外…