Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>A wee bit beyond the scope of your question... but here's what I do.</p> <p>The "how do I test a cron job?" question is closely connected to "how do I test scripts that run in non-interactive contexts launched by other programs?" In cron, the trigger is some time condition, but lots of other *nix facilities launch scripts or script fragments in non-interactive ways, and often the conditions in which those scripts run contain something unexpected and cause breakage until the bugs are sorted out.</p> <p>A general approach to this problem is helpful to have.</p> <p>One of my favorite techniques is to use a script I wrote called '<a href="https://github.com/Stabledog/crontest" rel="noreferrer">crontest</a>'. It launches the target command inside a GNU screen session from within cron, so that you can attach with a separate terminal to see what's going on, interact with the script, even use a debugger.</p> <p>To set this up, you would use "all stars" in your crontab entry, and specify crontest as the first command on the command line, e.g.:</p> <pre><code>* * * * * crontest /command/to/be/tested --param1 --param2 </code></pre> <p>So now cron will run your command every minute, but crontest will ensure that only one instance runs at a time. If the command takes time to run, you can do a "screen -x" to attach and watch it run. If the command is a script, you can put a "read" command at the top to make it stop and wait for the screen attachment to complete (hit enter after attaching)</p> <p>If your command is a bash script, you can do this instead:</p> <pre><code>* * * * * crontest --bashdb /command/to/be/tested --param1 --param2 </code></pre> <p>Now, if you attach with "screen -x", you'll be facing an interactive bashdb session, and you can step through the code, examine variables, etc.</p> <pre><code>#!/bin/bash # crontest # See https://github.com/Stabledog/crontest for canonical source. # Test wrapper for cron tasks. The suggested use is: # # 1. When adding your cron job, use all 5 stars to make it run every minute # 2. Wrap the command in crontest # # # Example: # # $ crontab -e # * * * * * /usr/local/bin/crontest $HOME/bin/my-new-script --myparams # # Now, cron will run your job every minute, but crontest will only allow one # instance to run at a time. # # crontest always wraps the command in "screen -d -m" if possible, so you can # use "screen -x" to attach and interact with the job. # # If --bashdb is used, the command line will be passed to bashdb. Thus you # can attach with "screen -x" and debug the remaining command in context. # # NOTES: # - crontest can be used in other contexts, it doesn't have to be a cron job. # Any place where commands are invoked without an interactive terminal and # may need to be debugged. # # - crontest writes its own stuff to /tmp/crontest.log # # - If GNU screen isn't available, neither is --bashdb # crontestLog=/tmp/crontest.log lockfile=$(if [[ -d /var/lock ]]; then echo /var/lock/crontest.lock; else echo /tmp/crontest.lock; fi ) useBashdb=false useScreen=$( if which screen &amp;&gt;/dev/null; then echo true; else echo false; fi ) innerArgs="$@" screenBin=$(which screen 2&gt;/dev/null) function errExit { echo "[-err-] $@" | tee -a $crontestLog &gt;&amp;2 } function log { echo "[-stat-] $@" &gt;&gt; $crontestLog } function parseArgs { while [[ ! -z $1 ]]; do case $1 in --bashdb) if ! $useScreen; then errExit "--bashdb invalid in crontest because GNU screen not installed" fi if ! which bashdb &amp;&gt;/dev/null; then errExit "--bashdb invalid in crontest: no bashdb on the PATH" fi useBashdb=true ;; --) shift innerArgs="$@" return 0 ;; *) innerArgs="$@" return 0 ;; esac shift done } if [[ -z $sourceMe ]]; then # Lock the lockfile (no, we do not wish to follow the standard # advice of wrapping this in a subshell!) exec 9&gt;$lockfile flock -n 9 || exit 1 # Zap any old log data: [[ -f $crontestLog ]] &amp;&amp; rm -f $crontestLog parseArgs "$@" log "crontest starting at $(date)" log "Raw command line: $@" log "Inner args: $@" log "screenBin: $screenBin" log "useBashdb: $( if $useBashdb; then echo YES; else echo no; fi )" log "useScreen: $( if $useScreen; then echo YES; else echo no; fi )" # Were building a command line. cmdline="" # If screen is available, put the task inside a pseudo-terminal # owned by screen. That allows the developer to do a "screen -x" to # interact with the running command: if $useScreen; then cmdline="$screenBin -D -m " fi # If bashdb is installed and --bashdb is specified on the command line, # pass the command to bashdb. This allows the developer to do a "screen -x" to # interactively debug a bash shell script: if $useBashdb; then cmdline="$cmdline $(which bashdb) " fi # Finally, append the target command and params: cmdline="$cmdline $innerArgs" log "cmdline: $cmdline" # And run the whole schlock: $cmdline res=$? log "Command result: $res" echo "[-result-] $(if [[ $res -eq 0 ]]; then echo ok; else echo fail; fi)" &gt;&gt; $crontestLog # Release the lock: 9&lt;&amp;- fi </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload