最近、仕事でRubyの案件があり、開発はPCのVirtualBox行い、Raspberry Piで納品したらどうなるか試していました。
そのままではうまくいかず数日間を無駄にしたので記事に残して忘れないようにしたいと思います。
ターミナルとシェルスクリプトはPATHが違う!
ターミナルから「bundle exec ruby」コマンドを打つと動くのに同じ内容のシェルスクリプトファイルをダブルクリックで実行しても何も起こらず数日悩みましたが解決しました。
結論から言ってしまうと、
シェルスクリプトファイルから実行されるコマンドにはPATHが通っていないことが原因でした。ターミナルを起動する時に読み込む「.bash_profile」や「.bashrc」などがシェルスクリプトファイルから実行する時には読み込まれなていなかったのでシェルスクリプトのファイル内に$PATHを上書きすることで実行できるようになります。
以下説明です。
動作環境
rbenvを使ってラズパイにRuby on Railsをインストールしています。
Raspberry pi 3
Raspberry pi OS (2021.4)
anyenv 1.1.2
nodenv 1.4.0
node-js 14.16.1
npm 6.14.12
rbenv 1.1.2
Ruby 2.6.7
Gem 3.0.3.1
Bundler 2.2.16
Rails 6.1.3
ターミナル上ではbundle execが問題なく実行できる状態として進めます。
PATHの差分を出し、シェルスクリプトで上書きする方法
ターミナルとシェルスクリプトのPATHの違いを知る
まず適当なシェルスクリプトファイルを作成する。
$ vim ~/Desktop/echo_path.sh
echo_path.shの中身
#!/bin/bash echo $PATH 1> /home/pi/Desktop/path.txt
デスクトップのpath.txtにecho $PATHの出力をするようにしています。
shファイルを作ったら右クリックで「ファイルのプロパティ」に入りパーミッションをすべて「すべて」にする。これをしないとダブルクリック時にエディタが起動してしまうので。
実行後、出力されたpath.txtに$PATHの中身が書き出されているはずです。私のマシンでは以下のようなPATHでした。
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games
次にターミナルでecho $PATHを実行する。
$ echo $PATH
例えばこんな感じに出ると思います。
/home/pi/.anyenv/envs/rbenv/shims:/home/pi/.anyenv/envs/rbenv/bin:/home/pi/.anyenv/envs/nodenv/shims:/home/pi/.anyenv/envs/nodenv/bin:/home/pi/.anyenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games
後半部分はpath.txtの中身と全く同じで「$PATH」にあたります。差分を取り出し、後ろに「:$PATH」を付けると上書き用のPATHとなります。
シェルスクリプトファイルのbundle exec実行前にPATHの上書き
最後に本番用のシェルスクリプトファイルのbundle exec実行前にPATHの上書きをすれば動作するはずです。参考になるかわかりませんが、サンプルソースを置いておきます。
#!/bin/bash cd `dirname $0` export PATH="/home/pi/.anyenv/envs/rbenv/shims:/home/pi/.anyenv/envs/rbenv/bin:/home/pi/.anyenv/envs/nodenv/shims:/home/pi/.anyenv/envs/nodenv/bin:/home/pi/.anyenv/bin:$PATH" cd /var/apps/hoge/ bundle exec ○○○○○○
ご参考になれば幸いです。
お世話になった記事
cron実行時に『/bin/sh: ~~: command not found』と出てcronが実行されない場合
助かりました!ありがとうございます!!