【问题标题】:Force carriage returns in IEx Ports' stderr?在 IEx Ports 的标准错误中强制回车?
【发布时间】:2020-07-06 11:30:42
【问题描述】:

如果我在 IEx 中为将任何内容打印到 stderr 的脚本打开一个端口,则任何输出都不会用回车符打印。我怎样才能解决这个问题?我正在运行无法控制其输出的外部软件,所以我不能手动添加返回。

示例

/tmp/run.sh

#!/usr/bin/env bash
>&2 echo -e "line 1\nline 2\nline 3\nline 4"

在IEx shell中

iex(1)> Port.open({:spawn_executable, "/tmp/run.sh"}, [])
line 1             
      line 2                                                                                                   
            line 3                                                                                             
                  line 4

【问题讨论】:

标签: erlang elixir elixir-iex


【解决方案1】:

我有另一个快速而肮脏的解决方案(仅限 Elixir)

Port.open({:spawn_executable, "/tmp/run.sh"}, [:use_stdio, :stderr_to_stdout, :binary, :hide]); receive do
  {_port, {:data, line}} -> String.split(line,"\n", trim: true) |> Enum.each(fn(x)-> IO.puts(x) end)
end

问题是你想对数据做什么。

更多信息链接https://bugs.erlang.org/browse/ERL-802 引用:

elixir --no-halt -e ':user_drv.start();Port.open({:spawn, "bash -c '\''>&2 echo \"stderr\nline2\"'\''"}, [:binary])' 2> err.log

【讨论】:

  • 谢谢——我的主要问题是我想将 stderr 保留在 stderr 中以用于日志记录。有没有办法在不加入 stdout 的情况下捕获 stderr?
【解决方案2】:

您可以在换行符之前插入回车符的包装器下运行脚本。这是一个使用bashperl 的包装器:

#!/usr/bin/env bash
"$@" 2>&1 | perl -pe 's/\n/\r\n/' 1>&2

这是另一个使用bashunix2dos

#!/usr/bin/env bash
"$@" 2>&1 | unix2dos 1>&2

基本上,任何可以读取原始程序的stderr,用回车和换行组合替换换行,然后将结果写入stderr的东西都可以。

将这些解决方案之一放入名为 /tmp/lf.sh 的文件中。下面我们使用原始的 /tmp/run.sh 从 iex 运行它,首先使用原始脚本,然后使用包装器:

iex(1)> Port.open({:spawn_executable, "/tmp/run.sh"}, [])
#Port<0.5>
iex(2)> line 1
              line 2
                    line 3
                          line 4

nil
iex(3)> Port.open({:spawn_executable, "/tmp/lf.sh"}, [args: ["/tmp/run.sh"]])
#Port<0.6>
iex(4)> line 1
line 2
line 3
line 4

nil
iex(5)>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-24
    • 2013-05-26
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 2019-12-05
    • 2013-05-11
    相关资源
    最近更新 更多