为什么 `#!/usr/bin/env var=val command` 会陷入无限循环

2023-12-10

In man(1) env it say:

env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]

所以考虑print_A.sh:

#!/usr/bin/env A=b bash
echo A is $A

当我运行它时./print_A.sh它挂了。

运行它strace ./print_A.sh我得到以下日志,重复:

execve("/path/to/print_A.sh", ["/path/to/print_A.sh"...], [/* 114 vars */]) = 0
uname({sys="Linux", node="my-host", ...}) = 0
brk(0)                                  = 0x504000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2a95556000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=171528, ...}) = 0
mmap(NULL, 171528, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2a95557000
close(3)                                = 0
open("/lib64/tls/libc.so.6", O_RDONLY)  = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\240\305\30100\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1641152, ...}) = 0
mmap(0x3030c00000, 2330696, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x3030c00000
mprotect(0x3030d30000, 1085512, PROT_NONE) = 0
mmap(0x3030e2f000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x12f000) = 0x3030e2f000
mmap(0x3030e35000, 16456, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x3030e35000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2a95581000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2a95582000
mprotect(0x3030e2f000, 16384, PROT_READ) = 0
mprotect(0x3030b14000, 4096, PROT_READ) = 0
arch_prctl(ARCH_SET_FS, 0x2a95581b00)   = 0
munmap(0x2a95557000, 171528)            = 0
brk(0)                                  = 0x504000
brk(0x525000)                           = 0x525000
open("/usr/lib/locale/locale-archive", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=48529088, ...}) = 0
mmap(NULL, 48529088, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2a95583000
close(3)                                = 0

如下所述,在 hash-bang 中运行命令并不等同于在命令行上运行它,但是,为什么它会进入无限循环?


这个答案有两个部分。已经给出了一个重复的问题。然而,那里的答案解释了问题的根本原因,而不是实际发生的情况。

第 1 部分 - 是什么原因造成的?

Hashbang 解析从未真正标准化。Here是 Sven Mascheck 写的一篇非常好的文章,其中还包括一个包含不同操作系统行为的表。

该表显示,例如Linux 确实如此所有参数合二为一, 意思是#!/usr/bin/env A=b bash执行env with 'A=b bash'作为第一个参数。

第 2 部分 -- 为什么是无限循环?

发生的事情是,env执行后,会设置环境变量A='b bash'然后重新执行原来的脚本。这导致内核再次重新解释 hashbang,我们得到了无穷无尽的结果env-执行循环。

经过一番思考,问题就变得很明显了:

A file test.sh与第一行#!/bin/sh param执行/bin/sh as '/bin/sh' 'param' 'test.sh'。脚本名称作为新的命令行参数附加(即argv).

因此在这个例子中,env实际上执行为/usr/bin/env 'A=b bash'script_name.

env因此按照它的指示执行,设置变量并执行script_name。这再次开始 hashbang 解释,我们得到了循环。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 `#!/usr/bin/env var=val command` 会陷入无限循环 的相关文章

随机推荐

  • 使用函数解析函数参数的正则表达式

    我想获取字符串的函数参数 sample 5 5 euros 这适用于 s 演示在这里 问题是当我将另一个函数放入参数中时 sample decimal 5 5 euros 仅适用于以下功能 s 演示在这里 但是对于两个或更多函数 我无法获取
  • 将新绘图添加到现有图形中

    我有一个带有一些图的脚本 请参阅示例代码 在做了一些其他事情之后 我想在现有的绘图中添加一个新的绘图 但是当我尝试它时 它会添加最后创建的图形 现在的图2 的绘图 我不知道如何改变它 import matplotlib pylab as p
  • 如何更改导航栏高度

    我看到了一个改变导航栏高度的解决方案 但对我来说没有任何作用 现在我的应用程序有一个与导航控制器连接的视图控制器 我还没有在我的项目中实现任何其他代码 在开始我的项目之前 我需要更改导航栏的高度 edited h CGSize sizeTh
  • 如何定义带有闭包的相互递归?

    我可以做这样的事情 fn func gt Vec
  • 如何解决“项目已添加。键入字典:”错误?

    我有一个应用程序 当我尝试向其中添加项目时 该应用程序被挂起 当我检查跟踪文件时 我得到了这个条目 for int i 0 i
  • 如何保留 svg 文本中的空格

    要在 svg 的文本元素中保留空格 应使用 xml space preserve 作为文本的属性 jsfiddle 但是 它不起作用 我究竟做错了什么 init snap var svgElement document getElement
  • Spring Boot Rest 中没有内容

    当方法未获取记录时 如何配置 Spring Boot 在 GET 方法 通常是 findAll 方法 中返回 204 我不想在每个方法中都做处理 输入下面的代码 if result return new ResponseEntity
  • 使用 django cms cmsplugin_filer_file 和 cmsplugin_filer_image 进行未定义上传

    我刚刚开始使用 django cms 所以请原谅我的新手 每次我尝试在管理区域上传文件时 例如 图像文件使用cmsplugin filer file cmsplugin filer image它 在剪贴板区域中显示为未定义 这很奇怪 因为
  • WifiManager.calculateSignalLevel(RSSI, 5) 问题

    我正在尝试使用 Wifimanager 来计算扫描期间找到的接入点的信号级别 我正在使用以下方法 WifiManager calculateSignalLevel int int 但无论 RSSI 级别是多少 它似乎总是返回相同的 int
  • 使用循环中的复杂命令在 gnome 终端中打开多个选项卡

    我有一个需要这样调用的命令 command complex argument 如果我想运行 gnome terminal 并传递这个参数 它会像这样 gnome terminal e command complex argument 我想在
  • XCode 7 UI 测试:关闭系统生成的 UIAlertController 不起作用

    我有一个 UI 测试 其中涉及取消系统生成的UIAlertController 此警报要求用户授予访问设备日历的权限 测试的目标是点击后的行为OK button 1 let app XCUIApplication this code was
  • 如何判断一个点是否在二维凸多边形内部?

    我有一个凸多边形 通常只是一个旋转的正方形 并且我知道所有 4 个点 如何确定给定点 黄色 绿色 是否为inside多边形 编辑 对于这个特定的项目 我无法访问 JDK 的所有库 例如 AWT 这一页 http www ecse rpi e
  • 无法在 junit 中模拟 BufferedWriter 类

    我在源代码中使用 BufferedWriter 对象 BufferedWriter outputToErrorFile new BufferedWriter new FileWriter file outputToErrorFile app
  • 如何找到像素级标准差?

    我有 20 个具有相同分辨率和范围的栅格 这是一个时间序列 每个栅格都是一年 我想计算所有栅格的像素标准偏差 到目前为止 我正在使用 raster 包 qq2 lt list maxras1 maxras2 maxras3 maxras4
  • 合并两个对象数组的最有效方法

    我已经解决了这个问题 不过 我正在寻找更快的解决方案 因为我的变量有数千个对象 我有两个这样的数组 var full a aa1 b bb1 a aa3 b bb2 a aa3 b bb3 a aa2 b bb3 some a aa1 b
  • 错误6(net::ERR_FILE_NOT_FOUND):找不到文件c或目录

    我正在使用 scriptcase php 代码生成器 它安装在服务器中 但我通过网络访问它 一切都很好 直到有人注销了服务器的管理员 这是我使用的用户 我重新启动了服务器并以管理员身份登录 但现在我无法从 chrome 访问 scriptc
  • 将执行计时代码放入函数中,OpenCV?

    我在我的程序 C 和 OpenCV 中随处使用了这个代码片段 它用于计时一些操作 double t Some code t double getTickCount Object1 LotOfComputing t 1000 double g
  • wait Promise.all() 和多个await 之间有什么区别?

    之间有什么区别 const result1 result2 await Promise all task1 task2 and const t1 task1 const t2 task2 const result1 await t1 con
  • 链接 Ajax URL 的正确方法

    在我的插件中 我有一些 jQuery Ajax 代码 用于处理表单数据并在单击按钮后将其添加到数据库中 由于许多人的插件文件夹路径不同 我想知道是否有办法标准化指向数据处理 PHP 文件的 URL 请参阅下面我的示例 ajax type P
  • 为什么 `#!/usr/bin/env var=val command` 会陷入无限循环

    In man 1 env it say env OPTION NAME VALUE COMMAND ARG 所以考虑print A sh usr bin env A b bash echo A is A 当我运行它时 print A sh它