为什么 spawn 子进程仅在使用 Python 执行后才打印到标准输出?

Why does the spawn child process print to stdout only after execution with Python?

我创建了以下 node.js 代码,其中包含执行 bash 代码的 spawn 子进程:

const spawn = require('child_process').spawn

const shellcode = `
file=$(mktemp)
cat > $file <<- "EOF"
echo "Hello World"
sleep 2
echo "Hello World"
sleep 2
echo "Hello World"
sleep 2
echo "Hello World"
EOF

bash $file
`

const child = spawn('/bin/bash', [ '-c',  shellcode ])

child.stdout.on('data', (data) => {
    console.log(data.toString())
})

它工作得很好,它在 shellcode 变量中执行 bash 并打印 Hello Worldnode.js 代码是 运行。

我的问题始于 Python,我创建了以下代码:

const spawn = require('child_process').spawn

const shellcode = `
file=$(mktemp)
cat > $file <<- "EOF"
import os

print('Hello World')
os.system("sleep 2")
print('Hello World')
os.system("sleep 2")
print('Hello World')
os.system("sleep 2")
print('Hello World')
EOF

python3 $file
`

const child = spawn('/bin/bash', [ '-c',  shellcode ])

child.stdout.on('data', (data) => {
    console.log(data.toString())
})

但是,此代码不会作为 spawn 代码执行。它等待进程完成以将结果打印到标准输出。我还使用 shellcode 变量中的 node.js 代码测试了相同的逻辑,它工作正常,就像 bash 一样。我错了什么?我不确定这是 Python 问题还是 node.js 问题。为什么 Python 代码不作为 spawn 运行(它正在等待进程完成以打印其输出)?

Python 默认缓冲其输出。

运行 python -u ... 或将 PYTHONUNBUFFERED 环境变量设置为 1.

顺便说一句,这里根本没有理由使用 bash – Python 可以愉快地从标准输入读取代码并在没有临时文件的情况下执行它:

const spawn = require('child_process').spawn

const shellcode = `
import os, time

print('Hello 1')
time.sleep(2)
print('Hello 2')
time.sleep(2)
print('Hello 3')
time.sleep(2)
print('Hello 4')
`.trim();

const child = spawn('/usr/bin/python3', ['-u', '-'], {stdio: ['pipe', 'pipe', 'inherit']});
child.stdin.write(shellcode);
child.stdin.end();
child.stdout.on('data', (data) => {
    console.log(new Date(), data.toString());
});

打印出来(在撰写本文时):

2022-01-19T13:18:16.084Z Hello 1

2022-01-19T13:18:18.088Z Hello 2

2022-01-19T13:18:20.091Z Hello 3

2022-01-19T13:18:22.093Z Hello 4