child_process
Reproduction of the error: https://gist.github.com/smrq/f028b22bc748af9e68a7
On Windows, child_process.spawn
handles the command incorrectly when both it and one of its arguments contains a space. So, this works fine:
var spawn = require('child_process').spawn;
spawn('nospaces.cmd', ['arg with spaces']);
spawn('command with spaces.cmd', ['nospaces']);
But this yields 'command' is not recognized as an internal or external command, operable program or batch file.
:
spawn('command with spaces.cmd', ['arg with spaces']);
(This is node-v0.x-archive #25895, still extant in higher Node.js versions.)
/cc @nodejs/platform-windows
I can reproduce, working on a fix.
I've had success using https://github.com/nodejs/node-v0.x-archive/issues/25895#issuecomment-180402332 from the linked issue as a work around.
Is this an issue with exec()
too?
They are related, exec
internally calls spawn
.
The problem is in how shell commands are executed under Windows. I have a fix almost ready, I'll publish it probably tomorrow.
Does this _not_ happen on v4?
exec internally calls spawn.
I get that. I was asking if exec()
was affected as well, since it does some manipulation before passing to spawn.
@mcollina Problem exists on v4.4.4 as well.
@s100 can you check on v4.4.7
LTS is affected for sure thats what I'm using.
Im my case we are only using spawn but given its at the point of exec I assume its affected too.
@TheAlphaNerd still present on v4.4.7. Any others?
Unfortunately I haven't been able to find a fix that would not also break a lot of other use cases. But there is luckily easy work around for this issue - you need to quote script filename and add shell:true
to options:
spawn('"with spaces.cmd"', ['arg with spaces'], { shell: true });
Thats pretty much what my fixed boiled down to, quoting the cmd
Kindest Regards,
Dean
On 30 Jun 2016, at 17:59, Bartosz Sosnowski [email protected] wrote:
Unfortunately I haven't been able to find a fix that would not also break a lot of other use cases. But there is luckily easy work around for this issue - you need to quote script filename and add shell:true to options:
spawn('"with spaces.cmd"', ['arg with spaces'], { shell: true });
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.
I don't think we can do anything more with this so I'm closing the issue. You can always reopen it if you feel so.
@bzoz Do you mean that the issue is fixed now?
@s100 sorry, I didn't make myself clear and provide summary. My bad.
The thing is, there is no way to fix this. When calling shell scripts under Windows, you need to add {shell: true}
to make sure things work ok (doc link). Shell scripts are not executable files under Windows, so they need special treatment. Also, Windows takes all arguments as single strings, not as array like Linux does.
When the script filename has space in it, it needs to be quoted. We cannot do this automatically - spawn
is used by exec
, for which users pass command and arguments as a single string. If we would add quotes we would break usages like in test-exec.js:93.
FWIW I've opened a PR to add a example to the documentation: https://github.com/nodejs/node/pull/8035
When the script filename has space in it, it needs to be quoted. We cannot do this automatically -
spawn
is used byexec
, for which users pass command and arguments as a single string. If we would add quotes we would break usages like in test-exec.js:93.
How does that follow? exec
on Windows is implemented in terms of spawn(…, { windowsVerbatimArguments: true })
, but shouldn’t spawn
without windowsVerbatimArguments
quote and escape the command and arguments?
Currently there’s no way to make a command like childProcess.spawn('npm', ['install', 'eslint@>=4.1.1'])
work in a cross-platform way. It works on Unix, but as written it fails with ENOENT on Windows, and with { shell: true }
the shell mangles the command and redirects the output of npm install eslint@
to a file named =4.1.1
. The latter failure also happens without { shell: true }
if the 'npm'
is changed to 'npm.cmd'
.
For anyone who comes here just looking for a workaround like I did, the cross-spawn package seems to implement the right API.
// DON'T WRITE THE http://
var options = {
host: 'http://yoururl.com',
path: '/path/to/resource'
};
Most helpful comment
Unfortunately I haven't been able to find a fix that would not also break a lot of other use cases. But there is luckily easy work around for this issue - you need to quote script filename and add
shell:true
to options:spawn('"with spaces.cmd"', ['arg with spaces'], { shell: true });