-
Notifications
You must be signed in to change notification settings - Fork 29.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
child-process: support any shells on Windows #21943
Conversation
lib/child_process.js
Outdated
@@ -399,7 +400,7 @@ function normalizeSpawnArguments(file, args, options) { | |||
if (Array.isArray(args)) { | |||
args = args.slice(0); | |||
} else if (args !== undefined && | |||
(args === null || typeof args !== 'object')) { | |||
(args === null || typeof args !== 'object')) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you undo unrelated style changes? They make review harder, break git blame
, and tend to induce merge conflicts.
test('cmd.exe'); | ||
test('C:\\WINDOWS\\system32\\cmd.exe'); | ||
test('powershell'); | ||
test('C:\\Program Files\\Git\\bin\\bash.exe'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it a build requirement to have git bash installed on Windows?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, git bash is one of prerequisites.
Basic Unix tools required for some tests, Git for Windows includes Git Bash and tools which can be included in the global PATH.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bash for windows is not a build requirement, but ATM it's a requirement for running the test suite.
Lines 265 to 267 in 5384570
* Basic Unix tools required for some tests, | |
[Git for Windows](http://git-scm.com/download/win) includes Git Bash | |
and tools which can be included in the global `PATH`. |
However it is not guaranteed to be at C:\\Program Files\\Git
. This could be done by running where bash
, and also skipping if it not found.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should not be assuming any paths, e.g. the SystemDrive
might not be C:
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I had a misunderstanding.
Well, can I use exec
in the exec
test? If not, is there a workaround?
// Replace the test L23 to the following.
cp.exec('where bash', (error, stdout) => {
if (error) {
return;
};
test(stdout.trim());
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, or execSync
.
test('cmd.exe'); | ||
test('C:\\WINDOWS\\system32\\cmd.exe'); | ||
test('powershell'); | ||
test('C:\\Program Files\\Git\\bin\\bash.exe'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bash for windows is not a build requirement, but ATM it's a requirement for running the test suite.
Lines 265 to 267 in 5384570
* Basic Unix tools required for some tests, | |
[Git for Windows](http://git-scm.com/download/win) includes Git Bash | |
and tools which can be included in the global `PATH`. |
However it is not guaranteed to be at C:\\Program Files\\Git
. This could be done by running where bash
, and also skipping if it not found.
node/test/parallel/test-child-process-spawnsync-shell.js Lines 59 to 61 in f5a2167
This test failed because it expects to use options like |
yes, absolutely! |
511b977
to
17ded87
Compare
Why did the test fail? I can't reproduce the error on my local repository.
|
@tkamenoko Don't worry about this one. It happens often on Travis |
@targos Thanks. |
started one more CI , to be certain. |
Does any of the documentation need updating? |
Are http2 tests flaky?
They both got the same error:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tkamenoko thanks for working on this! I left a few comments that I believe should be addressed, but other than that this is looking good.
I noticed you are adding commits with descriptions for your changes. Usually when we land PRs we squash into only one commit (or more in some cases). In this case, we can keep the title and description of the first commit, so I want to make sure you're OK with that. This can happen only when landing, having multiple commits here in the PR is great if we ever have to come back and understand where something came from.
This PR changes the behavior described in https://github.com/nodejs/node/blob/a4ce449bb7b0e2f9edba75baf2a2f652a6750454/doc/api/child_process.md#shell-requirements . Since child_process
is marked as stable, this will have to be semver major, and that section has to be adjusted to reflect these changes. Let me know if you'd like me to suggest some concrete text.
lib/child_process.js
Outdated
// '/d /s /c' is used only for cmd.exe. | ||
if (file.endsWith('cmd.exe') || file.endsWith('cmd')) { | ||
args = ['/d', '/s', '/c', `"${command}"`]; | ||
options.windowsVerbatimArguments = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
windowsVerbatimArguments
should be set out of this if block, to be active for any shell (this is mentioned in the documentation for spawn)
lib/child_process.js
Outdated
args = ['/d', '/s', '/c', `"${command}"`]; | ||
options.windowsVerbatimArguments = true; | ||
// '/d /s /c' is used only for cmd.exe. | ||
if (file.endsWith('cmd.exe') || file.endsWith('cmd')) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
String comparison should be case insensitive
if (error) { | ||
return; | ||
} | ||
test(stdout.trim()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The output of where
can have more than one line (in my machine I have bash
from git and WSL). There is an example of using where
here, but it can probably be simplified for this case.
|
||
test('cmd'); | ||
test('cmd.exe'); | ||
test('powershell'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also include a more complex PowerShell test (with quotes and pipes)? Something like
cp.exec(`Get-ChildItem "${__dirname}" | Select-Object -Property Name`,
{ shell: 'PowerShell' }, (error, stdout, stderror) => {
assert.ok(!error && !stderror);
assert.ok(stdout.includes('test-child-process-exec-any-shells-windows.js'));
});
@nodejs/platform-windows I like this as is, but when this lands people will start depending on this. So, now is a probably good time to discuss: do we want to have an explicit PowerShell case like the one this creates for CMD? Like CMD uses |
@joaocgreis I have 2 questions just to make sure: 1: I no longer need to write long descriptions when adding commits, right? Or, should I write descriptions? 2:
Do you mean that the code should be like this? if (file.endsWith('cmd.exe') || file.endsWith('cmd')) {// fix later
args = ['/d', '/s', '/c', `"${command}"`];
} else {
args = ['-c', command];
}
options.windowsVerbatimArguments = true; Thanks. |
1: no need to write descriptions, just needs to be clear to the person landing this what to do with the commit. I usually write something like 2: yes, that looks correct to me. |
@tkamenoko can you make this more general? Not all shells will use |
@bzoz Sorry, I can't decide by myself. This PR changes Windows shell requirements to that like Unix, except for
Your suggestion is interesting, but I don't know how to implement it without large fix. We need to discuss whether to accept shells that do not use |
@bzoz I think of exec as a way to run a line as if typed on the specified shell, it should know what arguments to use for each shell. Having an option to specify arguments would be ok, but I think it can be done in another PR if anyone is interested. Or do you think this PR should block on that? Note that quoting of the command depends on the arguments. @tkamenoko your update looks good, but I'm having issues running the test locally. Please let me investigate. The documentation update is still needed in https://github.com/nodejs/node/blob/a4ce449bb7b0e2f9edba75baf2a2f652a6750454/doc/api/child_process.md#shell-requirements . I suggest something like this:
|
The shell argument thingy can be done in another PR, this PR can land as it is. |
5c3943a
to
3a036cc
Compare
Test failure is related: the full listing of our |
On Windows, normalizeSpawnArguments set "/d /s /c" for any shells. It cause exec and other methods are limited to cmd.exe as a shell. Powershell and git-bash are often used instead of cmd.exe, and they can recieve "-c" switch like unix shells. So normalizeSpawnArguments is changed to set "/d /s /c" for cmd.exe, and "-c" for others. Fixes: nodejs#21905
Modify indent, and replace doublequote to singlequote.
This test ensure that child_process.exec can work with any shells. Giving a shell name if $path is defined, or full path is given. Testing with cmd, powershell, and git-bash, but the test fails when testing with git-bash. Git-bash is usually placed at 'C:\Program Files\Git\bin\', and it has a space that cause the failure.
When giving 'echo foo bar' to powershell, the result contains a new line like: foo bar This commit enables to test with poweshell correctly.
Before this commit, if given path contained spaces, like 'Program Files', exec failed to find a shell. 'options.windowsVerbatimArguments' is used for cmd.exe only, and spaces are escaped correctly.
Auto-formatting cause unnecessary indentations. These style changes are removed.
test-child-process-any-shell uses `where` before testing with bash to remove hard coding path.
This test expected to use cmd.exe options even if the shell was powershell. This commit fixes to check correct options for shells other than cmd.exe.
a624cb7
to
60437d2
Compare
60437d2
to
7a10600
Compare
@tkamenoko I pushed a commit to address the test failure. Feel free to change it or remove it if you don't agree with it. Rebased and new CI: https://ci.nodejs.org/job/node-test-pull-request/16929/ |
Landed in af883e1 Thanks for your contribution @tkamenoko ! |
On Windows, normalizeSpawnArguments set "/d /s /c" for any shells. It cause exec and other methods are limited to cmd.exe as a shell. Powershell and git-bash are often used instead of cmd.exe, and they can recieve "-c" switch like unix shells. So normalizeSpawnArguments is changed to set "/d /s /c" for cmd.exe, and "-c" for others. Fixes: #21905 PR-URL: #21943 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: João Reis <reis@janeasystems.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com>
In which version of node was this released? |
@ackvf It hasn't. This is |
On Windows, child_process methods like
exec
supported only cmd.exe as the shell. This change enables these methods to accept any shells using-c
switch like Unix shells.Fixes: #21905
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes