-
Notifications
You must be signed in to change notification settings - Fork 29.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
child_process: add shell option to spawn()
This commit adds a shell option, to spawn() and spawnSync(). This option allows child processes to be spawned with or without a shell. The option also allows a custom shell to be defined, for compatibility with exec()'s shell option. Fixes: #1009 PR-URL: #4598 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com>
- Loading branch information
1 parent
504b01b
commit 1c81530
Showing
4 changed files
with
144 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
'use strict'; | ||
const common = require('../common'); | ||
const assert = require('assert'); | ||
const cp = require('child_process'); | ||
|
||
// Verify that a shell is, in fact, executed | ||
const doesNotExist = cp.spawn('does-not-exist', {shell: true}); | ||
|
||
assert.notEqual(doesNotExist.spawnfile, 'does-not-exist'); | ||
doesNotExist.on('error', common.fail); | ||
doesNotExist.on('exit', common.mustCall((code, signal) => { | ||
assert.strictEqual(signal, null); | ||
|
||
if (common.isWindows) | ||
assert.strictEqual(code, 1); // Exit code of cmd.exe | ||
else | ||
assert.strictEqual(code, 127); // Exit code of /bin/sh | ||
})); | ||
|
||
// Verify that passing arguments works | ||
const echo = cp.spawn('echo', ['foo'], { | ||
encoding: 'utf8', | ||
shell: true | ||
}); | ||
let echoOutput = ''; | ||
|
||
assert.strictEqual(echo.spawnargs[echo.spawnargs.length - 1].replace(/"/g, ''), | ||
'echo foo'); | ||
echo.stdout.on('data', (data) => { | ||
echoOutput += data; | ||
}); | ||
echo.on('close', common.mustCall((code, signal) => { | ||
assert.strictEqual(echoOutput.trim(), 'foo'); | ||
})); | ||
|
||
// Verify that shell features can be used | ||
const cmd = common.isWindows ? 'echo bar | more' : 'echo bar | cat'; | ||
const command = cp.spawn(cmd, { | ||
encoding: 'utf8', | ||
shell: true | ||
}); | ||
let commandOutput = ''; | ||
|
||
command.stdout.on('data', (data) => { | ||
commandOutput += data; | ||
}); | ||
command.on('close', common.mustCall((code, signal) => { | ||
assert.strictEqual(commandOutput.trim(), 'bar'); | ||
})); | ||
|
||
// Verify that the environment is properly inherited | ||
const env = cp.spawn(`"${process.execPath}" -pe process.env.BAZ`, { | ||
env: Object.assign({}, process.env, {BAZ: 'buzz'}), | ||
encoding: 'utf8', | ||
shell: true | ||
}); | ||
let envOutput = ''; | ||
|
||
env.stdout.on('data', (data) => { | ||
envOutput += data; | ||
}); | ||
env.on('close', common.mustCall((code, signal) => { | ||
assert.strictEqual(envOutput.trim(), 'buzz'); | ||
})); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
'use strict'; | ||
const common = require('../common'); | ||
const assert = require('assert'); | ||
const cp = require('child_process'); | ||
|
||
// Verify that a shell is, in fact, executed | ||
const doesNotExist = cp.spawnSync('does-not-exist', {shell: true}); | ||
|
||
assert.notEqual(doesNotExist.file, 'does-not-exist'); | ||
assert.strictEqual(doesNotExist.error, undefined); | ||
assert.strictEqual(doesNotExist.signal, null); | ||
|
||
if (common.isWindows) | ||
assert.strictEqual(doesNotExist.status, 1); // Exit code of cmd.exe | ||
else | ||
assert.strictEqual(doesNotExist.status, 127); // Exit code of /bin/sh | ||
|
||
// Verify that passing arguments works | ||
const echo = cp.spawnSync('echo', ['foo'], {shell: true}); | ||
|
||
assert.strictEqual(echo.args[echo.args.length - 1].replace(/"/g, ''), | ||
'echo foo'); | ||
assert.strictEqual(echo.stdout.toString().trim(), 'foo'); | ||
|
||
// Verify that shell features can be used | ||
const cmd = common.isWindows ? 'echo bar | more' : 'echo bar | cat'; | ||
const command = cp.spawnSync(cmd, {shell: true}); | ||
|
||
assert.strictEqual(command.stdout.toString().trim(), 'bar'); | ||
|
||
// Verify that the environment is properly inherited | ||
const env = cp.spawnSync(`"${process.execPath}" -pe process.env.BAZ`, { | ||
env: Object.assign({}, process.env, {BAZ: 'buzz'}), | ||
shell: true | ||
}); | ||
|
||
assert.strictEqual(env.stdout.toString().trim(), 'buzz'); |