我怎麼能讓 cron 立即執行一個作業來進行測試/調試?不改變日程!

我怎麼能讓 cron 立即執行一個作業來進行測試/調試?不改變日程!

我有一個計劃每天運行的 cron 作業,除了更改計劃之外,還有其他方法可以立即測試該命令以查看它是否按預期運行嗎?

編輯:(從評論中)我知道該命令在shell(我的shell)中輸入時工作正常,但我想知道cron 運行它時它是否正常工作,它可能會受到ENV 或shell 特定內容的影響(〜擴展)或所有權和許可的東西或......

答案1

您可以使用以下命令強制 crontab 運行:

run-parts /etc/cron.daily

答案2

您可以模擬 cron 使用者環境,如中所述“立即手動執行 cron 作業”。這將允許您測試作業以 cron 使用者身分執行時的工作情況。


摘自連結:


步驟1:我將這一行暫時放在使用者的 crontab 中:

* * * * *   /usr/bin/env > /home/username/tmp/cron-env

然後在文件寫入後將其取出。

第2步:自己製作了一個 run-as-cron bash 腳本,其中包含:

#!/bin/bash
/usr/bin/env -i $(cat /home/username/tmp/cron-env) "$@"

那麼,作為有問題的用戶,我能夠

    run-as-cron /the/problematic/script --with arguments --and parameters

答案3

據我所知,沒有辦法直接做到這一點,因為 cron 有一個特殊的目的 - 在特定時間運行計劃命令。因此,最好的方法是手動建立一個(臨時)crontab 條目或編寫一個刪除並重置環境的腳本。

“刪除並重置環境”的說明:

可以啟動包裝器腳本(這會刪除環境),該腳本將在啟動腳本之前env -i取得已儲存的環境(確保匯出所有變量,可能會先進行設定)。set -a

保存的環境將是 cron 作業的預設環境,透過作為 cronjob運行env(或取決於 cron 作業使用的 shell)來記錄,並保存其輸出。declare -p

答案4

在需要自己偵錯 cron 作業後,我編寫了以下腳本。在執行命令之前,它會盡力模擬與 cron 完全相同的條件(包括修改的環境,但它也與非互動式 shell、沒有附加終端等有關)。

使用您的命令/腳本作為參數來呼叫它,您可以立即輕鬆地偵錯您的 cron 作業。它還託管(並可能更新)在 GitHub 上:run-as-cron.sh

#!/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 redirect the output into files
# and provide /dev/null as input
# (so that the command is executed without an open terminal
# on any standard file descriptor)
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"

相關內容