Skip to content
This repository was archived by the owner on Aug 11, 2022. It is now read-only.
This repository was archived by the owner on Aug 11, 2022. It is now read-only.

npm run-script doesn't work on windows when the script contains multiple commands #4040

@balupton

Description

@balupton

If I have:

{
  "scripts": {
    "test": "node ./out/test/everything-test.js",
    "prepublish": "./node_modules/.bin/projectz compile; npm test"
  }
}

And I run npm run-script prepublish on windows, no script will execute.

C:\Users\Benjamin\Documents\GitHub\ambi [dev-cakefile-replace +0 ~6 -0]> npm run-script prepublish

> ambi@2.1.4 prepublish C:\Users\Benjamin\Documents\GitHub\ambi
> node ./node_modules/projectz/bin/projectz compile; npm test

If I run the scripts manually, it works:

C:\Users\Benjamin\Documents\GitHub\ambi [dev-cakefile-replace +0 ~6 -0]> node ./node_modules/projectz/bin/projectz compile; npm test
info: Initialising project
info: Initialised project
info: Loading changes
info: Loaded 2 contributors from bevry/ambi repository
info: Loaded changes
info: Writing changes...
info: Writing package file: C:\Users\Benjamin\Documents\GitHub\ambi\package.json
info: Writing package file: C:\Users\Benjamin\Documents\GitHub\ambi\bower.json
info: Writing package file: C:\Users\Benjamin\Documents\GitHub\ambi\component.json
info: Skipping package file: jquery
info: Writing readme file: readme
info: Writing readme file: history
info: Skipping readme file: contributing
info: Skipping readme file: backers
info: Writing readme file: license
info: Wrote changes
info: Saved changes

> ambi@2.1.4 test C:\Users\Benjamin\Documents\GitHub\ambi
> node ./out/test/everything-test.js

ambi
ambi > should handle result on successful synchronous functions
ambi > should handle result on successful synchronous functions OK
ambi > should handle result on successful asynchronous functions
ambi > should handle result on successful asynchronous functions OK
ambi > should handle returned errors on unsuccessful synchronous functions
ambi > should handle returned errors on unsuccessful synchronous functions OK
ambi > should handle callbacked errors on unsuccessful asynchronous functions
ambi > should handle callbacked errors on unsuccessful asynchronous functions OK
ambi > should ignore returned errors on successfull asynchronous functions
ambi > should ignore returned errors on successfull asynchronous functions OK
ambi > should ignore returned errors on unsuccessful asynchronous functions
ambi > should ignore returned errors on unsuccessful asynchronous functions OK
ambi > should NOT handle thrown errors on unsuccessful synchronous functions
ambi > should NOT handle thrown errors on unsuccessful synchronous functions OK
ambi > should NOT handle thrown errors on unsuccessful asynchronous functions
ambi > should NOT handle thrown errors on unsuccessful asynchronous functions OK
ambi > should NOT handle asynchronous thrown errors on unsuccessful asynchronous functions
ambi > should NOT handle asynchronous thrown errors on unsuccessful asynchronous functions OK
ambi OK

9/9 tests ran successfully, everything passed
C:\Users\Benjamin\Documents\GitHub\ambi [dev-cakefile-replace +0 ~6 -0]>

Activity

balupton

balupton commented on Oct 25, 2013

@balupton
Author

Hrmmm, running the joined commands via child_process.exec doesn't work either:

C:\Users\Benjamin\Documents\GitHub\ambi [dev-cakefile-replace +0 ~6 -0]> node -e "require('child_process').exec('node ./node_modules/projectz/bin/projectz compile; npm test', {env:process.env, cwd:process.cwd()}, console.log)"
null '' ''
bear

bear commented on Oct 25, 2013

@bear

npm script runs are handled on linux/osx by calling sh so I would imagine on windows it is done by calling cmd.exe (or whatever your environment has defined) and as such I can't imagine you could expect ; to work across all OS's

even on linux I have trouble getting complex command lines to survive the journey thru nodejs and npm's script runs - so I just got used to creating wrapper bash scripts and letting the shebang line tell sh that it needs to spawn bash

i'm wondering if you can do something similar - create a foo.sh script and see if powershell's linux-like shell handling lets you get your commands run

isaacs

isaacs commented on Oct 27, 2013

@isaacs
Contributor

Commands are passed verbatim to either cmd or sh. Note that on OS X and some Linuxes, sh is actually bash with the (misnamed!) POSIXLY_CORRECT flag turned on.

Keep your command lines simple. A bash script won't work on Windows, for obvious reasons. Write a node program, or better yet, just don't use an install command. Presumably your prepublish script could just be written as a Node program, and run npm test as a spawn at the end.

Also, never ever write ./node_modules/.bin/ in your scripts. Seriously, that should just throw. What if the dep is somewhere else, installed globally, or as a parent's dep? npm puts ./node_modules/.bin in the PATH environ for a reason. Do not tightly couple to non-portable platform-specific paths! </rant>

rlidwka

rlidwka commented on Oct 28, 2013

@rlidwka
Contributor

What if the dep is somewhere else, installed globally, or as a parent's dep?

  1. As far as I know, if a dependency is installed globally or elsewhere, npm install won't find it and would install it locally anyway. So this command line would work.
  2. As far as I know, npm run-script doesn't handle parent's dep case correctly as well, so it's the same deal in this case.

So the only case when ./node_modules/.bin/ is actually worse than npm run-script is when a dependency is installed both as a parent and globally. Hmm, I suppose you're right though.

plato-cambrian

plato-cambrian commented on Sep 10, 2014

@plato-cambrian

I want to both run bower install and update my webdriver during postinstall; with the same package.json usable on both windows and linux.

Is there way that will let both these scripts run without making a new file? Here's what I am doing now:
"postinstall": "node node_modules/bower/bin/bower install; node node_modules/protractor/bin/webdriver-manager update"

The relative paths are because I don't want to assume bower or protractor are installed globally.

maranomynet

maranomynet commented on Oct 20, 2014

@maranomynet

@balupton, this should work:

"prepublish": "./node_modules/.bin/projectz compile && npm test"

The only 'catch' is that the second command (npm test) won't run if the first one fails.

othiym23

othiym23 commented on Oct 21, 2014

@othiym23
Contributor

@maranomynet the ./node_modules/.bin/ part of that path is redundant. As @isaacs says, npm run-script takes care of putting node_modules/.bin on the PATH for you.

maranomynet

maranomynet commented on Oct 21, 2014

@maranomynet

oh, I assumed the semi-colon was part of his problem, because on Windows command-line semicolon delimits parameters, instead of operations.

I stumbled upon this post as I was dealing with two-step package.json scripts not running on Windows, because of this semi-colon issue.

As soon as I changed the semi-colon to & (windows-only replacement for ;) or && (conditional) everything started running smoothly. And && works cross-platform.

(http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/ntcmds_shelloverview.mspx?mfr=true)

32 remaining items

brownieboy

brownieboy commented on Apr 27, 2018

@brownieboy

Essentially, this is boolean logic. So you can use that boolean logic to force the second script to run, even if the first script fails, and yes it works on Windows (where the semi-colon syntax doesn't work). Here's what I originally had in the scripts property of my package.json:

"scripts": {
    testRun: "node ./runtest.js && node ./runreports.js",

In this case, runreports.js would only run if runjest.js completed succesfully - i.e. didn't crash with exit code="1" (or whatever). That's because it's a logical AND. So I changed it to this to a boolean OR, like so:

"scripts": {
    testRun "node ./runtest.js || node ./runreports.js",

Now I had the opposite problem: runreports.js only ran if runtest.js did crash!

The way to force runreports.js to always run is to ensure that the preceding condition always results in a boolean true. In boolean logic something OR true always results in true, i.e:

true || true = true
true || false = true
false || true = true

Applying that logic to my package.json script:

"scripts": {
    "(node ./runtest.js || true) && node ./runreports.js",

By wrapping he first script call with in some brackets and the ORing it with a true, the result of that bracketed section must always be true, no matter what the runtest.js script does. So runreports.js will always run.

It works for me on Windows anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @usergenic@bear@isaacs@balupton@maranomynet

        Issue actions

          `npm run-script` doesn't work on windows when the script contains multiple commands · Issue #4040 · npm/npm