我正在使用sass-lint
NPM软件包从Rake任务中对.scss
文件进行样式检查,因此:
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
这基本上是可行的,只要发生任何林特警告或错误,Rake任务就会中止并将sass-lint
输出(包括错误)转储到控制台。
但是,直接运行时,sass-lint
会产生漂亮的彩色输出。由capture2e
捕获时,颜色会丢失。
我认为问题是sass-lint
(或节点)检测到它不在TTY中运行,因此输出纯文本。是否可以将某些Process.spawn()
选项传递给Open3.capture2e()
或其他方法,使我认为它正在TTY中运行?
(注意:我确实看过Trick an application into thinking its stdout is a terminal, not a pipe,但是macOS随附的BSD版本script
似乎不支持--return
或-c
选项,并且我在macOS上运行。)
更新:我按照Piccolo's answer尝试了script -q /dev/null
和PTY.spawn()
,但是没有运气。
script -q /dev/null …
可从命令行运行,但不能在Open3.capture2e()
中运行(它运行,但会产生单色输出和虚假的Bundler::GemNotFound
堆栈跟踪)。
对于PTY.spawn()
,将上面的代码替换为以下代码:
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
在另一个终端中,则显示为处于可中断的睡眠状态。杀死子进程并不能释放父进程。
块形式也是如此。
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
答案 0 :(得分:1)
您是否考虑过使用Ruby出色的pty
库而不是Open3
?
每个the thread you linked的伪终端似乎都模拟了实际的TTY,因此脚本除非知道$TERM
之类的脚本,否则不会知道它不在终端中,但是这也可以相对容易被欺骗。
根据this flowchart,使用pty
而不是Open3
的缺点是STDERR
不会获得自己的流。
或者,根据this answer,也从您链接的线程来看,script -q /dev/null $COMMAND
在Mac OS X上似乎可以解决问题。
在Mac上,ls -G
为ls
的输出着色,作为简短测试,我将ls -G
传递给cat
如下:
script -q /dev/null ls -G | cat
它以彩色显示,而只需运行
ls -G | cat
没有。
此方法在irb
中也有效,再次使用ls -G
:
$ 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 >