gpt4 book ai didi

unix - 为什么 `#!/usr/bin/env var=val command`会进入死循环

转载 作者:行者123 更新时间:2023-12-01 13:49:21 36 4
gpt4 key购买 nike

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

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 中运行命令并不等同于在命令行中运行它,但是,为什么它会进入无限循环?

最佳答案

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

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

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

该表显示,例如Linux 将所有参数合而为一,这意味着 #!/usr/bin/env A=b bash 执行 env with 'A =b bash' 作为第一个参数。

第 2 部分 -- 为什么会出现无限循环?

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

稍微思考一下,问题就变得相当明显了:

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

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

env 这样就按照它的指示进行操作,设置变量,然后执行 script_name。这再次启动 hashbang 解释,我们得到了我们的循环。

关于unix - 为什么 `#!/usr/bin/env var=val command`会进入死循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33126309/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com