Nick
Nick

Reputation: 1718

Why would calling a child_process command work with exec but not spawn?

Why would this work:

var exec = require("child_process").exec;
var command = exec("grunt");

But this throws an error:

var spawn = require("child_process").spawn;
var command = spawn("grunt");

The error it throws is Error: spawn ENOENT

At first I thought it might have something to do with the env, but it is exactly the same in both exec and spawn. I think it must somehow have something to do with Grunt, since trying git works in both.

Upvotes: 1

Views: 1387

Answers (3)

ekcrisp
ekcrisp

Reputation: 1911

From the docs, child_process.exec "Spawns a shell then executes the command within that shell", while child_process.spawn "spawns a new process using the given command". A shell, such as bash is an application that lets you execute compiled binaries defined in locations specified by the PATH. Exec behaves the same way as the shell it spawns, while spawn looks for compiled binaries in your PATH directly (probably by calling the C function execvp). I don't know the specifics of grunt, but it is likely not a compiled binary on your path, and probably gets added to the shell context a different way such as an alias in your .bashrc

Upvotes: 0

Lewis
Lewis

Reputation: 14876

I got the same problem. It only appears on Windows platform. And finally, I found this issue that helped me out of this stuff.

I followed isaacs suggestion:

The cmd is either "sh" or "cmd" depending on platform, and the arg is always either /c $cmd or -c $cmd.

child = child_process.spawnShell('util.bat glerp gorp', {options...})

Which would be sugar for:

child = child_process.spawn(isWin ? 'cmd' : 'sh', [isWin?'/c':'-c', arg], options)

Then, I wrote my own simple spawnShell:

var spawn = require('child_process').spawn;    
function spawnShell(args,options){
    var isWin = (process.platform === 'win32');
    args.unshift(isWin ? '/c' : '-c');
    return spawn(isWin ? 'cmd' : 'sh', args, options);
}

Although it's a little late, hopefully my answer still can help somebody else in the future.

Upvotes: 2

user568109
user568109

Reputation: 48003

On checking the node docs for spawn I found:

Note that if spawn receives an empty options object, it will result in spawning the process with an empty environment rather than using process.env. This due to backwards compatibility issues with a deprecated API.

The default option for env in exec is null, but for spawn it is process.env. So it is ambiguous if both are getting same env? Can you check this by giving same env explicitly for both.

Upvotes: 3

Related Questions