問題
「sudo
をつけてnode
を実行するとroot権限で実行できる」というのを聞いて、実際にやってみたら
$ sudo node index.js
sudo: node: command not found
このように「command not found」と表示された。
原因
え? コマンドが見つからないってなんで・・?
sudo
を付けずにnode
を実行するときちんと実行されるのに何故なんだ・・?
と思って調べてみたら、どうやら原因は「sudo
付きでコマンド実行すると環境変数であるPATH
がスーパーユーザーのものに変わるから」だった。
(ただし、このsudoの挙動はLinuxのディストリビューターによって違うらしいです。私の環境はUbuntuでしたが、Ubuntuではこのような挙動になってるらしいです)
例えば以下の2つのコマンドを実行してみてほしい。
printenv PATH
sudo printenv PATH
printenv
は「環境変数の一覧を表示する」というコマンドで、表示したい環境変数を引数に指定するとそれだけを表示できる。
私の環境では以下のような違いが出た。
$ sudo printenv PATH
/usr/local/sbin:
/usr/local/bin:
/usr/sbin:
/usr/bin:
/sbin:
/bin:
/snap/bin
$ printenv PATH
/home/vagrant/.yarn/bin:
/home/vagrant/.config/yarn/global/node_modules/.bin:
/home/vagrant/.nvm/versions/node/v10.14.2/bin:
/usr/local/sbin:
/usr/local/bin:
/usr/sbin:
/usr/bin:
/sbin:
/bin:
/usr/games:
/usr/local/games:
/snap/bin
(※分かりやすいように:で改行して、共通するパスは青で塗りつぶしています)
これを見ると、node
のパスはrootのほうには追加されていない。だから実行できなかったらしい。
解決策
解決策としては、3つくらいあるっぽい。
1つ目
1つ目は
sudo /home/vagrant/.nvm/versions/node/v10.14.2/bin/node index.js
という風に実行するたびにフルパスで書く方法。すると(当たり前だが)うまく動く。
だけど毎回フルパスで書くなんて、さすがに面倒すぎるので
sudo $(which node) index.js
という風に書いたほうがよい。
which
は指定したコマンドのパスを表示するコマンドで、Linuxでは$()
で囲うとそのコマンドの出力結果をコマンドとして使えるという機能があるらしい。
もしくはバッククォーテーション``
で囲ってもOK。
つまり、下の3つのコードは同じ結果をもたらす。
#全部おなじ結果
sudo /home/vagrant/.nvm/versions/node/v10.14.2/bin/node index.js
sudo `which node` index.js
sudo $(which node) index.js
2つ目
2つ目は、sudo
したときに一般ユーザーのPATH
を引き継ぐ方法。
詳しくはこちら。
3つ目
3つ目は、パスがすでに通っているフォルダに(今回の例でいうと例えばusr/bin/)にシンボリックリンクを貼る方法。
ln -s /home/vagrant/.nvm/versions/node/v10.14.2/bin/node /usr/bin/
おわり
コメント