Linux中的二进制可执行文件和脚本可执行文件及Shebang_ascii text executable-程序员宅基地

技术标签: python  Linux  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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_44966641/article/details/120598561

智能推荐

BASE64、MD5、SHA、HMAC几种加密算法-程序员宅基地

文章浏览阅读106次。BASE64编码算法不算是真正的加密算法。 MD5、SHA、HMAC这三种加密算法,可谓是非可逆加密,就是不可解密的加密方法,我们称之为单向加密算法。我们通常只把他们作为加密的基础。单纯的以上三种的加密并不可靠。 BASE64 按照RFC2045的定义,Base64被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。(The ..._base 64编码 和mad5 和雪花算法

住宅IP、家庭宽带IP以及原生IP,它们有什么区别?谷歌开发者账号应选择哪种IP?-程序员宅基地

文章浏览阅读1.1k次。IP地址(Internet Protocol Address)是互联网协议地址的简称,是互联网通信的基础,互联网上每一个网络设备的唯一标识符每个在线的设备都需要一个IP地址,这样才能在网络中找到它们并进行数据交换。IP地址有很多种类型,今天跟大家简单分享一下住宅IP、家庭宽带IP以及原生IP的区别。住宅IP通常是指由互联网服务提供商(ISP)分配给家庭的或小型办公室使用的互联网连接IP地址,并可能随着网络连接的变化而变化。此类IP地址主要用于日常网络活动,如浏览网页、发送接收电子邮件、上网冲浪等。

如何更改layui form表单位置,宽度,颜色等_layui-form-item 宽度-程序员宅基地

文章浏览阅读2.6w次,点赞14次,收藏30次。如何更改layui form表单位置,宽度,颜色等_layui-form-item 宽度

【翻译】Efficient Data Loader for Fast Sampling-Based GNN Training on Large Graphs_pagraph: scaling gnn training on large graphs via -程序员宅基地

文章浏览阅读612次。写的非常好_pagraph: scaling gnn training on large graphs via computation-aware caching

炫酷的HTML代码-程序员宅基地

文章浏览阅读2.7w次,点赞61次,收藏285次。很炫酷的html代码:<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><title>star</title><script type="text/javascript">window.onload = function () {C = Math.cos; // cache Math objectsS = Math.si.._炫酷的html

【HDU - 1166】敌兵布阵 (线段树模板 单点更新+ 区间查询)-程序员宅基地

文章浏览阅读204次。题干:C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了。A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况。由于采取了某种先进的监测手段,所以每个工兵营地的人数C国都掌握的一清二楚,每个工兵营地的人数都有可能发生变动,可能增加或减少若干人手,但这些都逃不过C国的监视。 中央情报局要研究敌人究竟演习什...

随便推点

【免费题库】华为OD机试C卷 - 数字字符串组合倒序(Java 代码+解析)-程序员宅基地

文章浏览阅读2.3k次。题目描述对数字,字符,数字串,字符串,以及数字与字符串组合进行倒序排列。字符范围:由 a 到 z, A 到 Z,数字范围:由 0 到 9符号的定义:“-”作为连接符使用时作为字符串的一部分,例如“20-years”作为一个整体字符串呈现;连续出现 2 个 “-” 及以上时视为字符串间隔符,如“out--standing”中的”–“视为间隔符,是 2 个独立整体字符串”out”和”standing”;除了 1,2 里面定义的字符以外其他的所有字符,都是非法字符,作为字符串的间隔符处理,倒序后

Android(14) ArrayAdapter(数组适配器)的三种方法-程序员宅基地

文章浏览阅读5w次,点赞36次,收藏138次。ArrayAdapter数组适配器用于绑定格式单一的数据,数据源可以是集合或者数组列表视图(ListView)以垂直的形式列出需要显示的列表项。实现过程:新建适配器->添加数据源到适配器->视图加载适配器第一种:直接用ListView组件创建列表每一行只有一行文字效果如图:activity_list布局:<?xml version="1.0" e..._arrayadapter

助力商家健康经营 创业者为水滴直播点赞-程序员宅基地

文章浏览阅读43次。近日,水滴直播平台登上了舆论的风口浪尖。有人认为水滴直播涉嫌侵犯隐私,但也有人表示这种互联网新生事物可以有效规避很多风险,值得鼓励,不应一棒子打死。记者采访时发现,很多商家、创业者对于水滴直播纷纷表示支持,并直言水滴直播为他们的经营带来了很大帮助。 邹志泉在北京丰台区经营着一家批发厂家直销男女内衣裤的店铺,平时就打开水滴直播,分享他在店铺的经营画面。面对水滴直播涉及隐私的提问,邹志泉明确表...

java毕业设计宠物收养管理系统Mybatis+系统+数据库+调试部署-程序员宅基地

文章浏览阅读67次。springboot基于SpringBoot的电影社区网站。springboot基于springboot食品销售网站。ssm基于微信平台的校园汉服租赁系统的设计与实现。ssm基于SSM高校教师个人主页网站的设计与实现。ssm基于SSM框架的在线健康系统设计与实现。ssm基于HTML的武昌理工学院二手交易网站。ssm基于JavaEE的网上图书分享系统。ssm基于Javaee的项目任务跟踪系统。

Nginx使用之反向代理、负载均衡、动静分离教程。_php动静分离-程序员宅基地

文章浏览阅读61次。负载均衡是指将客户端的请求分发到多个后端服务器,以平衡服务器的负载。反向代理是指将客户端的请求转发到后端服务器,并将响应返回给客户端。通过配置反向代理,Nginx将转发所有来自客户端的请求到后端服务器,并将响应返回给客户端。通过这样的配置,Nginx将根据请求的URL路径选择是将请求转发到后端服务器还是直接返回静态资源文件。通过配置负载均衡,Nginx将按照指定的策略将客户端的请求分发到后端服务器上,从而实现负载均衡。配置反向代理:编辑Nginx配置文件(通常是nginx.conf),在。_php动静分离

HTML5有哪些新特性_谈谈html5的一些新特性-程序员宅基地

文章浏览阅读9.5k次,点赞3次,收藏18次。(一) 语义标签(二)增强型表单(三)视频和音频(四)Canvas绘图(五)SVG绘图(六)地理定位(七)拖放API(八) WebWorker(九) WebStorage(十)Web..._谈谈html5的一些新特性

推荐文章

热门文章

相关标签