質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
cron

cronは、Unix系OS上でデーモンプロセスとして動作する、スクリプトの自動実行が可能なジョブスケジューラです。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Q&A

解決済

2回答

462閲覧

rubyファイルをcronで実行すると、gemファイルが見つからない

SNG

総合スコア9

cron

cronは、Unix系OS上でデーモンプロセスとして動作する、スクリプトの自動実行が可能なジョブスケジューラです。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

0グッド

0クリップ

投稿2024/01/16 21:20

実現したいこと

'pg'をrequireするrubyファイルをcronを使って定期的に動かしたい。(macOS 14.2.1)

発生している問題・分からないこと

'pg'をrequireするrubyファイルを作成し、ターミナル上で実行した場合にはエラーにならないのですが、cronに登録して実行するとLoadErrorが発生してしまいます。
何に原因があるのかわからないため、何を確認すれば良いか教えてください。

エラーメッセージ

error

1cannot load such file -- pg

該当のソースコード

ruby

1#!/usr/bin/env ruby 2 3begin 4 require 'pg' 5 `echo 'ok' >> ~/echo.txt` 6rescue LoadError => e 7 `echo '#{e}' >> ~/echo.txt` 8end

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

当該のrubyファイルを格納するフォルダを作成し、Gemfileに’pg’を追記し、bundle installをしてみましたが、結果は変わりませんでした。

補足

ruby 3.2.1 (2023-02-08 revision 31819e82c8) [arm64-darwin22]
gem 3.4.20
rbenv 1.2.0

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

melian

2024/01/17 02:20

cron で実行されるスクリプト内では環境変数 PATH がリセットされています。スクリプトに以下を追加して PATH の内容を確認してみてください。 `echo #{ENV['PATH']} > ~/env.txt`
SNG

2024/01/17 21:09

ご教授いただいた方法にて確認してみたところ、ご指摘の通り、意図したRubyが使えていないことがわかりました。ありがとうございました。
guest

回答2

0

ベストアンサー

すでに回答の付いているとおり、環境変数の違いによるものでしょう。
#!/usr/bin/env rubyというのは、「その時点の環境変数PATHを見て、上位にあるrubyを実行する」ということになります。

解決策としては、
案1:1行目を#!/usr/bin/env rubyでなく#!/xxx/yyyy/zzz/rubyのように実際に実行するrubyのフルパスを指定する。
端末にて、type rubyとすると、そのときにrubyというコマンドで実行されるファイルのフルパスが表示されますので、そのままコピペします。
ただし、このファイルを実行するrubyは固定されます。

crontab

10 1 * * * /path/to/ruby-script

ですが、こうじゃなくて

crontab

10 1 * * * ruby /path/to/ruby-script

と書いていたなら、1行目の#!~~は無視されるので、crontabのrubyをフルパスで書きます。

案2:環境変数をそろえる
端末にて、env | sort >/tmp/env-termを実行し、またcrontabで* * * * * env | sort > /tmp/env-cronと一時的に書いて、両者を比較して、違いがある物のうち、PATHやその他RUBYxxxとか、影響しそうな物を調べて、crontabファイルに書く。

crontab

1PATH=xxxxxxxxxx 20 1 * * * /path/to/ruby-script

シェルの初期設定ファイルに書くときは引用符や変数置換などのシェルの機能が使えますが、crontabでは使えないので、文字列をそのまま書きます。env-termから行単位でコピペ。

crontab

10 1 * * * PATH=xxxxxxxxxx /path/to/ruby-script

とコマンドラインに書いても良いので、見にくくなければこれもあり。
これだと「以降全部に対して環境変数設定」じゃなくて「この行だけの環境変数設定」で、変数展開などシェルの機能も使えます。

rbenvなどを使って複数のrubyを使い分けている場合は、案2だと、実行時点でrbenvに指示されているバージョンが使われるので、日によって結果が違うと言うこともあるでしょうね。

投稿2024/01/17 03:59

otn

総合スコア84618

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SNG

2024/01/17 21:05

ご丁寧にご回答いただきありがとございます。 rubyインタープリタとgemの関係性もよくわかっていなかったので、大変助かりました。 ただ、案1にて対応してみたところ、"ok"と出力はされたのですが、同時に"#{e}"とも出力されてしまいました。 エラーが発生しなければrescue以下は実行されないと思っていましたし、変数展開されずそのまま出力されているのもどういうことなのかよくわかりません。 こちらもやはりcronでの実行時のみに発生します。 この原因についても何かわかりますでしょうか?
otn

2024/01/18 06:51

>> ~/echo.txt はファイルへの追記なので、後ろにどんどん追加されます。 前の行を見ているのでしょう。最終行だけ見ましょう。
SNG

2024/01/18 20:44

改めて確認をしましたが、毎回"#{e}"も出力されていました。 出力結果 ok #{e} ok #{e} ... シバンを以下の通り変更することで解決できました。 変更前 #!/Users/username/.rbenv/shims/ruby 変更後 #!/Users/username/.rbenv/versions/x.x.x/bin/ruby
otn

2024/01/21 04:12 編集

毎回2行書かれているのが確かなら、2つの異なるRubyが1回ずつ起動されていることになるので、設定ファイルがなんかおかしなことになっているのかと思います。 一体どんな状態になれば2回起動するのか見当が付きませんが。 調査困難なら、Ruby環境を全部削除して、最初から設定し直すのが良いかと思います。
SNG

2024/01/20 22:08

ありがとうございます。 その後色々といじってみたところ、 #!/Users/username/.rbenv/shims/ruby とした場合には、~/.rbenv/shims/rubyがうまく処理できなかったのか、 実行ファイルがrubyではなくシェルスクリプトとして処理されているようでした。 そのため、beginや変数展開などのrubyの機能は実行されず、 echo 'ok' >> ~/echo.txt echo '#{e}' >> ~/echo.txt がそれぞれ単純にコマンドとして実行されていたようです。 そこでprintenvコマンドを使ってcronの環境変数の設定を確認し、 端末の設定との違いをcrontabに追加して実験したところ、 SHELL=/bin/zsh を書き加えることで解決できることがわかりました。 ~/.rbenv/shims/rubyのコードを読み解く力も足りず、 何故これで解決できたのかはよくわからなかったのですが。。 最終的には、ご教授いただいた案2の方を採用させていただき、 crontabファイルに、 SHELL=/bin/zsh PATH=/Users/username/.rbenv/shims:/usr/bin:/bin を追記して、 シバンは#!/usr/bin/env rubyに戻すことにしました。 大変ありがとうございました。
otn

2024/01/21 13:29 編集

なんと、「毎回"#{e}"も出力」は、#{e}に相当する結果が出力されているという意味ではなくて #{e} という文字列そのものが出力されていると言うことでしたか。それは予想外でした。 スクリプトファイルがシェルスクリプトとして実行されると言うことは、 (A) 明示的に「sh ファイル名」などと実行する (B) 1バイト目からがshbang行でない ですが、(A)は仕組み的に無さそうな気がするので、 あり得るとすると、ファイル編集の際に誤って1行目に空行を入れたとか、BOM付きUTF-8にしてしまったとかで(B)に該当する場合でしょうか。これは、「file ファイル名」で、前者は ASCII text、後者は UTF-8 Unicode (with BOM) text executable と表示されるので分かります。正しければ、a /Users/username/.rbenv/shims/ruby script, ASCII text executable 。 (B)に該当しない場合は、(A)なので、rbenvの何らかのファイルの破損が考えられます。あるいは、私が思いついてない別の原因かも。 原因が比較的簡単と思ったので、アドバイスしていませんでしたが、思ったより複雑なので、エラーメッセージを確認しましょう。 cronで実行したコマンドで何らかの出力があると、そのユーザーにメールされるので、メールを見ます。 postfix等のメールサーバーの設定を何もしておらずメールが届いていない場合は、 0 1 * * * /path/to/ruby-script >$HOME/stdout.txt 2>$HOME/stderr.txt のようにコマンドラインでリダイレクトして、ファイルを見ます。 (この行自体に文法エラーがあると駄目ですが) シェルスクリプトとして実行されている場合、begin などについて command not found が出ているはずですが、それら以前に手がかりとなるメッセージが出ている可能性が高いです。
SNG

2024/01/22 18:41

crontabのSHELL 設定をコメントアウトして、 シバンを#!/Users/username/.rbenv/shims/rubyに戻し、 ご指摘の点確認してみました。 fileコマンドの実行結果です。 echo.rb: a /Users/usename/.rbenv/shims/ruby script text executable, ASCII text ご教示いただいた表示内容とはexecutableの位置が異なるのですが問題ないでしょうか? /var/mail/usernameでメールの内容を確認しました。 X-Cron-Env: <PATH=/Users/username/.rbenv/shims:/usr/bin:/bin> X-Cron-Env: <SHELL=/bin/sh> X-Cron-Env: <LOGNAME=logname> X-Cron-Env: <USER=username> Message-Id: <xxx@xxx.xxx> Date: Tue, 23 Jan 2024 03:33:00 +0900 (JST) /Users/username/echo.rb: line 3: begin: command not found /Users/username/echo.rb: line 4: require: command not found /Users/username/echo.rb: line 6: rescue: command not found /Users/username/echo.rb: line 8: end: command not found こちらはいかがでしょうか? ご指摘いただいた通りrubyの関数はエラーになっているようですが、他に何かわかりますでしょうか。 SHELL=/bin/shが悪さをしている感じでしょうか?
otn

2024/01/25 16:58

> fileコマンドの実行結果です。 shbang行は意図通り認識されているようなので、大丈夫ですね。 > /var/mail/usernameでメールの内容を確認しました。 シェルのエラーメッセージ以外は何も情報が無いですね。
guest

0

cronから呼び出したプログラムでは、環境変数などが通常とは異なってきます。

きちんとrbenvでインストールしたRubyが呼ばれているのか、まずは確認が必要です。

投稿2024/01/17 01:06

maisumakun

総合スコア145190

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SNG

2024/01/17 21:06

早々のご回答大変ありがとうございました。 とても参考になり助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問