首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Ruby的Open3 / Process.spawn()捕获ANSI彩色输出

用Ruby的Open3 / Process.spawn()捕获ANSI彩色输出
EN

Stack Overflow用户
提问于 2018-07-25 21:12:24
回答 1查看 253关注 0票数 1

我使用sass-lint NPM包在Rake任务中对.scss文件进行样式检查,因此:

代码语言:javascript
复制
  sass_lint_cmd = "sass-lint --config #{ui_library_path}/scss/.sass-lint.yml '#{ui_library_path}/scss/*.scss' -v -q --max-warnings=0"
  output, status = Open3.capture2e(sass_lint_cmd)
  raise IOError, output unless status == 0

这基本上是起作用的,因为在发生任何linter警告或错误时,Rake任务中止,sass-lint输出(包括错误)被转储到控制台。

但是,当直接运行时,sass-lint会产生漂亮的彩色输出。当被capture2e捕获时,颜色就会丢失。

我假设问题是sass-lint (或Node)检测到它没有在TTY中运行,所以输出纯文本。是否有一些Process.spawn()选项可以传递给Open3.capture2e(),或者其他一些方法,可以让它认为它在运行在TTY中?

(注意:我确实看过Trick an application into thinking its stdout is a terminal, not a pipe,但是macOS附带的script的BSD版本似乎既不支持--return也不支持-c选项,而且我运行在macOS上。)

更新:--我尝试了script -q /dev/nullPTY.spawn(),就像Piccolo's answer一样,但没有成功。

script -q /dev/null …从命令行工作,但在Open3.capture2e()中不工作(它运行,但产生单色输出和虚假的Bundler::GemNotFound堆栈跟踪)。

对于PTY.spawn(),用以下代码替换上面的代码:

代码语言:javascript
复制
r, _w, pid = PTY.spawn(scss_lint_command)
_, proc_status = Process.wait2(pid)
output, status = [r, proc_status.exitstatus]
(warn(output); raise) unless status == 0

子进程似乎从未完成;如果我在另一个终端中ps,则显示为处于可中断的睡眠状态。杀死子进程并不能释放父进程。

同样的情况发生在块表单中。

代码语言:javascript
复制
output, status = nil
PTY.spawn(scss_lint_command) do |r, _w, pid|
  _, proc_status = Process.wait2(pid)
  output, status = [r, proc_status.exitstatus]
end
(warn(output); raise) unless status == 0
EN

回答 1

Stack Overflow用户

发布于 2018-07-25 22:02:11

你有没有考虑过使用Ruby的优秀pty库而不是Open3

按照the thread you linked的说法,伪终端似乎模拟了一个实际的TTY,所以脚本不会知道它不在终端中,除非它检查了$TERM之类的东西,但这也可以相对容易地被欺骗。

根据this flowchart的说法,使用pty而不是Open3的缺点是STDERR没有自己的流。

或者,根据this answer,也是从您链接的线程中,script -q /dev/null $COMMAND似乎在Mac上完成了这个任务。

在Mac上,ls -Gls的输出进行着色,作为一个简短的测试,我将ls -G插入cat中,如下所示:

代码语言:javascript
复制
script -q /dev/null ls -G | cat

它以颜色显示,而简单地运行

代码语言:javascript
复制
ls -G | cat

却没有。

此方法在irb中也有效,同样使用ls -G

代码语言:javascript
复制
$ touch regular_file
$ touch executable_file
$ mkdir directory
$ chmod +x executable_file
$ irb
2.4.1 :001 > require 'Open3'
 => true
2.4.1 :002 > output, status = Open3.capture2e("ls -G")
 => ["directory\nexecutable_file\nregular_file\n", #<Process::Status: pid 39299 exit 0>]
2.4.1 :003 > output, status = Open3.capture2e("script -q /dev/null ls -G")
 => ["^D\b\b\e[1m\e[36mdirectory\e[39;49m\e[0m       \e[31mexecutable_file\e[39;49m\e[0m regular_file\r\n", #<Process::Status: pid 39301 exit 0>]
2.4.1 :004 >
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51527732

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档