mollerhoj
mollerhoj

Reputation: 1336

Why I've got no crontab entry on OS X when using vim?

I would like to use cron on my Mac. I choose it over launchd, because I want to be able to use my new knowledge on Linux as well. However, I cannot seem to get the crontab -e command to work. It fires up vim, I enter my test job:

0-59 * * * * mollerhoj3 echo "Hello World"

But after saving and quitting (:wq),

crontab -l

says:

No crontab for mollerhoj3

What am I doing wrong?

Upvotes: 78

Views: 126624

Answers (14)

Andy
Andy

Reputation: 11995

The use of cron on OS X is discouraged. launchd is used instead. Try man launchctl to get started. You have to create special XML files that define your jobs and put them in a special place with certain permissions.

You'll usually just need to figure out launchctl load

https://www.unix.com/man-page/osx/1/launchctl/

http://nb.nathanamy.org/2012/07/schedule-jobs-using-launchd/

Edit

If you really do want to use cron on OS X, check out this answer: https://superuser.com/a/243944/2449

Upvotes: 22

Keith Thompson
Keith Thompson

Reputation: 263537

DISCLAIMER: I am not a Mac user. However, I have used crontab a great deal on Linux and similar systems. I presume that crontab on Mac works similarly.

A number of answers and comments suggest using an editor other than vim. That's fine, but there's no good reason that vim shouldn't work.

The cron system maintains a crontab for each user. The location of that file is unimportant; only the crontab implementation needs to know about it. cron provides an interface that allows users to request updates to their own crontabs.

The crontab -e command performs the following steps:

  • Copy the user's crontab to a temporary file.
  • Invoke the editor ($VISUAL or $EDITOR) on that temporary file.
  • When the editor command terminates, copy the temporary file back to the user's crontab (after doing some sanity checks).
  • Reload the user's crontab.

The vim editor, when you use it to edit a file, usually creates a new file with the same name. This shouldn't matter. The crontab -e command creates a temporary file, waits for the user to edit it, and then re-reads the temporary file by name. It doesn't keep the temporary file open while the user is editing it. If the Mac crontab implementation does this, I would argue that it's buggy. I'll also note that the original poster did not mention the "crontab: temp file must be edited in place" message; that was mentioned in a comment.

The most plausible explanation I can think of is that the OP was using gvim or something similar. gvim is a GUI version of vim, and if you invoke it from a shell prompt you'll get a new prompt immediately; it launches a GUI editor that runs in the background. If you use crontab -e and it tries to use gvim to edit the temporary file, then crontab will see the editor command terminating immediately, and it won't see any updates.

In fact, I was able to reproduce the problem by invoking

VISUAL=gvim EDITOR=gvim crontab -e

on a Linux system. (Again, I'm not a Mac user, and there might be some Mac-specific weirdness that I'm missing.)

A number of other answers and comments suggest using a different editor. That shouldn't be necessary. Any correctly working text editor should work with crontab -e -- as long as the editor command doesn't terminate until after the temporary file is updated. I've always had vim (or vi or nvi) as my default editor, and I've never had a problem using it with crontab.

The crontab line in the question:

0-59 * * * * mollerhoj3 echo "Hello World"

appears to be intended for a system crontab The first 5 fields specify the schedule, and the 6th is the user name. A normal user crontab does not have this 6th field, since the crontab command keeps track of the owner (the account that ran the crontab command). 99% of the time, you don't need to worry about system crontabs. Even root can use the crontab command to install a user crontab for the root account. However, this alone doesn't explain the problem seen by the OP; the syntax is valid for a user crontab, but it will attempt to invoke a command called mollerhoj3 with arguments echo "Hello World". That will cause an error when the command is scheduled, not when the crontab is created or updated.

Finally, a bit of advice that doesn't address the original question. Using crontab -e can be slightly dangerous, since it's easy to damage or destroy your crontab without meaning to. Instead, I suggest keeping a file in your home directory (possibly maintained in a version control system) and applying the contents of that file using crontab filename. For example, you might create and edit $HOME/.crontab, and run crontab $HOME/.crontab after updating it.

The question is over 9 years old, but the original poster is still more or less active (but may not have the same system).

Upvotes: 0

pskt
pskt

Reputation: 9

@Hanzaplastique answer in this comment worked for me: export EDITOR=nano

Upvotes: -1

mollerhoj
mollerhoj

Reputation: 1336

I did 2 things to solve this problem.

  1. I touched the crontab file, described in this link coderwall.com/p/ry9jwg (Thanks @Andy).
  2. Used Emacs instead of my default vim: EDITOR=emacs crontab -e (I have no idea why vim does not work)

crontab -lnow prints the cronjobs. Now I only need to figure out why the cronjobs are still not running ;-)

Upvotes: 7

Achraf
Achraf

Reputation: 1530

Use another text editor

env EDITOR=nano crontab -e 

or

env EDITOR=code crontab -e 

Upvotes: 0

Johandry
Johandry

Reputation: 121

Other option is not to use crontab -e at all. Instead I used:

(crontab -l && echo "1 1  * * *  /path/to/my/script.sh") | crontab -

Notice that whatever you print before | crontab - will replace the entire crontab file, so use crontab -l && echo "<your new schedule>" to get the previous content and the new schedule.

Upvotes: 2

user9652688
user9652688

Reputation:

The error crontab: temp file must be edited in place is because of the way vim treats backup files.

To use vim with cron, add the following lines in your .bash_profile
export EDITOR=vim
alias crontab="VIM_CRONTAB=true crontab"

Source the file:
source .bash_profile

And then in your .vimrc add:
if $VIM_CRONTAB == "true" set nobackup set nowritebackup endif

This will disable backups when using vim with cron. And you will be able to use crontab -e to add/edit cronjobs.

On successfully saving your cronjob, you will see the message:
crontab: installing new crontab

Source:
http://drawohara.com/post/6344279/crontab-temp-file-must-be-edited-in-placeenter link description here

Upvotes: 2

mirageglobe
mirageglobe

Reputation: 3124

The above has a mix of correct answers. What worked for me for having the exact same errors are:

1) edit your bash config file

$ cd ~ && vim .bashrc

2) in your bash config file, make sure default editor is vim rather than vi (which causes the problem)

export EDITOR=vim

3) edit your vim config file

$cd ~ && vim .vimrc

4) make sure set backupcopy is yes in your .vimrc

set backupcopy=yes

5) restart terminal

6) now try crontab edit

$ crontab -e

10 * * * * echo "hello world"

You should see that it creates the crontab file correctly. If you exit vim (either ZZ or :wq) and list crontab with following command; you should see the new cron job. Hope this helps.

$ crontab -l

Upvotes: 0

ShaneMit
ShaneMit

Reputation: 191

As the previous posts didn't work for me because of some permissions issues, I found that creating a separate crontab file and adding it to the user's crontab with the -u parameter while root worked for me.

sudo crontab -u {USERNAME} ~/{PATH_TO_CRONTAB_FILE}

Upvotes: 1

Cao Manh Dat
Cao Manh Dat

Reputation: 2112

Just follow these steps:

  1. In Terminal: crontab -e.
  2. Press i to go into vim's insert mode.
  3. Type your cron job, for example:

    30 * * * * /usr/bin/curl --silent --compressed http://example.com/crawlink.php
    
  4. Press Esc to exit vim's insert mode.

  5. Type ZZ to exit vim (must be capital letters).
  6. You should see the following message: crontab: installing new crontab. You can verify the crontab file by using crontab -l.

Note however that this might not work depending on the content of your ~/.vimrc file.

Upvotes: 192

user3130043
user3130043

Reputation: 41

In user crontab (crontab -e) do not put the user field.

Correct cron is:

0-59 * * * * echo "Hello World"

Syntax with user field is for /etc/crontab only:

0-59 * * * * mollerhoj3 echo "Hello World"

Upvotes: 4

Dave Meybohm
Dave Meybohm

Reputation: 651

NOTE: the answer that says to use the ZZ command doesn't work for me on my Mavericks system, but this is probably due to something in my vim configuration because if I start with a pristine .vimrc, the accepted answer works. My answer might work for you if the other solution doesn't.

On MacOS X, according to the crontab manpage, the crontab temporary file that gets created with crontab -e needs to be edited in-place. Vim doesn't edit in-place by default (but it might do some special case to support crontab -e), so if your $EDITOR environment variable is set to vi (the default) or vim, editing the crontab will always fail.

To get Vim to edit the file in-place, you need to do:

:setlocal nowritebackup

That should enable you to update the crontab when you do crontab -e with the :wq or ZZ commands.

You can add an autocommand in your .vimrc to make this automatically work when editing crontabs:

autocmd FileType crontab setlocal nowritebackup

Another way is to add the setlocal nowritebackup to ~/.vim/after/ftplugin/crontab.vim, which will be loaded by Vim automatically when you're editing a crontab file if you have the Filetype plugin enabled. You can also check for the OS if you're using your vim files across multiple platforms:

""In ~/.vim/after/ftplugin/crontab.vim
if has("mac")
  setlocal nowritebackup
endif

Upvotes: 42

Roobie Nuby
Roobie Nuby

Reputation: 1439

Difference between cron and launchd

As has been mentioned cron is deprecated (but supported), and launchd is recommended for OS X.

This is taken from developer.apple.com

Effects of Sleeping and Powering Off

If the system is turned off or asleep, cron jobs do not execute; they will not run until the next designated time occurs.

If you schedule a launchd job by setting the StartCalendarInterval key and the computer is asleep when the job should have run, your job will run when the computer wakes up. However, if the machine is off when the job should have run, the job does not execute until the next designated time occurs.

All other launchd jobs are skipped when the computer is turned off or asleep; they will not run until the next designated time occurs.

Consequently, if the computer is always off at the job’s scheduled time, both cron jobs and launchd jobs never run. For example, if you always turn your computer off at night, a job scheduled to run at 1 A.M. will never be run.

Upvotes: 8

Michael Campbell
Michael Campbell

Reputation: 2072

I've never had this problem, but I create a ~/.crontab file and edit that (which allows me to back it up, Time Machine or otherwise), then run

crontab ~/.crontab

Has worked for me for 20+ years across many flavors of unix.

Upvotes: 74

Related Questions