Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

(I have already read How can I test a new cron script ?.)

I have a specific problem (cron job doesn't appear to run, or run properly), but the issue is general: I'd like to debug scripts that are cronned. I am aware that I can set up a * * * * * crontab line, but that is not a fully satisfactory solution. I would like to be able to run a cron job from the command line as if cron were running it (same user, same environment variables, etc.). Is there a way to do this? Having to wait 60 seconds to test script changes is not practical.

share|improve this question
add comment

7 Answers

up vote 12 down vote accepted

Here's what I did, and it seems to work in this situation. At least, it shows me an error, whereas running from the command line as the user doesn't show the error.


Step 1: I put this line temporarily in the user's crontab:

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

then took it out once the file was written.

Step 2: Made myself a little run-as-cron bash script containing:

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


So then, as the user in question, I was able to

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

This solution could obviously be expanded to make use of sudo or such for more flexibility.

Hope this helps others.

share|improve this answer
1  
This does not work for me and I wonder if it does for anybody who upvoted. 1) Why are you using bash? It's not required here and it might not be located in /usr/bin. 2) The cat …/cron-env outputs multiple lines, which is does not work. Just try to execute /usr/bin/env -i $(cat cron-env) echo $PATH in the terminal, it outputs the environment literally instead of using it. 3) The current environment leaks into the emulated cron environment. Try: export foo=leaked; run-as-cron echo $foo. –  Marco Sep 24 '13 at 18:33
add comment

I present a solution based on Pistos answer, but without the flaws.

  • Add the following line to the crontab, e.g. using crontab -e

    * * * * *  /usr/bin/env > /home/username/cron-env
    
  • Create a shell script which executes a command in the same environment as cron jobs run:

    #!/bin/sh
    
    . "$1"
    exec /usr/bin/env -i "$SHELL" -c ". $1; $2"
    

Use:

run-as-cron <cron-environment> <command>

e.g.

run-as-cron /home/username/cron-env 'echo $PATH'

Note that the second argument needs to be quoted if it requires an argument. The first line of the script loads a POSIX shell as interpreter. The second line sources the cron environment file. This is required to load the correct shell, which is stored in the environment variable SHELL. Then it loads an empty environment (to prevent leaking of environment variables into the new shell), launches the same shell which is used for cronjobs and loads the cron environment variables. Finally the command is executed.

share|improve this answer
    
this helped me to reproduce my ruby-related sphinx loading error. –  cweiske Dec 9 '13 at 7:52
add comment

By default with most default cron daemons that I have seen, there is simply no way of telling cron to run right here right now. If you're using anacron, it may be possible I think to run a separate instance in the foreground.

If your scripts aren't running properly then you are not taking into account that

  • the script is running as a particular user
  • cron has a restricted environment (the most obvious manifestation of this is a different path).

From crontab(5):

Several environment variables are set up automatically by the cron(8) daemon. SHELL is set to /bin/sh, and LOGNAME and HOME are set from the /etc/passwd line of the crontab’s owner. PATH is set to "/usr/bin:/bin". HOME, SHELL, and PATH may be overridden by settings in the crontab; LOGNAME is the user that the job is running from, and may not be changed.

In general PATH is the biggest problem, so you need to:

  • Explicitly set the PATH within the script, while testing, to /usr/bin:/bin. You can do this in bash with export PATH="/usr/bin:/bin"
  • Explicitly set the proper PATH you want at the top of the crontab. e.g. PATH="/usr/bin:/bin:/usr/local/bin:/usr/sbin:/sbin"

If you need to run the script as another user without a shell (e.g. www-data), use sudo:

sudo -u www-data /path/to/crontab-script.sh

The first thing to test before all of that, of course, is that your script actually does what it is supposed to do from the command line. If you can't run it from the command line, it will obviously not work from with cron.

share|improve this answer
    
Thank you for the thorough response. I'm aware of the two issues of running as a particular user, and with a particular environment. As such, I've formulated my own answer, which I will now post... –  Pistos Nov 18 '09 at 14:33
add comment

Well, the user is the same as the one you put in the crontab entry (or whose crontab you put it into, alternately), so that's a no-brainer. crontab(5) should give you the list of environment variables set, there's only a few.

share|improve this answer
    
In other words, you're saying there is no way to do it? Only "close enough" workarounds? –  Pistos Nov 18 '09 at 14:13
    
No, I'm saying that you can do it, using the information I provided in my answer. –  womble Nov 18 '09 at 14:28
add comment

I've never found a way to run cron jobs manually but this write-up suggests setting the same environment as the cronjob would have and running the script manually.

share|improve this answer
    
Isn't what you suggest to do what the OP wants to know how to do? –  womble Nov 18 '09 at 14:11
    
Which would be why I included the link to the write-up that describes how to do it. I didn't think it necessary to copy-paste everything here. –  oneodd1 Nov 18 '09 at 14:40
add comment

As crontab don't do the job, you'll to manipulate it's content :

crontab -l | grep -v '^#' | cut -f 6- -d ' ' | while read CMD; do eval $CMD; done

What it does :

  • lists crontab jobs
  • remove comment lines
  • remove the crontab configuration
  • then launch them one by one
share|improve this answer
1  
This doesn't necessarily do it in the same environment that cron would, though, and I thought he wanted to test only one of them. –  Falcon Momot Aug 20 '13 at 4:39
    
correct, I have been mistaken... It only run the jobs but not like cron would do ! –  Django Janny Sep 2 '13 at 19:53
add comment

you can program the job to start the next minute :)

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.