这种行为很难解释,所以这里提供一个可以重现的示例(在 macOS 上测试过)。
首先,我有以下C文件。细节并不重要,但基本上我使用read
系统调用从标准输入读取16个字节,或者在遇到EOF时停止读取。注意,read
在遇到EOF时会返回0。
// test.c
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main() {
char buf[1];
for (int i = 0; i < 16; i++) {
if (read(STDIN_FILENO, buf, 1) == 0) {
printf("EOF encountered! Number of bytes read: %d\n", i);
return 0;
}
}
printf("Read all 16 bytes\n");
return 0;
}
假设我将这个文件编译成名为test
的二进制文件。以下是程序的运行过程:
$ echo 'sixteen bytes!!' | ./test
Read all 16 bytes
$ echo '' | ./test
EOF encountered! Number of bytes read: 1
$ ./test # Waits for user input
有道理吧?我甚至可以将最后一个命令作为后台进程运行(虽然这很无用):
$ ./test &
[1] 19204
[1] + suspended (tty input) ./test
假设我将以下命令放入以下shell脚本中(名为huh.sh
):
#!/bin/sh
./test &
当我运行这个shell脚本时,下面是输出结果:
$ ./huh.sh
EOF encountered! Number of bytes read: 0
这意味着read
在遇到EOF时立即退出,而这种情况只会发生在shell脚本的上下文中。
如果我将test
替换为另一个对EOF敏感的程序,我会看到类似的行为。例如,如果我直接在终端中运行node &
,我将能够在ps
的输出中看到node
进程。但是,如果我在shell脚本中运行node &
,它会立即退出。
有人能解释一下吗?