I've created new system account for cronjob on my centos 7 and set up a cronjob for it.

However my cronjob fails to run with error:

(CRON) ERROR chdir failed (/home/sysagent): No such file or directory

Currently crontab for sysagent account looks like:

15 16 * * * HOME="/tmp" && cd path/to/project_folder && ./src/mainroutine.sh | ts "[\%Y-\%m-\%d \%H:\%M:\%S]" >> /var/log/automation/sysagent.log

I've added HOME variable and cd to project folder after some investigation (used to have full path to shell script there), but it doesn't help. How to make cronjob forget about home directory? And why it's looking for it by the way?

  • 1
    Please edit your question to include the output of the following command: grep '^sysagent' /etc/passwd | awk -F: '{ print $6 }' That should print the user's home directory. – Andy Dalton May 8 '18 at 13:54
  • It outputs /home/sysagent which shouldn't be so because I've created it as system user (adduser -r). I guess just to specify -r option is not enough for making user no-login... – Vsevolod May 8 '18 at 14:01
  • Might want to try adding a HOME=/tmp line before the 15 16 * * * line. – Mark Plotnick May 8 '18 at 14:13
  • I did so on one of tries, it is the same as having it in one line with script call. – Vsevolod May 8 '18 at 14:22

On the assumption the docs are bad or wrong, a source code dive:

% rpm -qa | grep cron

... some altagoobingleduckgoing here as the URL in the RPM is broken ...

% git clone https://github.com/cronie-crond/cronie && cd cronie
% fgrep -rl 'chdir failed' .

... so that error only appears in one place, within the cron_change_user_permanently call that is called from various other places in the code ...

% grep cron_change_user_permanently **/*.c
src/do_command.c:               if (cron_change_user_permanently(e->pwd, env_get("HOME", jobenv)) < 0)
src/do_command.c:               if (cron_change_user_permanently(e->pwd, env_get("HOME", jobenv)) < 0)
src/popen.c:            if (cron_change_user_permanently(pw, env_get("HOME", jobenv)) != 0)
src/security.c:int cron_change_user_permanently(struct passwd *pw, char *homedir) {

... so in all cases the HOME environment variable appears to be used to determine where to chdir to for the user, and there is always a chdir to that directory. So you'll need to ensure that the HOME directory exists, or that HOME is properly set before cron_change_user_permanently is called (which likely happens before the shell code in your cron job is even looked at). (Or monkey patch cronie to do something else, but that's probably a really really bad idea.)

| improve this answer | |
  • Wow, that's a thorough investigation. And this definitely answers to first part of my question. So I understand right there is no way to change this behaviour without source code modification (which is not an option of course). My initial idea was to make user non login, so the user should not have $HOME env set (and I read somewhere on stack overflow that -r is the option I need to achieve that, but I can't find any confirmations to that assumption in man adduser). Which should result in error, if I guess right about cron_change_user_permanently behaviour. – Vsevolod May 8 '18 at 14:28
  • Users that run cron jobs will need a HOME directory and some level of access rights to be able to run cron jobs, though exactly how to achieve that while also preventing logins (remote? by password? ...) will vary. – thrig May 8 '18 at 15:25
  • Not having a valid home directory will not, by itself, prevent an user from logging in: usually they will just be logged in with / as the default directory instead. Having the account locked (i.e. having the password hash field in /etc/shadow contain only *) won't necessarily prevent that user's cron jobs from being executed, but will prevent any password-based logins. If you have any other login methods, it depends on their configuration: e.g. if you want an account not to be login-able by SSH keys, don't create a ~/.ssh/authorized_keys file for it. – telcoM May 8 '18 at 20:24

When cron runs a user's crontab, it'll want to start in the user's home directory. The initial value of that variable comes from /etc/passwd (in simple cases). By the time you try to override HOME in the crontab entry, cron has tried to change to ${HOME}.

| improve this answer | |
  • I like both responses but thrig's is more throughout (though the question was rather ill formed as I understand now). – Vsevolod May 8 '18 at 18:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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