我正在尝试在 dart 中运行二进制文件宽度 Process.start 并将其输出重定向到 stdout 并将 stdin 传输到进程。
这是我的代码:
import 'dart:io';
import 'dart:convert';
main() async {
Process.start('./test.bin', []).then((p) {
p.stdout.listen((bytes) {
stdout.add(bytes);
stdout.flush();
});
stdin.pipe(p.stdin);
});
}
问题是它仅在进程终止后刷新进程的标准输出。
在互联网上进行挖掘后,我发现:“这是由 libc 引起的,当未连接到终端时,它默认将 stdout int 缓冲模式置于其中。”
我如何告诉进程它正在从终端运行?
我这个项目的目标是在 web 应用程序中拥有一个终端,与后端运行的进程交互,因此它将在终端上运行,但进程显然不知道这一点。
我正在回答我自己的问题,以防有人发现这篇文章。
我最终在这个库的帮助下用nodejs编写了后端(https://www.npmjs.com/package/node-pty)
但是我也找到了一个类似的 dart 库(https://pub.dev/packages/pty)
NodeJS 在子进程管理方面表现更好。但我认为你可以使用某些类型的缓冲区分割来修复你的代码。按行分割的示例:-
var process = await Process.start(cmd, param,
environment: env,
includeParentEnvironment: true,
runInShell: true,
mode: ProcessStartMode.normal);
Stream<String> readLine() => process.stdout
.transform(utf8.decoder)
.transform(const LineSplitter());
readLine().listen(callback);
var exitcode = await process.exitCode;
print("Process Exit:- " + exitcode);
此代码从新进程重定向所有 stdio 流。有一些细节
代码:
final child = await Process.start(command, args, runInShell: true);
if (stdin.hasTerminal) {
stdin.lineMode = false;
unawaited(stdin.pipe(child.stdin));
}
unawaited(child.stdout.pipe(stdout));
unawaited(child.stderr.pipe(stderr));
if (await child.exitCode != 0) {
throw Exception(
'Failed to execute $command ${args.join(' ')}: with code ${await child.exitCode} ${child.stderr}',
);
}