私は通常、環境設定がされていないため、cronがスクリプトを実行する方法にいくつかの問題があります。スクリプトをインストールする前にテストできるように、cronと同じ方法でbash(?)を呼び出す方法はありますか?
私は通常、環境設定がされていないため、cronがスクリプトを実行する方法にいくつかの問題があります。スクリプトをインストールする前にテストできるように、cronと同じ方法でbash(?)を呼び出す方法はありますか?
回答:
これをcrontabに(一時的に)追加します。
* * * * * env > ~/cronenv
実行後、次のようにします。
env - `cat ~/cronenv` /bin/sh
これは、ユーザーのデフォルトシェルに関係なく、cronが/ bin / shを実行することを前提としています。
env -
猫〜/ cronenv` / binに/ sh`もcronジョブとして記述する必要がありますか?例を挙げてください
Cronはデフォルトでこの環境のみを提供します:
HOME
ユーザーのホームディレクトリLOGNAME
ユーザーのログインPATH=/usr/bin:/usr/sbin
SHELL=/usr/bin/sh
さらに必要な場合は、crontabのスケジュール表の前に環境を定義するスクリプトを用意できます。
いくつかのアプローチ:
cron envをエクスポートし、それを入手します。
追加
* * * * * env > ~/cronenv
あなたのcrontabに、それを一度実行し、それをオフにしてから実行します
env - `cat ~/cronenv` /bin/sh
そして今、あなたはsh
cronの環境を持つセッションの中にいます
環境をcronにする
上記の演習をスキップして. ~/.profile
、cronジョブの前で実行することもできます。
* * * * * . ~/.profile; your_command
画面を使用
上記の2つのソリューションは、実行中のXセッションに接続された環境などを提供するという点で失敗しますdbus
。たとえば、Ubuntuでは、nmcli
(Network Manager)は上記の2つのアプローチで機能しますが、cronでは失敗します。
* * * * * /usr/bin/screen -dm
上記の行をcronに追加し、1回実行してからオフに戻します。スクリーンセッションに接続します(screen -r)。あなたがチェックしている場合は、画面のセッションが作成されている(とps
)彼らは大文字(例では時々あることに注意してくださいps | grep SCREEN
)
さてnmcli
、同様のものは失敗します。
実行できます:
env - your_command arguments
これはyour_commandを空の環境で実行します。
env - HOME="$HOME" LOGNAME="$USER" PATH="/usr/bin:/bin" SHELL="$(which sh)" command arguments
ているトリック
アカウントのシェルに応じて
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から
6年後の回答:環境の不一致の問題はsystemd
、cronの代わりに「タイマー」によって解決される問題の1つです。systemd "サービス"をCLIから実行する場合でも、cron経由で実行する場合でも、まったく同じ環境を受け取り、環境の不一致の問題を回避します。
cronジョブが手動でパスするときに失敗する最も一般的な問題は、$PATH
cronによって設定された制限付きのデフォルトです。これは、Ubuntu 16.04の場合です。
"/usr/bin:/bin"
対照的に、Ubuntu 16.04で$PATH
設定されsystemd
ているデフォルトは次のとおりです。
"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
そのため、systemdタイマーが手間をかけずにバイナリを検出する可能性が高くなっています。
systemdタイマーの欠点は、設定に少し時間がかかることです。まず、実行したいものを定義する「サービス」ファイルと、それを実行するスケジュールを定義する「タイマー」ファイルを作成し、最後にタイマーを「有効」にしてそれをアクティブにします。
envを実行してstdoutをファイルにリダイレクトするcronジョブを作成します。「env-」と一緒にファイルを使用して、cronジョブと同じ環境を作成します。
cronの親はinitであるため、制御端末なしでプログラムを実行することを忘れないでください。次のようなツールでそれをシミュレートできます:
デフォルトでcron
は、システムのアイデアが何であれ、ジョブを実行しますsh
。これは、実際のBourneシェルであるか、または可能性がdash
、ash
、ksh
又はbash
(または別のもの)にシンボリックリンクsh
(およびPOSIXモードで動作している結果として)。
最善の方法は、スクリプトに必要なものがあることを確認し、何も提供されていないと想定することです。したがって、完全なディレクトリ指定を使用し、$PATH
自分などの環境変数を設定する必要があります。
0 0 * * 1 /path/to/executable >/dev/null 2>&1
次に、「実行可能」内での値を設定し$PATH
、完全なディレクトリ仕様を使用して入力ファイルや出力ファイルなどを作成します。例:/path/to/do_something /another/path/input_file /another/path/to/output_file
私が見つけた別の簡単な方法(ただし、エラーが発生する可能性があるため、まだテスト中です)は、コマンドの前にユーザーのプロファイルファイルを読み込むことです。
/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
受け入れられた答えは、cronが使用する環境でスクリプトを実行する方法を提供します。他の人が指摘したように、cronジョブのデバッグに必要な基準はこれだけではありません。
確かに、cronは、入力などが付加されていない非対話型端末も使用します。
それが役立つ場合は、コマンド/スクリプトをcronで実行するのと同じように簡単に実行できるスクリプトを作成しました。コマンド/スクリプトを最初の引数として呼び出してください。
このスクリプトはGithubでもホストされています(更新される可能性もあります)。
#!/bin/bash
# Run as if it was called from cron, that is to say:
# * with a modified environment
# * with a specific shell, which may or may not be bash
# * without an attached input terminal
# * in a non-interactive shell
function usage(){
echo "$0 - Run a script or a command as it would be in a cron job, then display its output"
echo "Usage:"
echo " $0 [command | script]"
}
if [ "$1" == "-h" -o "$1" == "--help" ]; then
usage
exit 0
fi
if [ $(whoami) != "root" ]; then
echo "Only root is supported at the moment"
exit 1
fi
# This file should contain the cron environment.
cron_env="/root/cron-env"
if [ ! -f "$cron_env" ]; then
echo "Unable to find $cron_env"
echo "To generate it, run \"/usr/bin/env > /root/cron-env\" as a cron job"
exit 0
fi
# It will be a nightmare to expand "$@" inside a shell -c argument.
# Let's rather generate a string where we manually expand-and-quote the arguments
env_string="/usr/bin/env -i "
for envi in $(cat "$cron_env"); do
env_string="${env_string} $envi "
done
cmd_string=""
for arg in "$@"; do
cmd_string="${cmd_string} \"${arg}\" "
done
# Which shell should we use?
the_shell=$(grep -E "^SHELL=" /root/cron-env | sed 's/SHELL=//')
echo "Running with $the_shell the following command: $cmd_string"
# Let's route the output in a file
# and do not provide any input (so that the command is executed without an attached terminal)
so=$(mktemp "/tmp/fakecron.out.XXXX")
se=$(mktemp "/tmp/fakecron.err.XXXX")
"$the_shell" -c "$env_string $cmd_string" >"$so" 2>"$se" < /dev/null
echo -e "Done. Here is \033[1mstdout\033[0m:"
cat "$so"
echo -e "Done. Here is \033[1mstderr\033[0m:"
cat "$se"
rm "$so" "$se"
回答https://stackoverflow.com/a/2546509/5593430は、cron環境を取得してスクリプトに使用する方法を示しています。ただし、使用するcrontabファイルによって環境が異なる場合があることに注意してください。を介して環境を保存するために、3つの異なるcronエントリを作成しましたenv > log
。これらは、Amazon Linux 4.4.35-33.55.amzn1.x86_64での結果です。
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
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
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
最も重要なこと PATH
、PWD
そしてHOME
異なることです。安定した環境に依存するように、これらをcronスクリプトで設定してください。