为什么`#!/ usr / bin / env var = val命令'进入无限循环 [英] why do `#!/usr/bin/env var=val command` gets into an infinite loop

查看:236
本文介绍了为什么`#!/ usr / bin / env var = val命令'进入无限循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

man(1)env 它说:

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 我得到以下日志,重复:

Running it with strace ./print_A.sh I get the following log, repeating:

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

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

As commented below, running a command in a hash-bang is not equivalent to running it on the command line, but still, why does it go into an infinite loop?

推荐答案

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

There two parts to this answer. One has already been given in a duplicate question. The answers there, however, explain the root cause for the problem, not what is actually going on.

第1部分 - 是什么原因?

Hashbang解析从未真正标准化。 这里是Sven Mascheck的一个很好的写作,其中还包括一个表与不同操作系统的行为。

Hashbang parsing has never been really standardized. Here is a very good writeup by Sven Mascheck, which also includes a table with the behavior for different operating systems.

该表显示例如Linux确实都在一个中引用,这意味着#!/ usr / bin / env A = b bash 执行 env 'A = b bash'作为第一个参数。

The table shows that e.g. Linux does all args in one, meaning that #!/usr/bin/env A=b bash executes env with 'A=b bash' as first argument.

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

发生什么事情是,执行 env 环境变量 A ='b bash',然后重新执行原始脚本。这导致内核再次重新解释hashbang,我们得到一个无尽的 env -exec循环。

What happens is that, env is executed, it sets the environment variable A='b bash' and then re-executes the original script. This results in the kernel re-interpreting the hashbang again and we get an endless env-exec loop.

之后有一点想法,问题变得很明显:

After a little thinking, the problem becomes quite obvious:

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

A file test.sh with first line #!/bin/sh param executes /bin/sh as '/bin/sh' 'param' 'test.sh'. The script name is appended as a new command line parameter (i.e. to argv).

因此,在该示例中, env 实际执行为 / usr / bin / env'A = b bash' script_name

Thus in the example, env is actually executed as /usr/bin/env 'A=b bash'script_name.

env 设置变量,并执行 script_name 。这再次开始hashbang解释,我们得到了我们的循环。

env thus does what it's told, sets the variable, and executes script_name. This again starts hashbang interpretation and we got our loop.

这篇关于为什么`#!/ usr / bin / env var = val命令'进入无限循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆