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
posted @ 2025-07-24 15:16  Ranger-dev  阅读(143)  评论(0)    收藏  举报