

`cron`のジョブの動作を作成するときに `bash -c` を用いて

[code]

    30 12 * * 1-5 bash -c 'export PATH="/usr/local/bin:/opt/rbenv/bin:$PATH"; eval "$(rbenv init -)"; cd /opt/foo; /opt/rbenv/shims/ruby foo.rb'
    
[/code]

のように必要な環境変数などを設定して実行するのですが、どうしてもシェル上の環境と異なってしまいエラーになることがあります。

そのような時にはいつも1分後にタスクを設定して動作を確認しているのですが
1~59秒間待たずにcrontabのリストから即座に特定のタスクを実行する方法はないでしょうか？

環境はUbuntu14.04を使用しています。


CC BY-SA 3.0
2015-01-22T09:15:51.333
5072
2020-07-31T07:31:27.453
2020-07-31T07:31:27.453
3060
3271
question
linux cron
cronの特定のタスクを即座に実行する方法


実際には crontab は以下の様に時刻情報の上の行に環境変数設定が書ける為

[code]

    FOO=BAR
    30 12 * * 1-5 /path/fo/foo
    
[/code]

そのままコピペして実行しても異なる結果となり得ます。  
インターネット上では grep や sed を駆使して `crontab -l` の結果から抜き出す物もありますが、上記の理由で信頼出来る物ではありません。

**一番の解は...**

環境変数の設定も含めた実行内容をスクリプトに全て書いて、crontab では実行文のみにするのが一番の解だと思います。

**追記**

環境変数を同じにしたいのであれば

[Running a cron job manually and immediately](https://serverfault.com/a/85906)

ここで言われている様に一度 env を吐き出して確認するのが良いと思います。


CC BY-SA 3.0
2015-01-22T09:54:13.563
5076
2015-01-22T10:00:13.980
2017-04-13T12:14:55.443
-1
440
5072
answer


cronは一分に一回設定ファイルを読み込んで評価するので、cronのままで難しいですね。

一定間隔で実行するだけなら、sleepを挟んだ無限ループのシェルスクリプトを  
rc.dに登録したほうが簡単かもしれないです。

serviceコマンドを使って起動しないと、環境変数が違う罠に引っかかるので気を付けて下さい。  
FreeBSDの場合は問題ないんですが、Linux系では一部環境変数がのこるものも有るらしいです。  
<http://heartbeats.jp/hbblog/2013/06/service-start-stop.html>

また、runitやdjb daemontools等の無限ループに対応したサービス管理ソフトもあります。


CC BY-SA 3.0
2015-01-22T11:56:24.833
5085
2015-01-22T11:56:24.833
4439
5072
answer


Debian / Ubuntu なら faketime というパッケージが標準で用意されており、これを用いれば `faketime`
下で動作するプロセスの日時や時間の進む速さを騙すことができます。

[code]

    $ sudo apt-get install faketime
    $ faketime -f x10 bash -c 'while :; do sleep 1; date;done'
    
[/code]

これが利用できるかと手元の `cron` を `faketime` を介して起動させてみたのですが、  
残念ながら騙せませんでした。

cron ジョブを即座に実行する方法ではありませんが、bash の rc によって設定される環境を利用して cron ジョブを実行したいのであれば、bash
に `-l` オプションを付与してログインシェルとして起動するようにしてみてください。

[code]

    30 12 * * 1-5 bash -lc 'export PATH="/usr/local/bin:/opt/rbenv/bin:$PATH"; eval "$(rbenv init -)"; cd /opt/foo; /opt/rbenv/shims/ruby foo.rb'
    
[/code]

余談ですが、シェルで複数のコマンドを実行するとき、続くコマンドが先のコマンドの実行結果に依存している場合は、コマンドを `;` で区切るのではなく `&&`
で区切ったほうが安全です。これによりコマンドが失敗した時点で中断できます。

[code]

    30 12 * * 1-5 bash -lc 'export PATH="/usr/local/bin:/opt/rbenv/bin:$PATH"; eval "$(rbenv init -)" && cd /opt/foo && /opt/rbenv/shims/ruby foo.rb'
    
[/code]

もしくは `set -e` を先に実行したほうがいいです。

[code]

    30 12 * * 1-5 bash -lc 'set -e; export PATH="/usr/local/bin:/opt/rbenv/bin:$PATH"; eval "$(rbenv init -)"; cd /opt/foo; /opt/rbenv/shims/ruby foo.rb'
    
[/code]


CC BY-SA 3.0
2015-01-22T17:11:15.757
5106
2015-01-22T17:44:28.213
2015-01-22T17:44:28.213
3061
3061
5072
answer


UNIX系OSにはatというコマンドがあって、時刻指定で一回だけコマンドを実行することができます。  
内部的にはcronと同じ仕組みでキューイングしているはずなのでこれを使って試すというのはどうでしょうか。

詳しくはman atを見ていただきたいですが、即時なら`at now`というのができるはずです。


CC BY-SA 3.0
2015-08-21T01:53:11.943
14688
2015-08-21T01:53:11.943
8136
5072
answer