node多版本管理 fnm使用
安装
win11
winget install Schniz.fnm
# 安装执行命令 否则终端找不到node npm 也不能使用fnm use
fnm env --use-on-cd | Out-String | Invoke-Expression
# 配置node下载加速 powersell 或者自己加环境变量
[Environment]::SetEnvironmentVariable('FNM_NODE_DIST_MIRROR', 'https://npmmirror.com/mirrors/node', 'User');
使用
#查看可安装的 Node.js 版本。
fnm list-remote fnm ls-remote
#查看目前已经安装了的node版本:fnm ls
#安装node 具体版本
fnm install v16.18.1
#安装最新LTS版本
fnm install --lts
#安装的版本最新的大版本
fnm install 24
#卸载
fnm unstall 24
#默认使用
fnm use 24
进入项目自动切换 node 版本
配置好环境变量之后,在项目根目录创建 .node-version 或者 .nvmrc 文件,进入项目目录后即可自动切换设定好的 node 版本。
22.17.1
webstrom 自动识别 node 路径
## 终端执行命令
[Environment]::SetEnvironmentVariable('Path', [Environment]::GetEnvironmentVariable('Path', 'User') + ";$env:APPDATA\fnm\aliases\default", 'User')
Linux安装
使用下面的安装脚本 安装执行命令
主要使用gitea actrunner ci/cd的 把actrunner 进程杀掉重启 否则不识别fnm
gitea actrunner的执行用户取决于谁把它启动的 一般和root一样
## 安装
~/fnminstall.sh -d /usr/local/fnm
## /root/.bashrc新增下面的东西
FNM_PATH="/usr/local/fnm"
if [ -d "$FNM_PATH" ]; then
export PATH="$FNM_PATH:$PATH"
eval "`fnm env`"
fi
## 刷新
source ~/.bashrc
## 新增 /etc/profile.d/fnm.sh 写入以下内容
cat >/etc/profile.d/fnm.sh <<'EOF'
#!/bin/sh
export FNM_DIR=/usr/local/fnm
export PATH="/usr/local/fnm:$PATH"
eval "$(fnm env --use-on-cd)"
EOF
chmod 644 /etc/profile.d/fnm.sh
source /etc/profile.d/fnm.sh
## 处理非root用户报错Can't create the symlink for multishells at "/run/user/0/fnm_multishells/35677_1757075243053".
## Maybe there are some issues with permissions for the directory? Permission denied报错
## 使用root 命令提前安装node 因为其他用户会出现没有权限的情况
## 查看其他用户id 我的git是105
id -u
## 安装目录
mkdir -p /run/user/105
chown git:git /run/user/105
chmod 700 /run/user/105
## 切换到其他用户 CI/CD用户
su git
cd ~/
## 在~/.bashrc新增下面的东西
export XDG_RUNTIME_DIR=/run/user/$(id -u)
FNM_PATH="/usr/local/fnm"
if [ -d "$FNM_PATH" ]; then
export PATH="$FNM_PATH:$PATH"
eval "`fnm env`"
fi
## 生效
source ~/.bashrc
## 执行
eval "$(fnm env --use-on-cd)"
安装脚本 fnminstall.sh
#!/bin/bash
set -e
RELEASE="latest"
OS="$(uname -s)"
case "${OS}" in
MINGW* | Win*) OS="Windows" ;;
esac
if [ -d "$HOME/.fnm" ]; then
INSTALL_DIR="$HOME/.fnm"
elif [ -n "$XDG_DATA_HOME" ]; then
INSTALL_DIR="$XDG_DATA_HOME/fnm"
elif [ "$OS" = "Darwin" ]; then
INSTALL_DIR="$HOME/Library/Application Support/fnm"
else
INSTALL_DIR="$HOME/.local/share/fnm"
fi
# Parse Flags
parse_args() {
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
-d | --install-dir)
INSTALL_DIR="$2"
shift # past argument
shift # past value
;;
-s | --skip-shell)
SKIP_SHELL="true"
shift # past argument
;;
--force-install | --force-no-brew)
echo "\`--force-install\`: I hope you know what you're doing." >&2
FORCE_INSTALL="true"
shift
;;
-r | --release)
RELEASE="$2"
shift # past release argument
shift # past release value
;;
*)
echo "Unrecognized argument $key"
exit 1
;;
esac
done
}
set_filename() {
if [ "$OS" = "Linux" ]; then
# Based on https://stackoverflow.com/a/45125525
case "$(uname -m)" in
arm | armv7*)
FILENAME="fnm-arm32"
;;
aarch* | armv8*)
FILENAME="fnm-arm64"
;;
*)
FILENAME="fnm-linux"
esac
elif [ "$OS" = "Darwin" ] && [ "$FORCE_INSTALL" = "true" ]; then
FILENAME="fnm-macos"
USE_HOMEBREW="false"
echo "Downloading the latest fnm binary from GitHub..."
echo " Pro tip: it's easier to use Homebrew for managing fnm in macOS."
echo " Remove the \`--force-no-brew\` so it will be easy to upgrade."
elif [ "$OS" = "Darwin" ]; then
USE_HOMEBREW="true"
echo "Downloading fnm using Homebrew..."
elif [ "$OS" = "Windows" ] ; then
FILENAME="fnm-windows"
echo "Downloading the latest fnm binary from GitHub..."
else
echo "OS $OS is not supported."
echo "If you think that's a bug - please file an issue to https://ghfast.top/https://github.com/Schniz/fnm/issues"
exit 1
fi
}
download_fnm() {
if [ "$USE_HOMEBREW" = "true" ]; then
brew install fnm
INSTALL_DIR="$(brew --prefix fnm)/bin"
else
if [ "$RELEASE" = "latest" ]; then
URL="https://ghfast.top/https://github.com/Schniz/fnm/releases/latest/download/$FILENAME.zip"
else
URL="https://ghfast.top/https://github.com/Schniz/fnm/releases/download/$RELEASE/$FILENAME.zip"
fi
DOWNLOAD_DIR=$(mktemp -d)
echo "Downloading $URL..."
mkdir -p "$INSTALL_DIR" &>/dev/null
if ! curl --progress-bar --fail -L "$URL" -o "$DOWNLOAD_DIR/$FILENAME.zip"; then
echo "Download failed. Check that the release/filename are correct."
exit 1
fi
unzip -q "$DOWNLOAD_DIR/$FILENAME.zip" -d "$DOWNLOAD_DIR"
if [ -f "$DOWNLOAD_DIR/fnm" ]; then
mv "$DOWNLOAD_DIR/fnm" "$INSTALL_DIR/fnm"
else
mv "$DOWNLOAD_DIR/$FILENAME/fnm" "$INSTALL_DIR/fnm"
fi
chmod u+x "$INSTALL_DIR/fnm"
fi
}
check_dependencies() {
echo "Checking dependencies for the installation script..."
echo -n "Checking availability of curl... "
if hash curl 2>/dev/null; then
echo "OK!"
else
echo "Missing!"
SHOULD_EXIT="true"
fi
echo -n "Checking availability of unzip... "
if hash unzip 2>/dev/null; then
echo "OK!"
else
echo "Missing!"
SHOULD_EXIT="true"
fi
if [ "$USE_HOMEBREW" = "true" ]; then
echo -n "Checking availability of Homebrew (brew)... "
if hash brew 2>/dev/null; then
echo "OK!"
else
echo "Missing!"
SHOULD_EXIT="true"
fi
fi
if [ "$SHOULD_EXIT" = "true" ]; then
echo "Not installing fnm due to missing dependencies."
exit 1
fi
}
ensure_containing_dir_exists() {
local CONTAINING_DIR
CONTAINING_DIR="$(dirname "$1")"
if [ ! -d "$CONTAINING_DIR" ]; then
echo " >> Creating directory $CONTAINING_DIR"
mkdir -p "$CONTAINING_DIR"
fi
}
setup_shell() {
CURRENT_SHELL="$(basename "$SHELL")"
if [ "$CURRENT_SHELL" = "zsh" ]; then
CONF_FILE=${ZDOTDIR:-$HOME}/.zshrc
ensure_containing_dir_exists "$CONF_FILE"
echo "Installing for Zsh. Appending the following to $CONF_FILE:"
{
echo ''
echo '# fnm'
echo 'FNM_PATH="'"$INSTALL_DIR"'"'
echo 'if [ -d "$FNM_PATH" ]; then'
if [ "$USE_HOMEBREW" != "true" ]; then
echo ' export PATH="$FNM_PATH:$PATH"'
fi
echo ' eval "`fnm env`"'
echo 'fi'
} | tee -a "$CONF_FILE"
elif [ "$CURRENT_SHELL" = "fish" ]; then
CONF_FILE=$HOME/.config/fish/conf.d/fnm.fish
ensure_containing_dir_exists "$CONF_FILE"
echo "Installing for Fish. Appending the following to $CONF_FILE:"
{
echo ''
echo '# fnm'
echo 'set FNM_PATH "'"$INSTALL_DIR"'"'
echo 'if [ -d "$FNM_PATH" ]'
if [ "$USE_HOMEBREW" != "true" ]; then
echo ' set PATH "$FNM_PATH" $PATH'
fi
echo ' fnm env | source'
echo 'end'
} | tee -a "$CONF_FILE"
elif [ "$CURRENT_SHELL" = "bash" ]; then
if [ "$OS" = "Darwin" ]; then
CONF_FILE=$HOME/.profile
else
CONF_FILE=$HOME/.bashrc
fi
ensure_containing_dir_exists "$CONF_FILE"
echo "Installing for Bash. Appending the following to $CONF_FILE:"
{
echo ''
echo '# fnm'
echo 'FNM_PATH="'"$INSTALL_DIR"'"'
echo 'if [ -d "$FNM_PATH" ]; then'
if [ "$USE_HOMEBREW" != "true" ]; then
echo ' export PATH="$FNM_PATH:$PATH"'
fi
echo ' eval "`fnm env`"'
echo 'fi'
} | tee -a "$CONF_FILE"
else
echo "Could not infer shell type. Please set up manually."
exit 1
fi
echo ""
echo "In order to apply the changes, open a new terminal or run the following command:"
echo ""
echo " source $CONF_FILE"
}
parse_args "$@"
set_filename
check_dependencies
download_fnm
if [ "$SKIP_SHELL" != "true" ]; then
setup_shell
fi