NPM在最新的Ubuntu(18.04)安装中是错误的版本。

正常安装的步骤是先运行sudo apt install nodejs来安装Node.js,然后再运行sudo apt install npm来安装Node Package Manager。然而,在这样做之后,npm -v显示的版本是3.5.2。要进行正常的升级,我会运行sudo npm install -g npm,这将更新到最新版本(在撰写本文时,最新版本是6.0.1)。
当我运行which npm时,得到的路径是/usr/local/bin/npm,然而apt/usr/bin/npm处创建了一个符号链接。如果我运行sudo apt purge npm来移除npm,它仍然会保留位于/usr/local/bin/npm的npm版本,但是npm -v会显示-bash: /usr/bin/npm: No such file or directory
许多文章都建议使用PPA来安装nodejs,但我认为应该有一种通过apt来完成的本地方式。
DigitalOcean关于正常安装和通过PPA安装的说明:https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-18-04 TecAdmin关于通过PPA安装的说明:https://tecadmin.net/install-latest-nodejs-npm-on-ubuntu/
4个回答

TLDR: 这个问题是由于Bash缓存了路径npm命令引起的,可以通过hash -d npm来解决。除非你想要处理apt purge,否则你甚至不需要这样做。

解释

以下是我在Ubuntu上获取新的npm版本的步骤。首先,按照OP描述进行安装:

$ sudo apt-get install npm
(...apt installation of npm was successful...)
$ npm -v
3.5.2
$ command -v npm
/usr/bin/npm
$ sudo npm install -g npm
(...npm installation of npm was successful...so far, so good)

您可以看到新版本已在 /usr/local/bin/npm 上正常运行,但不幸的是 Bash 缓存仍然有 /usr/bin/npm

$ /usr/local/bin/npm -v
6.4.1
$ npm -v
3.5.2
$ command -v npm
/usr/bin/npm
$ type npm
npm is hashed (/usr/bin/npm)

要解决这个问题,需要从Bash缓存中清除它(在所有打开的终端中执行此操作)。
$ hash -d npm

现在新版本按预期工作:
$ npm -v
6.4.1
$ command -v npm
/usr/local/bin/npm

1我实际上更喜欢这个答案,比起我的答案来说。 - Blairg23
这解决了我的问题。非常感谢你。解释得很好。唯一不清楚的是为什么清除bash缓存会修复问题的确切原因。删除/usr/bin/npm中存储的npm是否更好?如果两个版本都保留,为什么在清除bash缓存后会选择正确的版本? - temporary_user_name
@temporary_user_name 你可以使用 echo $PATH 命令来查看路径,这将显示当 Bash 在路径中查找时,如果两个目标都存在,那么优先选择 /usr/local/bin 而不是 /usr/bin。只有当 Bash 不记得之前找到目标的位置时,它才会在路径中查找。 - krubo
救命稻草!谢谢。我在尝试进行生产构建的过程中卡住了好几个小时。这解决了我的问题。 - RyanNerd
我只需要运行hash -d npm,然后一切都正常了!太感谢了! - Tom Bird

我找到的方法是通过sudo apt purge npm清除npm,然后仅通过ln -s /usr/local/bin/npm /usr/bin/npm重新创建到全局安装的符号链接。在那之后,修复了npm -v,预期返回6.0.1

2在Android 6.0.1上通过UserLAnd运行Ubuntu 18.04。谢谢! :) - l3l_aze
1楼主,你应该把这个标记为答案。 - Robert Munn
有趣的是,对我来说情况有些不同。我在/usr/bin/npm中有更新的版本,所以我选择了相反的方法,使用ln -s /usr/bin/npm /usr/local/bin/npm。虽然有点奇怪,但你的回答帮助我找到了解决错误版本问题的方法。 - LordAnomander

为了控制已安装的npm版本,我总是使用nvm(Node版本控制)。您可以按照这里的说明进行安装:https://github.com/creationix/nvm 然后通过以下命令在您的计算机上安装最新的npm:

很不幸,其他答案对我都没有起作用。以下是我在Ubuntu 18.04上使其正常工作的方法。
简而言之,按照以下步骤操作:
sudo ln -s /usr/local/lib/nodejs/node-v10.16.3-linux-x64/bin/npm /usr/local/bin

解释:

我通过默认的软件仓库安装了npm,这将npm可执行文件安装到了/usr/bin/npm。

当我使用sudo npm install -g npm进行更新时,一个新的可执行文件被安装到了/usr/local/lib/nodejs/node-v10.16.3-linux-x64/bin/npm。

为了让非root用户能够使用npm,你可以将以下内容放入该用户的~/.profile文件中(我认为这就是在不使用sudo的情况下执行npm install -g npm时所做的操作):

# Nodejs
VERSION=v10.16.3
DISTRO=linux-x64
export PATH=/usr/local/lib/nodejs/node-$VERSION-$DISTRO/bin:$PATH

然而,由于此目录不在root用户的$PATH环境变量中,因此它对于sudo命令无效。
$ sudo npm -v
3.5.2

如你所见,sudo 并不使用最新的 npm,而是使用通过软件包管理器安装的版本。
在 Ubuntu 上,root 用户的默认 $PATH 是:
root ~# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin

由于npm的包管理器版本已经安装在/usr/bin目录下,我们可以创建一个符号链接来将最新版本放在较高优先级的$PATH链中,比如/usr/local/bin。这样,即使包管理器的版本有更新,也不会被覆盖掉。
$ sudo ln -s /usr/local/lib/nodejs/node-v10.16.3-linux-x64/bin/npm /usr/local/bin
$ sudo npm -v                                                                                                                                                                                                    
6.14.1          

请注意,我假设如果节点也被更新了,那么这个路径也会变化,所以您将需要使用更新后的路径重复此步骤。
$ sudo rm /usr/local/lib/nodejs/node-v10.16.3-linux-x64/bin/npm
$ sudo ln -s /usr/local/lib/nodejs/{NEW_NODE_VERSION}-linux-x64/bin/npm /usr/local/bin