首页 > 解决方案 > 飞镖子进程无权访问终端

问题描述

我有一个 dart 进程,它产生一个子 dart 进程。

父 dart 进程可以访问终端,我可以通过调用进行检查:

stdin.hasTerminal

然而,当我调用 stdin.hasTerminal 时,子 dart 进程返回 false。

父进程将每个 stdin/stdout/stderr 连接到子进程,这是我认为子进程访问终端所需的全部内容。

这是我用来生成子飞镖进程的方法:

父.dart

import 'dart:async';
import 'dart:cli';
import 'dart:io';

void main() {
  print('parent hasTerminal=${stdin.hasTerminal}');
  // Execute the script
  final process = waitFor<Process>(Process.start('dart', ['child.dart']));

  // Pipe std out and in
  final StreamSubscription stderrSub =
      process.stderr.listen((List<int> d) => stderr.add(d));
  final StreamSubscription stdoutSub =
      process.stdout.listen((List<int> d) => stdout.add(d));
  final StreamSubscription stdinSub =
      stdin.listen((List<int> d) => process.stdin.add(d));

  final exitCode = waitFor<int>(process.exitCode);

  final futures = <Future<void>>[];

  futures.add(stderrSub.cancel());
  futures.add(stdoutSub.cancel());
  futures.add(stdinSub.cancel());

  waitFor<void>(Future.wait(futures));

  exit(exitCode);
}

这是我产生的子进程:

孩子.dart

import 'dart:io';

void main() {
  print('child: has terminal: ${stdin.hasTerminal}');
}

您可以通过将两个文件放在同一目录中并运行以下命令来运行该示例:

飞镖父母.dart

当我运行应用程序时,我得到:

dart parent.dart 
parent hasTerminal=true
child: has terminal: false

我确实想知道使用“dart child.dart”启动子进程是否可能是问题的一部分。

所以我使用 dart2native 编译了 child.dart 脚本,然后将父脚本更改为直接调用新的可执行文件'child'。

然而结果是一样的。即使我直接生成了 exe,孩子也无法访问终端。

我应该注意,如果我运行子 exe 或dart child.dart从 cli 运行,则子脚本可以访问终端。

标签: dartterminalcommand-line-interface

解决方案


所以事实证明这比预期的要容易。

以下脚本启动vi填充fred.text作为要编辑的文件的名称。

然后代码等待vi完成。

import 'dart:cli';
import 'dart:io';

void main()
{
  // Execute the script
    final process = waitFor<Process>(Process.start('vi', ['fred.text'],
        mode: ProcessStartMode.inheritStdio));

    final exitCode = waitFor<int>(process.exitCode);
}

Process.start 方法具有模式“inheritStdio”。当您设置此 dart 时,会将子进程直接附加到终端。

第一次调用 waitFor 导致脚本等待“vi”启动,第二次调用 waitFor 导致脚本等待“vi”结束。

在这种情况下,您无法拦截在孩子和终端之间移动的 io,但我想不出任何有用的情况。


推荐阅读