crontabs outside /var/spool/crontabs with SysV cron

SysV cron (as found on e.g. Solaris and derivatives) works a bit differently than vixie/ISC cron in regards to crontabs other than a user’s self-modifiable crontab. Rather than reading /etc/cron.d/* and merging them into a system crontab (where the time spec must be followed by a username), a directory exists at /etc/cron.d/crontabs where crontabs named for a user can be placed by an admin, and those jobs will be run as the named user.

You can actually create these per-user system crontabs on SysV systems using the cron module like: cron: cron_file="crontabs/<user>" ... but unfortunately the cron module makes the assumption that if you are using the cron_file param, the file should be in the <timespec> <user> <command> format, whereas in SysV cron, these per-user system crontabs should be in the <timespec> <command> format.

I’m happy to provide a PR implementing a fix for this, but I need to know what the preferred implementation would be. Here are a few ideas:

  • Add a new boolean to cron like include_user controlling the inclusion of the user field, that defaults to an automatic value based on the use of cron_file but can be forced on or off.
  • Check if (ansible_os_family == 'Solaris' and cron_file.startswith('crontabs/')) and don’t include the username field if true.
  • Add a new boolean to cron like use_system_dir that, if set, in the absence of the cron_files param, will edit files in /etc/cron.d/crontabs/<user>.

And finally, I think I like this one best because it’s the cleanest and most broadly applicable:

  • Add a new param to cron like spool_dir that, if set to a directory, overrides /etc/cron.d as the directory in which crontabs will be created, AND:
  • If cron_file is set, create the file as <spool_dir>/<cron_file> and use the <timespec> <username> <command> format
  • If cron_file is unset, create the file as <spool_dir>/<user> and use the <timespec> <command> format.

Thanks,
–nate

Even on vixie/isc modified crons you can still have 'user crons',
normally in /vars/spool/crontabs, so this would be useful for all
implementations, i believe a 'user_cron=yes/no(default) might be the
simplest way to signify this. Most crons I've used will just pass it
to crontab -u <user> and create the file in the appropriate directory,
w/o need of specifying it (my Solaris is VERY rusty, so I do not
recall if the option is the same there).

Hey Brian,

Omitting cron_file on Solaris already correctly does what you’re describing, it uses the crontab command to modify the user’s crontab in /var/spool/cron/crontabs (both vixie and SysV cron store them in this directory). I’m trying to accomplish something slightly different.

The /etc/cron.d/crontabs user crontabs are named per-user like /var/spool/cron/crontabs, but differ in that they are owned by root and not user-modifiable. They are edited by hand, not with the crontab command. This user immutability the same reason I use cron_file on Linux to create cron jobs (so they can’t be modified by the user for which I’m creating them). The problem is that unlike vixie cron’s /etc/cron.d/*, SysV cron doesn’t have any other way to create crontabs that the user can’t modify (other than the monolithic /etc/crontab, which vixie cron also has).

–nate

ah, sorry for the confusion, still this seems like a useful addition.

I’m a little confused. The current default behavior without cron_file set is to do what user_cron=yes would do. I am not sure what the desired action would be if user_cron=no? It seems to overlap with cron_file unless I misunderstand what user_cron should do.