nvm-sh / nvm

Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`nvm install --lts -b` fails in zsh

engnadeau opened this issue · comments

Operating system and version:

nvm debug output:

nvm --version: v0.39.2
$SHELL: /usr/bin/zsh
$SHLVL: 1
whoami: 'nicholas'
${HOME}: /home/nicholas
${NVM_DIR}: '${HOME}/.nvm'
${PATH}: ${HOME}/.local/bin:${HOME}/bin:${NVM_DIR}/versions/node/v18.12.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/wsl/lib:/mnt/c/Windows/system32:/mnt/c/Windows:/mnt/c/Windows/System32/Wbem:/mnt/c/Windows/System32/WindowsPowerShell/v1.0/:/mnt/c/Windows/System32/OpenSSH/:/mnt/c/Program Files/Microsoft VS Code/bin:/mnt/c/Program Files (x86)/NVIDIA Corporation/PhysX/Common:/mnt/c/Program Files/NVIDIA Corporation/NVIDIA NvDLISR:/mnt/c/Program Files/Docker/Docker/resources/bin:/mnt/c/Users/Nicholas/AppData/Local/Microsoft/WindowsApps
$PREFIX: ''
${NPM_CONFIG_PREFIX}: ''
$NVM_NODEJS_ORG_MIRROR: ''
$NVM_IOJS_ORG_MIRROR: ''
shell version: 'zsh 5.8 (x86_64-ubuntu-linux-gnu)'
uname -a: 'Linux 5.15.74.2-microsoft-standard-WSL2 #1 SMP Wed Nov 2 19:50:29 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux'
checksum binary: 'sha256sum'
OS version: Ubuntu 20.04.5 LTS
curl: /usr/bin/curl, curl 7.68.0 (x86_64-pc-linux-gnu) libcurl/7.68.0 OpenSSL/1.1.1f zlib/1.2.11 brotli/1.0.7 libidn2/2.2.0 libpsl/0.21.0 (+libidn2/2.2.0) libssh/0.9.3/openssl/zlib nghttp2/1.40.0 librtmp/2.3
wget: /usr/bin/wget, GNU Wget 1.20.3 built on linux-gnu.
git: /usr/bin/git, git version 2.25.1
ls: cannot access 'grep:': No such file or directory
grep: grep: aliased to grep --color (grep --color), grep (GNU grep) 3.4
awk: /usr/bin/awk, GNU Awk 5.0.1, API: 2.0 (GNU MPFR 4.0.2, GNU MP 6.2.0)
sed: /usr/bin/sed, sed (GNU sed) 4.7
cut: /usr/bin/cut, cut (GNU coreutils) 8.30
basename: /usr/bin/basename, basename (GNU coreutils) 8.30
ls: cannot access 'rm:': No such file or directory
rm: rm: aliased to rm -i (rm -i), rm (GNU coreutils) 8.30
mkdir: /usr/bin/mkdir, mkdir (GNU coreutils) 8.30
xargs: /usr/bin/xargs, xargs (GNU findutils) 4.7.0
nvm current: v18.12.1
which node: ${NVM_DIR}/versions/node/v18.12.1/bin/node
which iojs: iojs not found
which npm: ${NVM_DIR}/versions/node/v18.12.1/bin/npm
npm config get prefix: ${NVM_DIR}/versions/node/v18.12.1
npm root -g: ${NVM_DIR}/versions/node/v18.12.1/lib/node_modules

nvm ls output:

->     v18.12.1
        v19.2.0
default -> lts/* (-> v18.12.1)
iojs -> N/A (default)
unstable -> N/A (default)
node -> stable (-> v19.2.0) (default)
stable -> 19.2 (-> v19.2.0) (default)
lts/* -> lts/hydrogen (-> v18.12.1)
lts/argon -> v4.9.1 (-> N/A)
lts/boron -> v6.17.1 (-> N/A)
lts/carbon -> v8.17.0 (-> N/A)
lts/dubnium -> v10.24.1 (-> N/A)
lts/erbium -> v12.22.12 (-> N/A)
lts/fermium -> v14.21.1 (-> N/A)
lts/gallium -> v16.18.1 (-> N/A)
lts/hydrogen -> v18.12.1

How did you install nvm?

install script in readme

What steps did you perform?

nvm install --lts -b

What happened?

ZSH install fails:

  • awk: cmd. line:1: ^ unterminated string error
  • awk: cmd. line:1: ^ syntax error error
  • mkdir: cannot create directory ... File name too long error
>> nvm install --lts -b                                                                                                                                                                                  

Installing latest LTS version.
Downloading and installing node v18.12.1...
awk: cmd. line:1: { if ("node-v18.12.1-linux-integer 10 readonly '!'=252
awk: cmd. line:1:       ^ unterminated string
awk: cmd. line:1: { if ("node-v18.12.1-linux-integer 10 readonly '!'=252
awk: cmd. line:1:       ^ syntax error
(23) Failed writing body
mkdir: cannot create directory ‘/home/nicholas/.nvm/.cache/bin/node-v18.12.1-linux-integer 10 readonly '!'=252\ninteger 10 readonly '#'=0\ninteger 10 readonly '$'=10\narray readonly '*'=(  )\nreadonly -=569JNRXghikls\n0=nvm_get_arch\ninteger 10 readonly '?'=0\narray readonly @=(  )\nlocal ADDITIONAL_PARAMETERS=''\nlocal ALIAS=''\ninteger 10 readonly ARGC=0\nassociation BG\ntied cdpath CDPATH=''\ninteger 10 COLUMNS=252\nlocal COMMAND=install\nCPUTYPE=x86_64\nlocal DEFAULT_IFS=$' \\t\\n'\nDISPLAY=:0\nEDITOR=code\ninteger 10 EGID=1000\nfloat readonly EPOCHREALTIME\ninteger readonly EPOCHSECONDS\ninteger 10 EUID=1000\nlocal EXIT_CODE=''\nassociation FG\ntied fignore FIGNORE=''\nlocal FLAVOR=node\ntied fpath FPATH=’: File name too long
creating directory /home/nicholas/.nvm/.cache/bin/node-v18.12.1-linux-integer 10 readonly '!'=252
integer 10 readonly '#'=0
integer 10 readonly '$'=10
array readonly '*'=(  )
readonly -=569JNRXghikls
0=nvm_get_arch
integer 10 readonly '?'=0
array readonly @=(  )
local ADDITIONAL_PARAMETERS=''
local ALIAS=''
integer 10 readonly ARGC=0
association BG
tied cdpath CDPATH=''
integer 10 COLUMNS=252
local COMMAND=install
CPUTYPE=x86_64
local DEFAULT_IFS=$' \t\n'
DISPLAY=:0
EDITOR=code
integer 10 EGID=1000
float readonly EPOCHREALTIME
integer readonly EPOCHSECONDS
integer 10 EUID=1000
local EXIT_CODE=''
association FG
tied fignore FIGNORE=''
local FLAVOR=node
tied fpath FPATH=/home/nicholas/.oh-my-zsh/plugins/extract:/home/nicholas/.oh-my-zsh/custom/plugins/zsh-autosuggestions:/home/nicholas/.oh-my-zsh/custom/plugins/alias-tips:/home/nicholas/.oh-my-zsh/plugins/common-aliases:/home/nicholas/.oh-my-zsh/plugins/git:/home/nicholas/.oh-my-zsh/functions:/home/nicholas/.oh-my-zsh/completions:/home/nicholas/.oh-my-zsh/cache/completions:/usr/local/share/zsh/site-functions:/usr/share/zsh/vendor-functions:/usr/share/zsh/vendor-completions:/usr/share/zsh/functions/Calendar:/usr/share/zsh/functions/Chpwd:/usr/share/zsh/functions/Completion:/usr/share/zsh/functions/Completion/AIX:/usr/share/zsh/functions/Completion/BSD:/usr/share/zsh/functions/Completion/Base:/usr/share/zsh/functions/Completion/Cygwin:/usr/share/zsh/functions/Completion/Darwin:/usr/share/zsh/functions/Completion/Debian:/usr/share/zsh/functions/Completion/Linux:/usr/share/zsh/functions/Completion/Mandriva:/usr/share/zsh/functions/Completion/Redhat:/usr/share/zsh/functions/Completion/Solaris:/usr/share/zsh/functions/Completion/Unix:/usr/share/zsh/functions/Completion/X:/usr/share/zsh/functions/Completion/Zsh:/usr/share/zsh/functions/Completion/openSUSE:/usr/share/zsh/functions/Exceptions:/usr/share/zsh/functions/MIME:/usr/share/zsh/functions/Math:/usr/share/zsh/functions/Misc:/usr/share/zsh/functions/Newuser:/usr/share/zsh/functions/Prompts:/usr/share/zsh/functions/TCP:/usr/share/zsh/functions/VCS_Info:/usr/share/zsh/functions/VCS_Info/Backends:/usr/share/zsh/functions/Zftp:/usr/share/zsh/functions/Zle
integer 10 FUNCNEST=500
association FX
integer 10 GID=1000
HISTCHARS='!^#'
integer 10 readonly HISTCMD=193
HISTFILE=/home/nicholas/.zsh_history
integer 10 HISTSIZE=50000
HIST_STAMPS=yyyy-mm-dd
HOME=/home/nicholas
HOST=blue
HOSTTYPE=x86_64
local HOST_ARCH=x86_64
IFS=$' \t\n'
KEYBOARD_HACK=''
integer KEYTIMEOUT=40
local KIND=binary
LANG=C.UTF-8
LESS=-R
integer 10 readonly LINENO=32
integer 10 LINES=67
integer LISTMAX=100
integer LOGCHECK=60
LOGNAME=nicholas
LSCOLORS=Gxfxcxdxbxegedabagacad

What did you expect to happen?

Successful install.

Switching to BASH works:

>> nvm install --lts -b
Installing latest LTS version.
Downloading and installing node v18.12.1...
Downloading https://nodejs.org/dist/v18.12.1/node-v18.12.1-linux-x64.tar.xz...
##################################################################################################################################################################################################################################################### 100.0%
Computing checksum with sha256sum
Checksums matched!
Now using node v18.12.1 (npm v8.19.2)
Creating default alias: default -> lts/* (-> v18.12.1)

Usually I'd expect this error to come from using an older copy of nvm. If you're sure that nvm --version prints out the same thing in both shells, then something else is going on.

However, this might be a duplicate of #2914, which is fixed in #2915 and will be in the next release.

@engnadeau Are you using oh-my-zsh?

I had the same issue and figured out the root cause. The issue happens due to the global alias in a plugin named common-aliases

Incidentally, a local variable L is defined in the function nvm_get_arch . On defining the local variable, L outputs the $PATH and thereafter the whole script goes berserk.

I verified locally by changing the variable name to something else and it works fine.

@ljharb oh-my-zsh is a commonly used zsh configuration tool and the plugin common-aliases from oh-my-zsh is also commonly used. Do you think it is better to fix the issue? It is just about renaming a variable so seems fairly simple and straightforward. If you are okay, I can raise a PR for it.

For the future, we should probably avoid naming local variables with a single letter to avoid these collisions.

@jignaasu if there's a way to fix it, absolutely, but it seems like a better fix might be to suggest common-aliases stop using single letter aliases?

It's not sustainable to just change the variable names every time it's an issue.

The local L should mean it shadows the global one, no?

@ljharb

I am not a shell script expert here. Here is what I think. L is an alias and is already available when the terminal first opens the session and .zshrc or .zsh_profile is sourced. And overriding or shadowing happens only for other variables, not aliases or functions.

I use single-letter aliases quite commonly. For ex: l for ls and ll for ls -ltr, T for the piped tail and t for the tail. This is just me. In this case, my preference is to fix the variable name instead of the alias. The other reason is changing the aliases has a bigger impact on the users compared to the variable name change where the impact will not be felt by the users.

Shell scripting is tricky and you know it better than me. Maybe we could use Coding guidelines and the usual PR reviews to avoid similar issues in future. I am not aware of any friendly linters we could integrate into the workflow, otherwise, that could also help.

I have created the PR. As this is a variable name change, no extra tests would be required.

That is my 2 cents and thanks for building and maintaining such a wonderful tool. This has made my life so much easier.

@jignaasu , interesting. Yes I'm using OMZ and have been for years with nvm. Weirdly, yesterday, everything seems to work well on another equivalent system (but I didn't check versions).

I looked into this because I have been researching "local" recently. The global aliasing is very (scarily) general in zsh!

Every eligible word in the shell input is checked to see if there is an alias defined for it. If so, it is replaced by the text of the alias if it is in command position (if it could be the first word of a simple command), or if the alias is global.

https://zsh.sourceforge.io/Doc/Release/Shell-Grammar.html#Aliasing

A potential work-around is to avoid the "word" from matching the global alias, like:

local "L"
# or
local \L

This can theoretically still fail if the "word" matches a global alias and gets replaced, but unlikely!

$ alias -g \\L="yes way"
$ echo \L
yes way

Another work-around is to assign the value so the "word" is not the variable name, but this may have its own tradeoffs for portability:

local L=""

Yeah, local L="" will break on ksh, so that's not an option. I'm totally fine modifying nvm to do one of those two workarounds to make it less likely.

Another alternative is if there's a zsh option that can fix this very dangerous and broken behavior - in which case nvm could set it for its own run.

I found there is setopt no_aliases. (Are aliases ever wanted? Not in this context?)

I would expect not. Basically, adding nvm_is_zsh && setopt local_options no_aliases inside the nvm function should theoretically fix it. If you can verify that, a PR would be great!

@jignaasu Do you want to try this approach instead of the variable rename in your PR?

The local_options makes the change revert when the enclosing function exits, so this can be called early in the nvm() function.

nvm_is_zsh && setopt local_options no_aliases

I had a casual go at using setopt local_options no_aliases in the nvm script, and I completely failed to make it work. I didn't work out why! So passing along a heads-up that might not be as simple as one would hope, and the less general but easier approach to change the local variable usage would be an easier fix for the L problem in particular.