Problem Description

When installing npm packages on a Ubuntu server from package.json with sudo npm install, many dependencies are not installed. Running npm install locally installs everything as expected. The problem appears to be caused by permissions issues inside the node_modules/ directory. How can I ensure that npm is able to install all dependencies recursively?

Background

I'm deploying a NodeJS application to a Ubuntu webserver. All of my packages are defined in my package.json file, something like this:

{
  "name": "MyApp",
  "engines": {
    "node": "0.10.x",
    "npm": "1.2.x"
  },
  "dependencies": {
    "express": "~3.5.1",
    "jade": "~1.3.1",
    "mongoose": "3.8.8",
    ...
  }
}

When I run npm install locally, I'm able to immediately spin up the node server with node server.js without any problems (after running all tasks/pre-compilation jobs).

Running npm install on the server fails, due to EACCES errors like this one:

npm ERR! error rolling back Error: EACCES, unlink '/myapp/staging/node_modules/.bin/express'
npm ERR! error rolling back  express@3.5.1 { [Error: EACCES, unlink '/myapp/staging/node_modules/.bin/express']
npm ERR! error rolling back   errno: 3,
npm ERR! error rolling back   code: 'EACCES',
npm ERR! error rolling back   path: '/myapp/staging/node_modules/.bin/express' }
npm ERR! Error: EACCES, unlink '/myapp/staging/node_modules/.bin/express'
npm ERR!  { [Error: EACCES, unlink '/myapp/staging/node_modules/.bin/express']
npm ERR!   errno: 3,
npm ERR!   code: 'EACCES',
npm ERR!   path: '/myapp/staging/node_modules/.bin/express' }
npm ERR! 
npm ERR! Please try running this command again as root/Administrator.

When I run sudo npm install on the server (after removing node_modules/ and running sudo npm cache clean), npm fetches all the top-level packages:

npm http GET https://registry.npmjs.org/jade
npm http GET https://registry.npmjs.org/mongoose
npm http GET https://registry.npmjs.org/express
...

but doesn't use sudo when installing the dependencies, so they quietly fail without any error message. The result is that the server fails to start:

$ node server.js

module.js:340
  throw err;
      ^
Error: Cannot find module './lib/express'
    at Function.Module._resolveFilename (module.js:338:15)
    at Function.Module._load (module.js:280:25)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (/myapp/node_modules/express/index.js:4:5)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)

and the solution is to install each top-level package individually, which then properly fetches and installs the recursive dependencies:

$ sudo npm install express
...

However that defeats the entire purpose of package.json, not to mention requires heavy maintenance for every new deployment.

有帮助吗?

解决方案

Don't use sudo. Your application's dependencies do not need to be installed system-wide. So install your application code on the server in some normal directory, then cd into that directory and run npm install as your regular user (not root) without sudo. npm will put all of your app's dependencies (fully recursive) into a node_modules subdirectory and you should be good to go. Not sure exactly why things are failing for you with sudo, but it's just never a good idea. Keep in mind that's downloading scripts from the Internet and running them as root as npm packages can have install scripts. Lots of extra risk there when running as root.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top