Bash script not handling npm commands correctly

19,797

Solution 1

Per Olorin's suggestion to look at the node error, I explored that more. Despite the fact that node -v for someuser was returning v9.4.0 and the locate command not finding any v8 versions installed for any user, and having re-installed node, i was still getting the same error. The following command works. Note the source ~/.nvm/nvm.sh;

#!/bin/sh  
/bin/su tstapps -c "
cd /opt/app1/;
git remote update;
git pull origin dev;
cd /opt/app1/client/;
source ~/.nvm/nvm.sh;
npm run build;

At one point I had nvm use v9.5.0 and then tested it still works without it. Next I removed source ~/.nvm/nvm.sh; and it was broken again. So apparently the nvm isn't available in shell-scripts env without sourcing it and the npm run build needs to see nvm.

Strange issue and looks like some users ran into similar issues with using nvm resources in bash based on this thread. Still not sure where it was getting the v8 from. Unless it was getting v8 from the include/node directory of v9 installations. Example:

/home/someuser/.nvm/versions/node/v9.5.0/include/node/v8-platform.h
/home/someuser/.nvm/versions/node/v9.5.0/include/node/v8-profiler.h
/home/someuser/.nvm/versions/node/v9.5.0/include/node/v8-testing.h
/home/someuser/.nvm/versions/node/v9.5.0/include/node/v8-util.h
/home/someuser/.nvm/versions/node/v9.5.0/include/node/v8-value-serializer-version.h
/home/someuser/.nvm/versions/node/v9.5.0/include/node/v8-version-string.h
/home/someuser/.nvm/versions/node/v9.5.0/include/node/v8-version.h
/home/someuser/.nvm/versions/node/v9.5.0/include/node/v8.h
/home/someuser/.nvm/versions/node/v9.5.0/include/node/v8config.h

Solution 2

env -i cleans the environment, and that includes the PATH variable, which is used to look up commands if you don't give the full path. So, with env -i, you need to specify the full path to commands being invoked. With npm, what probably happens is that npm itself is a script which has #! /usr/bin/env node as the shebang, so the lookup for the node command fails.

If you need to clean the environment, try either of:

  • sudo -iu someuser sh -c "...."
  • su someuser - -c "...." (both these commands start login shells with some cleaning of the environment)
  • or, with env, retain some environment variables, like the Ubuntu service command does:

    $ grep env $(command -v service) -m1
    out=$(env -i LANG="$LANG" LANGUAGE="$LANGUAGE" LC_CTYPE="$LC_CTYPE" LC_NUMERIC="$LC_NUMERIC" LC_TIME="$LC_TIME" LC_COLLATE="$LC_COLLATE" LC_MONETARY="$LC_MONETARY" LC_MESSAGES="$LC_MESSAGES" LC_PAPER="$LC_PAPER" LC_NAME="$LC_NAME" LC_ADDRESS="$LC_ADDRESS" LC_TELEPHONE="$LC_TELEPHONE" LC_MEASUREMENT="$LC_MEASUREMENT" LC_IDENTIFICATION="$LC_IDENTIFICATION" LC_ALL="$LC_ALL" PATH="$PATH" TERM="$TERM" "$SERVICEDIR/$SERVICE" status 2>&1)
    

    You probably don't need all those, but keep $PATH, $TERM, and maybe set LC_ALL=C.

Share:
19,797

Related videos on Youtube

jtlindsey
Author by

jtlindsey

Hello, My name is Travis. Im on the web at jtlindsey.com

Updated on September 18, 2022

Comments

  • jtlindsey
    jtlindsey over 1 year

    I have a script that runs some git and npm commands based on a user like

    #!/bin/sh
    /bin/su someuser -c "
    cd /opt/app1/;
    env -i git remote update;
    env -i git pull origin dev;
    cd /opt/app1/client/;
    npm run build;
    "
    

    The git commands run correctly. The npm command runs and builds the files but throws lots of errors about

    Node Sass could not find a binding for your current environment: Linux 64-bit with Node.js 8.x
    
    Found bindings for the following environments:
      - Linux 64-bit with Node.js 9.x
    
    This usually happens because your environment has changed since running `npm install`.
    Run `npm rebuild node-sass --force` to build the binding for your current environment.
    

    If I run npm run build as the user from terminal, everything builds fine. I even tried env -i npm run build in the script and that just says env: ‘npm’: No such file or directory. So i then tried env -i /usr/local/bin/npm run build and oddly that returned /usr/bin/env: 'node': No such file or directory.

    I though that the user -c would set me up with all env like the user was logged in and that env -i would give me clean env without the parent.

    also tried:

    #!/bin/sh
    /bin/su someuser - -c "
    cd /opt/app1/;
    git remote update;
    git pull origin dev;
    cd /opt/app1/client/;
    npm run build;
    "
    

    That last attempt returns same as first: git commands work, build throws errors about sass and environment as if something is different than when i run the command as the user from the terminal.

    Any idea why this command is not working correctly?

  • jtlindsey
    jtlindsey about 6 years
    I updated my answer with the result of changes. Note that i'm using su vs sudo because i need any user that is part of the group that can run that command to be able to run it without sudo and without a password. The command worked great until we needed to npm run build as part of the process.
  • Olorin
    Olorin about 6 years
    @jtlindsey I don't understand what you mean by the part where you say "because ... without a password". It's easy to setup NOPASSWD rules with sudo, and if you can use su, you can use sudo for that. Also, in the edit, env without any options is meaningless, you might as well run the commands without it. Note how the output says that it expected Node 8.x and got 9.x. How did you install/setup Node 8.x for your user?
  • jtlindsey
    jtlindsey about 6 years
    Fixed last edit. For the install, I logged in as the user and did npm install and then confirmed all npm commands worked from command line before logging out. So i'm not sure how a v8 is showing up. Node legacy is not installed and the user node env is v9
  • Olorin
    Olorin about 6 years
    Did you add anything to .profile, etc. for setting up npm?
  • jtlindsey
    jtlindsey about 6 years
    Just did a locate command to see where any v8 node might be and removed all of them (nvm leave behind previous versions). Then i removed node modules, did npm install again to re-install modules, and same issue. npm run build works if i do it from terminal but it breaks in the middle of the build process when run from script. At this point i don't know where it is getting the v8 from because locate doesn't find v8 anywhere anymore.
  • Olorin
    Olorin about 6 years
    Yep, nvm does rely on environment variables to do its work. I'd misread your comments, and thought you used npm somehow for this and not nvm.