13

I would like to set up a cron job that recusively does a chmod/chown on a directory (the dropbox directory).

This works when I execute the commands manually like:

sudo chown -R $USER ~/Dropbox
sudo chmod -R u+rw ~/Dropbox

I tried to convert it into a cron job like this:

10      *       *       *       *       sudo chown -R $USER ~/Dropbox

But it doesn't seem to do the job.

How to do this?

user9517
  • 115,471
  • 20
  • 215
  • 297
tvgemert
  • 277
  • 1
  • 2
  • 7

5 Answers5

17

sudo should almost never be used in scheduled tasks. It expects to be able to talk to a terminal, and requires specific flags to avoid trying to do so.

Create your cron job as root (in /etc/crontab - Note that the format of this file is slightly different: minute hour mday month wdayusercommand) instead.
This also has the benefit of working on systems where sudo isn't installed.

voretaq7
  • 79,879
  • 17
  • 130
  • 214
  • Thanks! I created this, but I'm still unsure about it. I didn't get the expected result: `55 * * * * root chown -R somename ~/Dropbox` – tvgemert Feb 16 '12 at 16:57
  • 3
    `somename` could be anywhere; it is a relative path. Secondly, `~` is only understood by the shell; use `$HOME`. Use a command like this: `chown -R /some/path/somename $HOME/Dropbox` (this will use `root`'s home directory...) – Mei Feb 16 '12 at 18:18
  • @David: `somename` is not a path, but the user name (and should also contain the group name: `somename:somegroup`) ;) – knittl Feb 16 '12 at 19:10
  • 5
    @tvgemert What David said above (and in his answer) regarding paths/relative paths/symbolic paths (`~`) is ***CRITICALLY IMPORTANT*** -- Please spend some time with the cron and crontab man pages and be sure you understand what's going on (if in doubt, create a cron job that does `echo "what you want to do" > /tmp/what-i-would-run` and look at the results to be sure they're sane -- MUCH less chance of destroying the universe.) – voretaq7 Feb 16 '12 at 19:11
  • Thank for the useful tips, gave me more insight already! – tvgemert Feb 16 '12 at 19:57
13

You want your root cron script (edit by running sudo crontab -e) to be:

 55 * * * * /bin/chown -R somename /home/somename/Dropbox && /bin/chmod u+rw /home/somename/Dropbox

Assuming the user is named somename and that /home/somename/Dropbox is the full path of your Dropbox directory. As root user, ~ goes to /root.

dr jimbob
  • 399
  • 2
  • 12
  • 1
    Thanks for the clear answer! I think this shows me some of the missing links I was looking for. I'll test it first thing tomorrow :) – tvgemert Feb 16 '12 at 19:55
  • Tested it, and it's working! – tvgemert Feb 17 '12 at 11:14
  • 2
    Great; glad its working. The lessons are (a) don't expect environmental variables like `$PATH` to be defined equivalent to those of a signed in user in a cronjob (e.g., on my linuxbox $HOME is defined, but $PATH is set to `/usr/bin` and `/bin` from crontab and $USER is not defined; so in this case you didn't need to specify `/bin` before chmod/chown), (b) avoid `sudo` in scripts (run cron task as `root` user), (c) as root user `$HOME` will refer to /root not your normal user, (d) `~` should be avoided in cron scripts (by default run as `#!/bin/sh`. – dr jimbob Feb 17 '12 at 12:57
  • I'd also recommend putting in a script per David's advice if you ever do anything more complicated than this; a script seems overkill for a combination of a chmod / chown. However, if you begin applying to other users's Dropboxes or other directories or decide to only run on recently changed files (e.g., result of `find`), etc than it makes sense to put in a script. – dr jimbob Feb 17 '12 at 13:02
6

Two issues:

1) Paths aren't normally set up in cron the same way they are when you log in. Try /usr/bin/sudo /bin/chown ... (or whatever the right paths are to those programs on your system).

2) sudo normally asks for your password, or may otherwise not be happy running noninteractively. I suggest you put the commands in root's crontab without the sudo instead, then the commands run as root.

pjc50
  • 1,720
  • 10
  • 12
6

There are multiple issues with your crontab:

10 * * * sudo chown -R $USER ~/Dropbox

The issues:

  • sudo should not be used here; it requires terminal input
  • chown should be fully specified (i.e., /bin/chown)
  • USER as an actual variable may not exist; some systems use LOGNAME
  • ~ (tilde) will only be recognized by a shell - a bare chown will not understand it
  • specifying HOME in root's crontab goes to root's home

I think I'd actually script it:

#!/bin/bash

# FILE: /usr/local/bin/myscript

USER=$1
eval chown -R $1 ~$1/Dropbox
eval chmod -R u+rw ~$1/Dropbox

(The eval is needed to convert ~$1 to ~user then to /home/user.)

Run this script from root's crontab:

# root's crontab
10 * * * /usr/local/bin/myscript someuser
Mei
  • 4,590
  • 8
  • 45
  • 53
0

As an alternative, you might be able to enable ACL support and use setfacl to achieve the same/similar result.

Ryan D
  • 21
  • 2