Pipe-redirecting Grunt's output is broken #510

Closed
jakub-g opened this Issue Nov 6, 2012 · 18 comments
@jakub-g

I'm not 100% sure the source of the problem is Grunt, but since Unix tools are rather thoroughly tested, I thought I'll start from reporting here. Can someone try to reproduce on their machines?

Version: 0.3.17
I do everything under WinXP/MINGW32 (Git 1.7.11) sh console.

Let's create a simple grunt file grunttest.js:

module.exports = function(grunt) {

  grunt.registerTask('t1', function(){
    console.log('t1 hello');
  });
  grunt.registerTask('t2', function(){
    console.log('t2 hello');
  });
  grunt.registerTask('default', 't1 t2'); 

};

Let's run it:

$ grunt --config ./grunttest.js
Running "t1" task
t1 hello

Running "t2" task
t2 hello

Prints fine, all-white (standard text color).

Let's redirect to a file:

$ grunt --config ./grunttest.js > out.txt

Open out.txt in Notepad++:

[4mRunning "t1" task[24m
t1 hello

[4mRunning "t2" task[24m
t2 hello

[32mDone, without errors.[39m

These are escape codes used to color the output. (Notepad++ additionally prints the ESC chars before the left-braces: char 27, or 0x1B, I deleted them since it was breaking the Markdown processor). cat out.txt actually produces a nice ASCII out of it, just like the first command, but colored.

The interesting starts now:

$ grunt --config ./grunttest.js | cat
Running "t1" task

When I want to pipe to cat or less, I only see the first line (in cyan). I don't see the other lines. The above yields the same BTW:

$ grunt --config ./grunttest.js 2>&1 | cat

I'm pretty sure it's not a feature ;) Can someone confirm my findings? Any guesses what the problem might be?

I've tried a simple Node.js code (a few console.logs) and it works fine on the contrary. So it seems that Grunt + colored output are the cause.

@shama
grunt member

You can use the --no-color option to remove coloring.

@jakub-g

@shama Thanks for the comment. However the problem remains -- no colors are output, but still I get only the first line while redirecting to cat / less / whatever:

$ grunt --no-color --config ./grunttest.js | cat
Running "t1" task

whereas when I redirect output to a file, it's fine:

$ grunt --no-color --config ./grunttest.js > out.txt

Open out.txt in Notepad++:

Running "t1" task
t1 hello

Running "t2" task
t2 hello

Done, without errors.
@shama
grunt member

@jakub-g Strange. I'll try on my Windows machine when I get it up and running. Not seeing that issue with OSX and Ubuntu.

@jakub-g

Some more findings after checking on my machines at home:
(using Grunt 0.3.17 & Node 0.8.14):

WinXP Professional SP3 32bit + Git 1.7.11 shell -- like above
WinXP Professional SP3 32bit + Git 1.8.0 shell -- like above
Win7 Professional SP1 32bit + Git 1.8.0 -- even worse; displaying or redirecting to file works fine, but when cat-ing I don't even see the first line. With or without --no-color

Perhaps it's a MINGW32 thing, but I've been using Git from command line for a couple of months without any issues for cating, diffing etc.

@dcherman

It's a bug in node in Windows where stdout/stderr isn't flushed properly prior to exiting the process. See nodejs/node-v0.x-archive#3584 .

FWIW I work around this in the meantime by doing grunt.cmd --no-color > grunt.tmp & type grunt.tmp & del grunt.tmp
which works because the behavior of process.stdout becomes blocking when piped to a file - http://nodejs.org/api/process.html#process_process_stdout

@cowboy
grunt member

Can you try grunt 0.4.0rc4? I'm pretty sure the problem is fixed there.

@benjamine

I got it fixed by using the workaround @dcherman suggested (pipe to a file), is far from ideal, but it works

@eddieloeffen

the problem is still in grunt 0.4.0rc7. This is the output for a failing jshint task:

Running:
node v0.8.18
Windows 7 Professional x64

>grunt jshint --no-color | more
Running "jshint:src" (jshint) task

>

If i don't pipe to more, then I get the full output with all my jshint errors

@vladikoff
grunt member

While working on grunt-devtools version for Windows (works fine in OS X), I also discovered this issue when trying to pipe output to devtools from grunt tasks. I didn't have time to debug this yet, but will let you guys know if I find anything.

@benjamine

On windows I found that using powershell (instead of .bat) can solve this problem too. (and --no-color too)

@benjamine

as @dcherman points out this is clearly not related to grunt, I have seen the same behavior when using npm and other node.js apps.

@jakub-g

#708 contains detailed info on the problem and a workaround code for this.

@adamstallard

I do remember seeing this problem in npm a while back, but it seems to have been fixed. Perhaps we should see how they fixed it and follow suit.

I know that apps that use process.exit to abort execution often suffer from this.

@andr2

It seems that Grunt.js development is dead. Very annoying bug. Thanks for fix to Adam. But what about merge?

@adamstallard

I think @andr2 is referring to #744 . I keep my fork up-to-date (i just merged a couple of trivial things), so you are welcome to use it.

@jakub-g jakub-g referenced this issue in ariatemplates/ariatemplates May 28, 2013
Closed

Node 0.10 #516

0 of 3 tasks complete
@jeanlauliac

Why grunt is not using process.stdout.isTYY and process.stderr.isTYY to disable colors automatically when out of a terminal? That's pretty much considered a standard behaviour for command line tools.

By running:

$ grunt sometask
$ grunt sometask | cat

The first should output colors, the second none, out-of-the-box. Then, it could provide a --color command to force it back.

@brandf

I'm using this workaround to remove color output while piping. Doesn't work for other ansi codes like BEEP though. Unfortunately node streams don't have a flush method, or else the same monkey patch could be used to shim synchronous writes:

if (!process.stdout.isTTY) {
    var stdOutWrite = process.stdout.write;
    process.stdout.write = function (chunk, encoding, callback) {
        stdOutWrite.call(process.stdout, grunt.log.uncolor(chunk.toString()), 'utf8', callback);
    };
}

edit: since I can't seem to make this approach work for the lack of flushing a simpler approach can be done just to remove color/beeps:

// work around a grunt bug where color output is written to non-tty output
if (!process.stdout.isTTY) {
    grunt.option("color", false);
}
@vladikoff
grunt member

This issue should be fixed via #921
Let's continue discussion there.

@vladikoff vladikoff closed this Sep 29, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment