解决 Linux 下 JetBrains 全家桶无法识别使用 Node 版本管理器安装的 Node 的问题
本文将介绍如何解决 Linux 下,JetBrains 全家桶无法识别使用 Node 版本管理器安装的 Node 的问题。
现有问题
通常来说,我们会使用如 nvm
, fnm
, volta
等 Node 版本管理器来安装 Node。安装后,我们可以正常地在终端中使用 Node 版本管理器所安装的 Node。
但目前(2022年)为止,JetBrains 全家桶只兼容 nvm
。
nvm
有许多替代品,实际上开发者可能并不使用 nvm
而是使用如 fnm
等替代品。可 JetBrains 全家桶并不兼容它们,不能识别它们所安装的 Node。
分析问题
这里,让我们简单分析一下 nvm
的安装脚本,了解 nvm
是如何运作的。
当我们执行官方的安装脚本后,脚本首先将执行 nvm_do_install()
函数。我们需要关注的主要是这一部分:
local NVM_PROFILE
NVM_PROFILE="$(nvm_detect_profile)"
local PROFILE_INSTALL_DIR
PROFILE_INSTALL_DIR="$(nvm_install_dir | command sed "s:^$HOME:\$HOME:")"
SOURCE_STR="\\nexport NVM_DIR=\"${PROFILE_INSTALL_DIR}\"\\n[ -s \"\$NVM_DIR/nvm.sh\" ] && \\. \"\$NVM_DIR/nvm.sh\" # This loads nvm\\n"
COMPLETION_STR='[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion\n'
BASH_OR_ZSH=false
if [ -z "${NVM_PROFILE-}" ] ; then
local TRIED_PROFILE
if [ -n "${PROFILE}" ]; then
TRIED_PROFILE="${NVM_PROFILE} (as defined in \$PROFILE), "
fi
nvm_echo "=> Profile not found. Tried ${TRIED_PROFILE-}~/.bashrc, ~/.bash_profile, ~/.zshrc, and ~/.profile."
nvm_echo "=> Create one of them and run this script again"
nvm_echo " OR"
nvm_echo "=> Append the following lines to the correct file yourself:"
command printf "${SOURCE_STR}"
nvm_echo
else
if nvm_profile_is_bash_or_zsh "${NVM_PROFILE-}"; then
BASH_OR_ZSH=true
fi
if ! command grep -qc '/nvm.sh' "$NVM_PROFILE"; then
nvm_echo "=> Appending nvm source string to $NVM_PROFILE"
command printf "${SOURCE_STR}" >> "$NVM_PROFILE"
else
nvm_echo "=> nvm source string already in ${NVM_PROFILE}"
fi
if ${BASH_OR_ZSH} && ! command grep -qc '$NVM_DIR/bash_completion' "$NVM_PROFILE"; then
nvm_echo "=> Appending bash_completion source string to $NVM_PROFILE"
command printf "$COMPLETION_STR" >> "$NVM_PROFILE"
else
nvm_echo "=> bash_completion source string already in ${NVM_PROFILE}"
fi
fi
if ${BASH_OR_ZSH} && [ -z "${NVM_PROFILE-}" ] ; then
nvm_echo "=> Please also append the following lines to the if you are using bash/zsh shell:"
command printf "${COMPLETION_STR}"
fi
安装脚本将检测 ~/.bashrc
,~/.zshrc
,~/.profile
等文件是否存在。如果存在,就向其写入如下内容:
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
根据以上内容,当我们启动终端后,将自动执行 $HOME/.nvm/nvm.sh
。这个脚本的主要工作之一就是向环境变量中写入其所安装并被用户启用的 Node 的路径。
类似的,fnm
的安装脚本也做了如 nvm
般的工作。它写入如下内容:
export PATH=/home/kubuntu/.fnm:$PATH
eval "`fnm env`"
显然,JetBrains 全家桶启动时并没有执行以上命令。
解决方案
了解问题所在后,解决它其实并不复杂。我们只需要让 JetBrains 全家桶(如 WebStorm)启动时,能够自动执行 ~/.bashrc
,~/.zshrc
,~/.profile
等文件即可。
在 KDE 桌面环境下,点击图标后所执行的动作由其中的 Exec
字段所定义。
Exec=env BAMF_DESKTOP_FILE_HINT=/var/lib/snapd/desktop/applications/webstorm_webstorm.desktop /snap/bin/webstorm %f
在不同环境、不同安装方式下,你所看到的 Exec
字段内容可能与此处的大不相同,但这并不要紧。
为修复 JetBrains 全家桶无法识别使用 Node 版本管理器安装的 Node 的问题,我们只需要在原有命令前加上 bash -ic
或 zsh -ic
即可。例如:
Exec=bash -ic "env BAMF_DESKTOP_FILE_HINT=/var/lib/snapd/desktop/applications/webstorm_webstorm.desktop /snap/bin/webstorm %f"
这是使得我们以 Interactive Shell
的形式启动 Bash 并执行后续启动 JetBrains 全家桶的命令。
Zsh 的运作机制与 Bash 类似。
When an interactive shell that is not a login shell is started, bash reads and executes commands from ~/.bashrc, if that file exists. This may be inhibited by using the –norc option. The –rcfile file option will force bash to read and execute commands from file instead of ~/.bashrc.
当以 Interactive Shell
启动 Bash 时,Bash 将自动读取并执行 ~/.bashrc
,这样 Node 版本管理器所想要设置的环境变量就得以传入 JetBrains 全家桶的运行环境。