outer.sh
:
ls -l /proc/$$/exe
coproc cat
./inner.sh
kill $!
inner.sh
:
ls -l /proc/$$/exe
set | grep COPROC || echo No match found
coproc cat
kill $!
当我运行时./outer.sh
,会打印出来:
lrwxrwxrwx 1 joe joe 0 Jun 16 22:47 /proc/147876/exe -> /bin/bash
lrwxrwxrwx 1 joe joe 0 Jun 16 22:47 /proc/147879/exe -> /bin/bash
No match found
./inner.sh: line 3: warning: execute_coproc: coproc [147878:COPROC] still exists
既然COPROC
并COPROC_PID
没有设置在孩子身上,它怎么知道来自父母的那个能够给我这个警告?
此外,我发现如果我添加#!/bin/bash
到顶部inner.sh
,或者如果我调用bash ./inner.sh
而不是仅仅./inner.sh
from outer.sh
,那么警告就会消失。为什么这会改变任何东西,因为无论哪种方式都使用 bash 子进程运行?
没有 shebang 的脚本应该由符合 POSIX 的解释器来
sh
解释。这实际上是编写 POSIX 脚本的 POSIX 方式,POSIX 没有指定 shebangs,尽管在实践中使用 shebangs 更便携/可靠,这是一个很好的例子。bash shell 就是这样一个 POSIX sh 解释器。bash (某些版本和某些自定义构建以及某些环境中)实际上是我所知道的唯一一个在运行时(而不是在运行时)被认证为兼容的 FLOSS shell 。
sh
bash
当执行无shebang脚本时,bash,当
execve()
返回ENOEXEC并检查它看起来不像二进制文件后,在他的孩子中解释它,通过尝试将其状态重置为默认值来模拟执行。但是,这意味着该脚本在运行时
bash
被解释为 bash 脚本而不是 POSIX sh 脚本,除非bash
它本身以 POSIX 模式运行(例如当作为sh
自身调用时)。查看当
a
被.bash
bash
看看如何
bash
没有执行sh
来解释脚本。您得到的事实
warning: execute_coproc: coproc [147878:COPROC] still exists
是一个错误,bash
无法正确重置其状态。在任何情况下,
coproc
不是sh
关键字,因此在无 shebang 脚本中没有它的位置。coproc
来自zsh
(而协进程来自 ksh),虽然bash
' 的实现完全不同,所以你应该在#! /bin/bash -
这里有一个 shebang。使用
bash ./inner.sh
或使用 shebang,新解释器实例的正确执行,并execve()
完全正确地擦除进程内存。