web-dev-qa-db-ja.com

cronでスクリプトを実行する環境をシミュレートする方法は?

通常cronには環境が設定されていないため、cronのスクリプトの実行方法にいくつかの問題があります。 cronと同じようにbash(?)を呼び出す方法はありますか。スクリプトをインストールする前にテストできますか?

243
Jorge Vargas

これをcronに追加します:

30 08 * * * env > ~/cronenv

実行後、次を実行します。

env - `cat ~/cronenv` /bin/sh

これは、cronが/ bin/shを実行することを前提としています。これは、ユーザーのデフォルトシェルに関係なくデフォルトです。

371
mmccoo

Cronはデフォルトでこの環境のみを提供します:

  • HOMEユーザーのホームディレクトリ
  • LOGNAMEユーザーのログイン
  • PATH=/usr/bin:/usr/sbin
  • Shell=/usr/bin/sh

さらに必要な場合は、crontabのスケジューリングテーブルの前に環境を定義するスクリプトを入手できます。

61
gregseth

いくつかのアプローチ:

  1. cron envをエクスポートしてソース:

    追加

    * * * * * env > ~/cronenv
    

    あなたのcrontabに、それを一度実行させて、それをオフに戻してから実行してください

    env - `cat ~/cronenv` /bin/sh
    

    そして今、あなたはcronの環境を持つshセッションの中にいます

  2. 環境をcronに移行する

    上記の演習をスキップして、cronジョブの前で. ~/.profileを実行できます。

    * * * * * . ~/.profile; your_command
    
  3. 画面を使用

    上記の2つのソリューションは、dbusなどにアクセスできる実行中のXセッションに接続された環境を提供するという点で依然として失敗します。たとえば、Ubuntuでは、nmcli(Network Manager)ただし、cronでは失敗します。

    * * * * * /usr/bin/screen -dm
    

    上記の行をcronに追加し、一度実行してから、オフにします。スクリーンセッションに接続します(screen -r)。スクリーンセッションが(psで)作成されたことを確認する場合、それらが大文字である場合があることに注意してください(例:ps | grep SCREEN

    これで、nmcliおよび同様のものも失敗します。

47
Cookie

以下を実行できます。

env - your_command arguments

これにより、空の環境でyour_commandが実行されます。

22
dimba

アカウントのシェルに応じて

Sudo su
env -i /bin/sh

または

Sudo su
env -i /bin/bash --noprofile --norc

から http://matthew.mceachen.us/blog/howto-simulate-the-cron-environment-1018.html

14
tcurdt

6年後の回答:環境の不一致の問題は、cronの代替としてsystemd "timers"によって解決される問題の1つです。 systemdの「サービス」をCLIから実行する場合でも、cron経由で実行する場合でも、まったく同じ環境を受け取り、環境の不一致の問題を回避します。

Cronジョブが手動で渡されたときに失敗する最も一般的な問題は、cronによって設定された制限付きのデフォルト$PATHです。これはUbuntu 16.04では次のとおりです。

"/usr/bin:/bin"

対照的に、Ubuntu 16.04でsystemdによって設定されるデフォルトの$PATHは次のとおりです。

"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

そのため、systemdタイマーがさらに手間をかけずにバイナリを見つける可能性がすでにあります。

Systemdタイマーの欠点は、それらをセットアップする時間がもう少し長いことです。最初に「サービス」ファイルを作成して実行するものを定義し、「タイマー」ファイルを実行してスケジュールを定義し、最後にタイマーを「有効化」してアクティブにします。

12
Mark Stosberg

Envを実行し、stdoutをファイルにリダイレクトするcronジョブを作成します。 「env-」と一緒にファイルを使用して、cronジョブと同じ環境を作成します。

10
Jens Carlberg

Cronの親はinitなので、制御端末なしでプログラムを実行することを忘れないでください。次のようなツールでそれをシミュレートできます。

http://libslack.org/daemon/

3
Randy Proctor

デフォルトでは、cronは、システムのshの考えが何であれ、そのジョブを実行します。これは、実際のBourne Shellまたはdashashksh、またはbash(または別の1つ)がshにシンボリックリンクされている可能性がありますPOSIXモード)。

最善の方法は、スクリプトに必要なものがあることを確認し、何も提供されていないことを前提とすることです。したがって、完全なディレクトリ仕様を使用し、$PATHなどの環境変数を自分で設定する必要があります。

2

私が見つけたもう1つの簡単な方法(ただし、エラーが発生する可能性があるため、まだテスト中です)は、コマンドの前にユーザーのプロファイルファイルを取得することです。

/etc/cron.d/スクリプトの編集:

* * * * * user1 comand-that-needs-env-vars

になります:

* * * * * user1 source ~/.bash_profile; source ~/.bashrc; comand-that-needs-env-vars

汚れていますが、仕事は完了しました。ログインをシミュレートする方法はありますか?実行できるコマンドだけですか? bash --loginは機能しませんでした。しかし、それがより良い方法だと思われます。

編集:これは堅実な解決策のようです: http://www.epicserve.com/blog/2012/feb/7/my-notes-cron-directory-etccrond-ubuntu-1110/

* * * * * root su --session-command="comand-that-needs-env-vars" user1 -l
1
four43

回答 https://stackoverflow.com/a/2546509/55934 は、cron環境を取得してスクリプトに使用する方法を示しています。ただし、使用するcrontabファイルによって環境が異なる可能性があることに注意してください。 env > log経由で環境を保存するために、3つの異なるcronエントリを作成しました。これらは、Amazon Linux 4.4.35-33.55.amzn1.x86_64での結果です。

1. rootユーザーを含むグローバル/ etc/crontab

MAILTO=root
Shell=/bin/bash
USER=root
PATH=/sbin:/bin:/usr/sbin:/usr/bin
PWD=/
LANG=en_US.UTF-8
SHLVL=1
HOME=/
LOGNAME=root
_=/bin/env

2.ルートのユーザーcrontab(crontab -e

Shell=/bin/sh
USER=root
PATH=/usr/bin:/bin
PWD=/root
LANG=en_US.UTF-8
SHLVL=1
HOME=/root
LOGNAME=root
_=/usr/bin/env

3. /etc/cron.hourly/のスクリプト

MAILTO=root
Shell=/bin/bash
USER=root
PATH=/sbin:/bin:/usr/sbin:/usr/bin
_=/bin/env
PWD=/
LANG=en_US.UTF-8
SHLVL=3
HOME=/
LOGNAME=root

最も重要なのは、PATHPWD、およびHOMEが異なることです。安定した環境に依存するように、これらをcronスクリプトで設定してください。

0
Maikel