使用root用户npm install

复现

  • 使用root用户进行npm install操作
  • 然后执行npm run postinstall:"bower install"

报错:

npm WARN lifecycle ****~postinstall: cannot run in wd  (wd=/app)
  • 首先wd是当前的工作目录
  • 说明npm run postinstall不能在当前的目录下运行

我的执行过程:使用npm install 安装bower, 然后在postscript中使用bower install(使用bower安装bower中的依赖)

使用Docker启动一个node container 作为运行环境。

// Dockerfile
FROM node:8.12.0
RUN mkdir /app
WORKDIR /app
COPY . .
ENTRYPOINT ["/bin/bash", "-c"]

// docker-compose.yml
version: '2'
services:
  dev:
    build: .
    volumes:
      - ~/.ssh:/home/node/.ssh:ro

// package.json

"scripts": {
    "postinstall": "bower install --allow-root"
  }
  
// auto/test

docker-compose run --rm dev "npm ci && ${@-bash}"

解决过程

  • 直接运行auto/auto/test报错

npm WARN lifecycle ***~postinstall: cannot run in wd *** bower install --allow-root (wd=/app)

根据以上错误翻译:npm warn 生命周期script postinstall: 不能在当前的work dir中运行bower install --allow-root

  • 是否是因为postinstall中执行了一些不能运行的command,于是尝试替换
// package.json

"scripts": {
    "postinstall": "whoami"
  }

发现报错一样,说明:
不论postinstall里执行任何命令都会导致以上的错误

原因:

如果使用root调用npm的时候,npm会将uid修改成user account或者是在npm的config文件中找到user config然后用此时的user修改uid,如果这些值都没有,user的默认值是nobody.你可以通过设置--unsafe-perm=true使用root权限运行npm script命令.

  • 是否是所有的npm script都不能执行呢?

试验:移除postinstall脚本,然后定义新的script bowerInstall: bower install --allow-root, 在npm ci 之后执行npm ci && npm run bowerInstall

结果: bower install成功

结论: 当你使用root用户执行npm的指令,会导致npm相关lifecycle方法(之后npm lifecycle中的方法,比如postinstall)的运行出现以上的问题

当你使用root调用npm,只有在running package lifecycle script,npm才会将uid设置成nobody。对于其他的script,npm不会强制设置你的uid

npm script
中文版

npm 中的每一个script都会运行三个独立的脚本。prescript、script本身以及postscript。正如它们的名称所暗示的,这两个附加脚本在主脚本之前和之后运行。pre以及post脚本通常被用来setup以及clean up工作。prepost in the same scripts object as before.

  • root 权限执行npm会有什么问题?

如果使用root执行npm install, 当你安装postinstall一个package,npm还会是用当前这个权限去运行这个package中的postinstall, 因此如果脚本中写了一些不利于操作系统的脚本,会直接broke你的电脑。

当你使用root执行npm install的时候,npm为了安全性考虑,将你的uid设置成nobody, nobody权限非常的低,因此postinstall里写的很多脚本nobody都没有权限执行,因此不会造成安全问题
Issue link

  • 那么如果必须使用root用户调用npm,如何解决上面的问题呢?

虽然npm可以自动的帮助你在执行lifecycle script的时候降低权限到nobody, 但是如果你自己希望npm不要强制修改你的uid,你可以使用npm install --unsafe-perm

强制npm运行所有lifecycle script的时候都使用root,不要自动帮你改变权限。但是请注意这是一项很危险的动作。

  • 那么有没有什么安全的fix方法呢?

那么你可以选择不要使用root用户调用npm的各种执行,在Docker image中使用USER node,将用户从root改成node。

或者不要把你想要执行的脚本写在postinstall(lifecycle)脚本中,而是写在其他npm script

bower install --allow-root: 这条指令允许你运行使用root权限运行bower install,但是事实上,根本没有必要使用root权限运行, 但是如果你还是强行想使用root权限那么可以使用all-root

你可能感兴趣的:(使用root用户npm install)