0

I'm running a script provided by rehmatworks to install a LetsEncrypt certificate, which (in addition to the initial install) sets up a monthly cronjob to auto renew. Everything installs fine, however, the cron job is failing, and I can't seem to figure out why.

Here is the cron job (from root 'crontab -e'):

@monthly "sudo service nginx-sp stop && yes | letsencrypt --standalone renew &>/dev/null && service nginx-sp start && service nginx-sp reload"

Which fails with a not found error:

/bin/sh: 1: sudo service nginx-sp stop && yes | letsencrypt --standalone renew &>/dev/null && service nginx-sp start && service nginx-sp reload: not found

Running directly from the command line work fine, however:

sudo service nginx-sp stop && yes | letsencrypt --standalone renew &>/dev/null && service nginx-sp start && service nginx-sp reload

Any ideas why this works from command line, but not via cron?

  • Your first code sample shows an unbalanced quote; assuming it's actually balanced then the issue is likely that "command args" is not the same thing as command args i.e. the shell (sh) is seeing the quoted string as a single command rather than a command plus its arguments. Aside from that, remove sudo and run it from root's crontab if elevated permissions are required. – steeldriver May 07 '18 at 22:14
  • ... you will also need to change &>/dev/null (which is a bashism) to >/dev/null 2>&1 (or change the crontab's shell from /bin/sh to /bin/bash) – steeldriver May 07 '18 at 23:13
  • @steeldriver I think you got it. The trick is changing cron to 'SHELL=/bin/bash', and adding 'PATH=/sbin:/bin:/usr/sbin:/usr/bin' variables. However, now getting an error 'No such file or directory'. – Douglas McDonald May 07 '18 at 23:45
  • @steeldriver I should clarify. With quotes using bash I get error 'No such file or directory'. Without quotes no error — but can't confirm that the renew is working. Might be rate limited? idk. I'll do more testing. In the meantime, if you want to write an answer I'll mark it as correct. – Douglas McDonald May 08 '18 at 00:06

3 Answers3

1

Try to specify the entire path to the binaries that you're using. I guess they aren't found since the $HOME variable or $PATH should be different to the root and user.

If what I said is the problem, the source of it must be the location of letsencrypt binary, probably not found by root

Manel Reis
  • 11
  • 2
  • Good suggestion. I tried it. Works from command line, but unfortunately, still getting the 'not found' error from cron. Here is the revised command/error: /bin/sh: 1: sudo /usr/sbin/service nginx-sp stop && yes | /usr/bin/letsencrypt --standalone renew &>/dev/null && /usr/sbin/service nginx-sp start && /usr/sbin/service nginx-sp reload: not found – Douglas McDonald May 07 '18 at 20:40
  • run this command twice once as user and once as root: whereis service nginx-sp letsencrypt – WiKrIe May 07 '18 at 20:51
  • I'm running everything as root to (hopefully) avoid any user errors. Here is the output: letsencrypt: /usr/bin/lets encrypt /etc/letsencrypt /usr/share/man/man1/letsencrypt.1.gz – Douglas McDonald May 07 '18 at 20:57
  • Did you try the /etc/letsencrypt instead of the /usr/bin/letsencrypt on the crontab? – Manel Reis May 07 '18 at 21:20
  • @ManelReis My understanding is that /etc/letsencrypt is source and not binary. But I tried it regardless. Works from command line, not from cron. I also added full path to yes (/usr/bin/yes) just in case – no luck. – Douglas McDonald May 07 '18 at 21:39
  • @ManualReis To simplify, I tried just running 1) sudo service nginx-sp reload and 2) sudo /usr/sbin/service nginx-sp reload and 3) /usr/bin/sudo /usr/sbin/service nginx-sp reload. All not found. wth?! – Douglas McDonald May 07 '18 at 22:00
  • @DouglasMcDonald i'm not familiarized with service. In particular with the that one, I'm sorry I couldn't help – Manel Reis May 07 '18 at 22:14
  • @ManelReis No sorrows. Thank you so much!!! Really appreciate the help. I think you were half right. But the bigger issue is that 'sh' shell doesn't support commands in quotes, so no matter what paths were defined, it was doomed to fail. In addition to changing the SHELL to bash, I also added PATH variables. – Douglas McDonald May 07 '18 at 23:57
  • so it looks like your nginx-sp whatever this sp means is not working propper. can you check it with whereis nginx-sp to find out where is this nginx. – WiKrIe May 08 '18 at 07:04
  • I think sp stands for ServerPilot and since it is an argument for service I don't know if whereis will give you a relevant output – Manel Reis May 08 '18 at 07:31
  • The bigger issue is that it is running in 'sh' and not 'bash'. sh doesn't like the command in quotes. So anything would be 'not found'. Changing it to bash seems to have solved the problem (which steeldriver pointed out above in comments). – Douglas McDonald May 10 '18 at 19:57
1

This is already reported as issue to script provider:

https://github.com/rehmatworks/serverpilot-letsencrypt/issues/8

So you should wait for an answer there. It is not easy to give you a quality answer if we do not know the total background of the system, looks like some special environment.

Update: Issue is solved now by Scriptowner on Github, please checkout the Github. rehmatworks commented 12 hours ago

Solution: Please reclone the script and you will be able to do much more with great ease.

sorry
chris

WiKrIe
  • 1,939
  • Thanks Christian. Yes. I'm aware of that. I was one of the posters of the issue. Unfortunately not getting any reply from the dev (been a couple weeks now), and I suspect that it is a general cron issue rather than a script issue. – Douglas McDonald May 07 '18 at 20:44
0

Update: rehmatworks has since updated the original script to address this issue.

Thanks to @steeldriver comments above, I've learned that the main problem is:

  • The crontab should be run using 'bash' (not the default 'sh'), because:
    • &>/dev/null is bash syntax ('sh' would be >/dev/null 2>&1).
    • sh does not recognize commands in quotation marks (produces 'not found' error).
  • The crontab should define the default PATH variables.
  • If the crontab is run under root, then don't need to use 'sudo' (although probably doesn't hurt).

To edit the root crontask, use sudo crontab -e -u root. Final looks like this:

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin

@monthly service nginx-sp stop && yes | letsencrypt --standalone renew &>/dev/null && service nginx-sp start && service nginx-sp reload
#

So far, seems like it works (but please confirm by reviewing logs).

Note: Not tested, but in terms of fixing the original install script, without having to define the shell environment separately, it's possible you could wrap the cron command in a bash subshell to make sure it gets run in bash (per askubuntu SE answer):

bash -c "bashcommand"