web-dev-qa-db-ja.com

Bashスクリプトがnpmコマンドを正しく処理しない

次のようなユーザーに基づいていくつかのgitおよびnpmコマンドを実行するスクリプトがあります

#!/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;
"

gitコマンドは正しく実行されます。 npmコマンドを実行してファイルをビルドしますが、次のような多くのエラーをスローします

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.

端末からユーザーとしてnpm run buildを実行すると、すべて正常にビルドされます。スクリプトでenv -i npm run buildを試してみたところ、env: ‘npm’: No such file or directoryと表示されました。それで私はenv -i /usr/local/bin/npm run buildを試しましたが、奇妙なことに/usr/bin/env: 'node': No such file or directoryが返されました。

user -cは、ユーザーがログインしたときのようにすべての環境を設定し、env -iは親なしでenvを提供してくれると思いました。

また試しました:

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

最後の試みは最初と同じ結果を返します:gitコマンドは機能し、ビルドはsassと環境に関するエラーをスローします。ターミナルからユーザーとしてコマンドを実行するときとは何かが異なるかのようです。

このコマンドが正しく機能しない理由は何ですか?

2
jtlindsey

ノードエラーを確認するというオロリンの提案に従って、私はそれをさらに調査しました。 someusernode -vv9.4.0を返していて、locateコマンドがv8のバージョンをユーザーにインストールしていないため、再インストールされたnodeでも、同じエラーが発生しました。次のコマンドが機能します。 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;

ある時点で私はnvm use v9.5.0を持っていて、それなしでも動作することをテストしました。次に、source ~/.nvm/nvm.sh;を削除しましたが、再び壊れました。そのため、明らかにnvmShell-scriptsenvではソースなしでは利用できず、npm run buildnvmを参照する必要があります。

奇妙な問題で、一部のユーザーがnvmbashリソースを this thread に基づいて使用すると、同様の問題に遭遇したようです。 v8がどこから取得されたかはまだわかりません。 v8インストールのinclude/nodeディレクトリからv9を取得していない限り。例:

/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
1
jtlindsey

env -iは環境をクリーンアップします。これにはPATH変数が含まれます。これは、フルパスを指定しない場合にコマンドを検索するために使用されます。したがって、env -i、呼び出すコマンドへのフルパスを指定する必要があります。 npmを使用すると、npm自体が#! /usr/bin/env nodeはシバンなので、nodeコマンドの検索は失敗します。

環境をクリーンアップする必要がある場合は、次のいずれかを試してください。

  • Sudo -iu someuser sh -c "...."
  • su someuser - -c "...."(これらのコマンドはどちらも、環境のクリーンアップを行ってログインシェルを起動します)
  • または、envを使用して、Ubuntu serviceコマンドのように、いくつかの環境変数を保持します。

    $ 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)
    

    おそらくそれらすべては必要ありませんが、$PATH$TERM、そしておそらくLC_ALL=C

1
Olorin