さくらレンタルサーバの Cron Job で Bash スクリプトを実行する

サーバー上で決められた時刻に特定のスクリプトを走らせたい、という時に役立つのがCron Job。さくらレンタルサーバもその機能を提供しており、コントロールパネルから設定可能。毎日 AWStats に Apache ログをインポートさせるのに使えたり、と便利。ただ、Perl のスクリプトはそのファイルのパスを指定して実行されるが、Bash の場合、気をつけないとハマる。

bash コマンドのパス

さくらサーバーのスタンダードプランでは、Cron Job の登録数は5つまでという制限がある。今回、1つの登録で複数まとめて走らせようと、.sh のバッシュスクリプトを書いたのだが、実行されないという罠にハマった。

設定ページはコントロールパネルのアプリケーションの設定 -> CRONの設定から開くことができる。Perl スクリプトなどは /home/ユーザー名/hoge/awstats/cgi-bin/awstats.pl -optionなどとして実行コマンドのフィールドには、直接コマンド名不要で、スクリプトのファイルのパスを指定きる。しかし、バッシュスクリプトは対象のスクリプトファイルのパスを指定しても「入力内容に問題のある項目があります。」というメッセージがでて受け付けてくれない。これは、コマンド名 パス という風に、コマンド名を先に渡してその後に、実行ファイルを書いてあげる必要がある。

  • ☓ /home/{user name}/scripts/test.sh
  • ○ {command} /home/{user name}/scripts/test.sh 

ここで、そのコマンド名を単にbash とすると実行してくれないので注意が必要。

  • bash /home/{user name}/scripts/test.sh

これを sh にすると、実行はしてくれるのだけれど、色々制約がある。

  • sh /home/{user name}/scripts/test.sh

$BASH_SOURCE 変数が使えない罠 (sh の場合)

$BASH_SOURCE 変数は実行中のスクリプトのパスなどを配列として格納してくれている。

BASH_SOURCE
An array variable whose members are the source filenames corre-
sponding to the elements in the FUNCNAME array variable.

(ソース: FreeBSD Manual Pages Bash)

ただ、この変数、 sh でスクリプトを走らせるとアクセスできないみたい。これを知らずに sh で走らせると、ハマる。

1行目の記述 #!/bin/bash

ということは、バッシュスクリプト内の1行目の記述も、

ではなく、

にしなければならないのかとテストしてみたが、これは別に #!/bin/bash で良いみたい。んー、よくわからん。

Bash で走らせるには

細かな制約が絡んでくるので、sh でなくて bash で走らせれるならそれにこしたことはない、ということで、bash の位置を確認。ついでに sh, csh も。

/usr/local/bin/bash ということなので、これを Cron のコマンドとして渡してあげる。

  • ◎  /usr/local/bin/bash /home/{user name}/scripts/test.sh

これで、スクリプトが bash で呼び出されるようになった。

Pathが違う罠

他に注意点として、Cron で実行される際の環境変数の値が、各ユーザーがコンソールにログインして走らせる際のものと違う。スクリプト内で$PATH を参照している場合、想定しているディレクトリとは違う場所が入っていたりする。

これに関しては、もしスクリプト内で何かプログラムを走らせる場合、パスを再度指定してあげると良い。次のラインをスクリプトの先頭部分 #!/bin/sh#!/bin/bash の下に記述してあげる。

date コマンドのオプションの仕様が違う罠

date コマンドは現在時刻や何日前といった時間の計算に便利なのだけど、他のOSのdateコマンドのオプションのシンタックスが違うため、そのフォーマットに則った記述でないとエラーを引き起こし、スクリプトがきちんと動作しなくなる。

具体的には、昨日の日付を取得しようとして、

としても、FreeBSD では通らない。

としなければならない。これを知らないとハマる。というかハマった。

簡単なテスト方法

Cron が正常に走ってるかどうか確かめる方法として、現在時刻の1分後の分を実行日時の分のフィールドに与える。で、スクリプトにログを記録する記述を入れて、正常にログが生成されるかどうかをチェックする。

ちなみにサーバーの現在の時刻を知りたい場合、コンソールで以下のように打つと出る。これで時刻を確認して過ぎていれば、ログがあるかどうか見るという作業の流れを作れる。

$HOME/scripts/test.sh

({user-name} はさくらインターネットから与えられたアカウント名)

こんな感じのテストスクリプトを走らせる。結果、対象スクリプトと同階層に log ディレクトリが作られ、その中に、test.log が生成されればOK。

test.log

$PATH/usr/local/bin/ を含んでいないので、bash が通らないわけだ。ここで sh で走らせてたりすると、SOURCE に値が入ってなかったりする。

デイリースクリプト

これで、バッシュスクリプトをクロンジョブで走らせることができたので、デイリーで走らせるスクリプトを書く。

次のスクリプトは daily ディレクトリに入っている Bash スクリプトを順に実行していくというもの。実行したスクリプトは時刻とともに、そのパスを log 内のログファイルに記録していく。これで何がいつ走ったかは把握できる。ログファイルは月ごとのに名称を変えるので、かさばる心配もしなくて良い。

で、 daily ディレクトリに Bash スクリプトを放り込んでいくだけ。後は、コントロールパネルで、時刻と頻度を希望のものすれば設定完了。

共用サーバの呪縛

見てきたとおり、さくらレンタルサーバの Cron で Bash スクリプトを走らせようとすると、数々の罠が張り巡らされており、やりたいことを達成するのは至難の技ということがわかった。これはまだまだ序の口で、何かちょっとしたことをしようとするだけで、数え切れない壁が立ちはだかる。共用のレンタルサーバーというのは、一見、誰でも運用できそうなイメージがあり、敷居が低いように見える。しかし、自由度が低く、その縛りをかいくぐるスキルが問われる為、実はめちゃくちゃハードルが高い。

Leave a Reply

Your email address will not be published. Required fields are marked *