Skip to content
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.spawn does not work with npm run scripts on windows. #3675

Closed
sanemat opened this issue Nov 5, 2015 · 26 comments
Closed

child_process.spawn does not work with npm run scripts on windows. #3675

sanemat opened this issue Nov 5, 2015 · 26 comments
Labels
child_process Issues and PRs related to the child_process subsystem. invalid Issues and PRs that are invalid.

Comments

@sanemat
Copy link

sanemat commented Nov 5, 2015

child_process.spawn does not work with npm run scripts on windows.

# package.json
{
  "dependencies": {
    "touch": "^1.0.0"
  },
  "scripts": {
    "test": "npm run touch1 --verbose && node test.js",
    "touch1": "touch foo.txt"
  }
}

# test.js
var spawn = require('child_process').spawn;
var touch1 = spawn('npm', ['run', 'touch1', '--verbose'], { stdio: 'inherit' });
touch1.on('error', function(err) {
  console.error(err);
  process.exit(1);
});

npm run touch1 works fine both linux and windows.

spawn('npm', ['run', 'touch1']) works fine on linux.
https://travis-ci.org/sanemat/node-windows-spawn-confirm/builds/89416274
But this does not work on windows.
https://ci.appveyor.com/project/sanemat/node-windows-spawn-confirm/build/1.0.2

{ [Error: spawn npm ENOENT]
  code: 'ENOENT',
  errno: 'ENOENT',
  syscall: 'spawn npm',
  path: 'npm' }

Is this nodejs issue? or npm issue?

confirming code: child_process.spawn does not work with npm run scripts on windows. by sanemat · Pull Request #2 · sanemat/node-windows-spawn-confirm

@bnoordhuis
Copy link
Member

I'd say a local issue. The ENOENT error code is the operating system telling you it can't find npm. You probably either need to configure your PATH environment variable or use an absolute path.

@Fishrock123 Fishrock123 added the child_process Issues and PRs related to the child_process subsystem. label Nov 5, 2015
@sanemat
Copy link
Author

sanemat commented Nov 5, 2015

@bnoordhuis
Thank you for your reply.

On windows environment (appveyor), process.env.PATH includes npm path.

where npm
C:\Program Files (x86)\nodejs\npm 
C:\Program Files (x86)\nodejs\npm.cmd
process.env.PATH
C:\Program Files (x86)\nodejs\node_modules\npm\bin\node-gyp-bin;C:\projects\node-windows-spawn-confirm\node_modules\.bin;C:\Perl\site\bin;C:\Perl\bin;C:\windows\system32;C:\windows;C:\windows\System32\Wbem;C:\windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\bin;C:\Program Files\Google\Compute Engine\sysprep\;C:\Program Files\Google\Compute Engine\metadata_scripts\;C:\ProgramData\chocolatey\bin;C:\Program Files\Microsoft\Web Platform Installer\;C:\Tools\GitVersion;C:\Tools\PsTools;C:\Program Files\7-Zip;C:\Program Files\Git\cmd;C:\Program Files\Git\usr\bin;C:\Program Files\Mercurial;C:\Program Files (x86)\Subversion\bin;C:\Program Files\Microsoft SQL Server\120\Tools\Binn\;C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\110\Tools\Binn\;C:\Program Files (x86)\Microsoft SQL Server\120\Tools\Binn\;C:\Program Files\Microsoft SQL Server\120\DTS\Binn\;C:\Program Files (x86)\Windows Kits\8.1\Windows Performance Toolkit\;C:\Program Files (x86)\Microsoft SDKs\TypeScript\1.4\;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI\wbin;C:\Tools\WebDriver;C:\Tools\NUnit\bin;C:\Tools\xUnit;C:\Tools\MSpec;C:\Tools\Coverity\bin;C:\Program Files (x86)\nodejs\;C:\Program Files\nodejs;C:\Program Files (x86)\iojs;C:\Program Files\iojs;C:\Users\appveyor\AppData\Roaming\npm;C:\Program Files (x86)\CMake\bin;C:\go\bin;C:\Program Files\Java\jdk1.8.0\bin;C:\Python27;C:\Ruby193\bin;C:\Program Files\erl7.1\bin;C:\Users\appveyor\.dnx\bin;C:\Program Files\Microsoft DNX\Dnvm\;C:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit\;C:\Program Files (x86)\MSBuild\14.0\Bin;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow;C:\Tools\NuGet3;C:\Program Files\Amazon\AWSCLI\;C:\Program Files\Microsoft Windows Performance Toolkit\;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\120;C:\Users\appveyor\AppData\Roaming\npm;C:\Program Files\AppVeyor\BuildAgent\

https://ci.appveyor.com/project/sanemat/node-windows-spawn-confirm/build/1.0.17/job/3u42bafouw95to63

@bnoordhuis
Copy link
Member

Windows being Windows, I'm going to guess that you need to execute npm.cmd

@sanemat
Copy link
Author

sanemat commented Nov 6, 2015

You guess this?

if (windowsEnvironment) {
  var cmd = 'npm.cmd'
} else {
  var cmd = 'npm'
}
spawn(cmd, ['run', 'touch1'])

Ummm...

@bnoordhuis
Copy link
Member

Yes, like that. I'll close the bug report as it's not an issue with node.js itself.

@bnoordhuis bnoordhuis added the invalid Issues and PRs that are invalid. label Nov 6, 2015
@sanemat
Copy link
Author

sanemat commented Nov 6, 2015

thanks.

@ktstowell
Copy link

I can verify: npm.cmd works. Blegh.

@dpmott
Copy link

dpmott commented Mar 22, 2017

Well, npm.cmd works to launch the process, but later when you want to kill it (e.g. touch1.kill(), assuming that you had started a process that runs forever such as a server), the kill() command silently fails to actually terminate the process.

In my case, "npm start" would run "node server.js"; if I specify spawn('node', ['server.js']) it works beautifully. If I specify proc = spawn('npm.cmd', ['start']), the process is left running after I call proc.kill().

@sam-github
Copy link
Contributor

Above problem occurs on linux as well, its because node server.js is not your direct child, npm is, and it has a shell child, and the shell has a node server.js child.... POSIX process groups would be the unix way of dealing with this, but process groups don't exist on Windows.

@sam-github
Copy link
Contributor

Note that various npmjs.com packages exist to portably spawn npm, check them out.

@dpmott
Copy link

dpmott commented Mar 22, 2017

Thanks!

@dpmott
Copy link

dpmott commented Mar 23, 2017

In case anyone else with a similar issue finds this thread, here was my solution:

const os = require('os');
const process = spawn(...); // long running process
// ... later...
        if (os.platform() === 'win32') { // process.platform was undefined for me, but this works
          execSync(`taskkill /F /T /PID ${process.pid}`); // windows specific
        } else {
          process.kill();
        }

@alflennik
Copy link

While I can understand why the existence of a workaround could be considered a solution to this issue, I find the inclination to allow differences to proliferate between OSes disturbing. **Stands on soapbox.** JS is a cross-platform language. Node should be as well. To say that I should worry about Windows while developing in Linux on a MacBook is WRONG. And to say the bugs that come from that are my fault is WRONG. **Gets off soapbox.**

@bnoordhuis
Copy link
Member

Then use .exec() or pass { shell: true } to .spawn(). It's all in the documentation.

@publicocean0
Copy link

publicocean0 commented Jul 31, 2017

hi i have a problem with spawn

var spawn = require('child_process').spawn;
var bower = spawn('bower', ['install',comp], { stdio: 'inherit' , shell: true});
console.log('********',comp)
bower.on('error', function(err) {
  console.error(err);
  process.exit(1);
});
		bower.on('close', function(code) {
			if (code !== 0) {
				console.log('Bower failed.');
				
			}

console.log('-------------');
		

		});

	
		bower.on('exit', function(code) {
			if (code !== 0) {
				console.log('Bower failed.');
				
			}

console.log('-------e------');
		

		});
	
}

command is executed but i cant intercept when execution is finished

@601939654
Copy link

./scripts/watch-demo demos/nn-art/nn-art.ts
events.js:160
throw er; // Unhandled 'error' event
^

Error: spawn node_modules/.bin/watchify ENOENT
at exports._errnoException (util.js:1018:11)
at Process.ChildProcess._handle.onexit (internal/child_process.js:193:32)
at onErrorNT (internal/child_process.js:367:16)
at _combinedTickCallback (internal/process/next_tick.js:80:11)
at process._tickCallback (internal/process/next_tick.js:104:9)
at Module.runMain (module.js:606:11)
at run (bootstrap_node.js:390:7)
at startup (bootstrap_node.js:150:9)
at bootstrap_node.js:505:3

How can I fix this?

@Qarun-Qadir-Bissoondial

Hey everyone, not sure how relevant my comment is going to be, but i managed to run my npm run commands using child_process.exec() instead of spawn().

My current example uses a Nrwl workspace, but it can work for any npm commands really.

const exec = require('child_process').exec
const execContext = exec('npm run affected:libs');

const stdOutMessages = [];

execContext.stdout.on('data', (cmd) => {
    console.log('Getting stdout data...');
    stdOutMessages.push(cmd)
});

execContext.stdout.on('close', () => {
    console.log('stdout closed...');
    console.log(stdOutMessages.join(''));
});

Produces the following output in the terminal:

Getting stdout data...
Getting stdout data...
Getting stdout data...
stdout closed...

> my-lib@0.0.0 affected:libs C:\Users\qbissoondial\work\my-lib
> nx affected:libs


>  NX  Affected libs:

  - my-lib

I'm on Node version 12 and I ran this on a Windows 10 machine without any problems. I didn't need to use npm.cmd either.

@AllanOricil
Copy link

Then use .exec() or pass { shell: true } to .spawn(). It's all in the documentation.

THANK YOU SO MUCH FOR YOUR ANSWER!
I think this {shell:true} should be handled by the spawn command. Node has capacity to determine the right config to use depending on the OS. I really don't understand why they put this as an option.

@benjamingr
Copy link
Member

@AllanOricil

I really don't understand why they put this as an option.

{shell: true} doesn't just "make .spawn work" in this case. When you .exec or .spawn with shell: true node will first spawn a shell (cmd.exe by default on windows) and then run the command in that shell.

This is usually not desirable when using spawn for certain workloads. If you explicitly want this behavior (of having a shell) you can just .exec like Ben said.

@AllanOricil
Copy link

@AllanOricil

I really don't understand why they put this as an option.

{shell: true} doesn't just "make .spawn work" in this case. When you .exec or .spawn with shell: true node will first spawn a shell (cmd.exe by default on windows) and then run the command in that shell.

This is usually not desirable when using spawn for certain workloads. If you explicitly want this behavior (of having a shell) you can just .exec like Ben said.

@benjamingr thanks for the response. I don't really know if I had exactly same problem, I just know that when I added the following option to my code, it started to work on windows. I'm using sfdx cli, which is built using Ocliff. The sfdx cli allow us to extend the native functionality by creating plugins. I created on plugin that was calling a standard sfdx command using spawn, and it was working fine on linux, but when I ran it on Windows it was not working at all. Then I added the option below and the problem was solved to both environments.

shell: os.platform() === 'win32'

@kasvtv
Copy link

kasvtv commented Aug 11, 2020

In my case (windows, trying to run npm/yarn with spawn), passing {shell:true} as the third argument to spawn did the trick:

https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options

@wangrongding
Copy link

Hi, maybe this can help you.

import { spawn } from "child_process";
// or
const { spawn } = require("child_process");

// alias spawn
const exec = (commands) => {
  spawn(commands, { stdio: "inherit", shell: true });
};

// use like this
exec("npm run build");

You can change the function name exec, maybe run ?

nice,brother!

demosjarco added a commit to demosjarco/wrangler-action-node that referenced this issue Jun 23, 2023
yaacovCR added a commit to yaacovCR/graphql-js that referenced this issue Mar 17, 2024
yaacovCR added a commit to graphql/graphql-js that referenced this issue Mar 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
child_process Issues and PRs related to the child_process subsystem. invalid Issues and PRs that are invalid.
Projects
None yet
Development

No branches or pull requests