lesser-evil/shell-verbosity-is-evil

v1.0.0 2022-11-02 23:02 UTC

This package is auto-updated.

Last update: 2024-08-30 01:44:04 UTC


README

SHELL_VERBOSITY 环境变量是在 symfony/console 3.4 中引入的,并且在 symfony/console 6.2 中仍然存在。它定义了一种粘性很强的详细程度。

理论似乎是这样的:如果你以详细模式(-v)调用一个命令,并且它调用任何子命令,那么所有这些子命令也应该以详细模式运行。我认为,如果各种命令遵循简单的、顺序性的程序,并将输出显示给人类,那么这是可以的。

但是,当程序以 Unix 风格 组合 时,这种约定是有害的。为了简单起见,考虑一个调用子命令的 Symfony Console 命令(snafu)。

class SnafuCommand extends Command {
  public function execute(...) {
    shell_exec('find_data | filter_data > /tmp/my_data.json');
    $data = json_decode(file_get_contents('/tmp/my_data.json'));
  }
}

如果你调用 snafu -v,那么 Symfony 会秘密地将 SHELL_VERBOSITY=1 设置为每个子进程。因此,filter_data 接收到 SHELL_VERBOSITY=1 并开始输出处理日志 - 除了其常规 JSON 输出之外。现在,文件 /tmp/my_data.json 就不再是 JSON 了 - 它是 JSON 加随机噪音。所以任何读取 my_data.json 的东西都会崩溃。

整体效果是使系统变得不可靠。任何基于 Symfony 的命令都可以通过设置(SHELL_VERBOSITY)或因它而损坏(通过接受 SHELL_VERBOSITY)。如果出现问题,你必须遍历进程图以找到导致问题的两个相关方。破坏只发生在运行 snafu -v 时。如果你单独运行命令,或者以正常方式运行 snafu,那么它就能正常工作 - 这将会困扰调试工作。

当然,使用 -v 的原因是为了调试某个东西。如果 -v 本身造成另一个错误,那么你正在调查两个错误的组合行为。

如何移除 SHELL_VERBOSITY

朋友不会让朋友使用 SHELL_VERBOSITY。这个仓库定义了一个用于杀死 SHELL_VERBOSITY 的适配器。

composer require lesser-evil/shell-verbosity-is-evil

在 Symfony 3.4 - 6.2 中,SHELL_VERBOSITY 的行为由 Application::configureIO() 定义。重写这个方法

use LesserEvil\ShellVerbosityIsEvil;

class MyApplication extends Application {
  protected function configureIO(InputInterface $input, OutputInterface $output) {
    ShellVerbosityIsEvil::doWithoutEvil(function() use ($input, $output) {
      parent::configureIO($input, $output);
    });
  }
}