1

I want to log my public ip to a file using cron. Something like this:

2021-05-17T01:11:46 99.99.99.99
2021-05-17T01:12:46 99.99.99.99
2021-05-17T01:13:46 99.99.99.99

Here's what I've cobbled together:

* * * * * { date +%FT%T | tr "\n" " "; curl https://ipinfo.io/ip -s ; echo "" ; } >> /home/mario/logs/pubip.log

It works* in at sh prompt but once I put the asterisks in front and put it into crontab -e I get the following error:

/bin/sh: 1: Syntax error: end of file unexpected (expecting "}")

OS: Ubuntu 20.04.2 LTS

*There's gotta be a more elegant way to handle the formatting. What I frankensteind feels pretty awkward.

nuifd
  • 27
  • After some more experimenting, removing the "+" argument in the date command gets rid of the error.Cron doesn't like it for some reason. Any ideas why? The same command with the "+" argument works fine from a sh prompt and in a cronjob via bash script – nuifd May 27 '21 at 11:48
  • Or just use a simpler API.. https://api.ipify.org - curl https://api.ipify.org – Fanatique May 27 '21 at 14:12

3 Answers3

0

So it turned out to be the '%' symbols. Should have read the docs more: crontab(5)

The "sixth" field (the rest of the line) specifies the command to
       be run.  The entire command portion of the line, up to a newline
       or a "%" character, will be executed by /bin/sh or by the shell
       specified in the SHELL variable of the cronfile.  A "%" character
       in the command, unless escaped with a backslash (\), will be
       changed into newline characters, and all data after the first %
       will be sent to the command as standard input.

Correct cron line that worked in the end is

* * * * * { date +\%FT\%T | tr "\n" " "; curl https://ipinfo.io/ip -s ; echo "" ; } >> /home/mario/logs/pubip.log

That said, I'll be moving this into a script just for readability's sake as @scimerman suggested.

nuifd
  • 27
-1

I couldn't reproduce your. If the command for cron is too bulky, more elegant way is to wrap it inside a separate cron script and call that from crontab:

$ cat ~/crontab.ip 
#!/bin/bash
{ date +%FT%T | tr "\n" " "; curl https://ipinfo.io/ip -s ; echo "" ; } >> ~/log.ip

and my crontab is:

$ crontab -l
* * * * * ~/crontab.ip

It should work.

  • Thanks. The script does appear to work fine. Probably similar to the reason why the command works from a shell prompt. I'll likely be doing this since the command is so bulky. For educations sake, did you try the non-script way and not get the error I got? I'd still like to know why that's not working. After some testing it appears to be because of the + symbol in the date command. Why would that not work as a cron job? – nuifd May 27 '21 at 11:47
-3

When putting commands in the cron system, you must use the full path for the command.

I.e.,
date should be /bin/date
tr should be /usr/bin/tr
curl should be /usr/bin/curl.
echo should be /usr/bin/echo

Shōgun8
  • 711
  • 2
    Couldn't find any reference to this requirement. In fact, crontab(5) lists examples without full paths. – nuifd May 27 '21 at 12:42
  • It's not a requirement - but its a strong recommendation to do so. – Jeremy Boden May 27 '21 at 13:17
  • 1
    In fact, I recommend against this. In a highly stable system that does not get regular updates - sure, it improves security a tiny bit. But in a system that is getting updates regularly, this is NOT ok. Reason #1 is that on some distributions updates sometimes change the location of a binary. This is a breaking change when you're using full paths. Also note that on one of the most stable distros - Debian - this IS an issue. Reason #2 is that this is barely a security issue for when you're using root to execute crons. root's PATH variable is hardly accessible. – Fanatique May 27 '21 at 14:17
  • Also, for echo it is generally recommended nowadays that you use the shell function, rather than the binary. In the old days it was recommended so that you use a more "portable" version. But different distributions have it in different locations nowadays - totally not "portable", and also the shell function pretty much has all the options you need on all shells. – Fanatique May 27 '21 at 14:21
  • @Fanatique, what does it have to do with security? Its ridiculous to say that not using the full path is LESS secure somehow. What if the path to echo was changed in the environment path to rootkit? Answer that. You are posting REALLY BAD information. – Shōgun8 May 28 '21 at 01:32
  • @nuifd, you're just telling the root to run certain commands. If the PATH envs aren't set to precisely what you want, then you will get unexpected results. That is why you should always use full paths; so that you get the same result every time. – Shōgun8 May 28 '21 at 01:35
  • You seem to misdiagnose the issue in the question. – Kusalananda May 28 '21 at 08:27
  • @Shōgun8 I have said nowhere in my comment that using full paths is less secure. I've said that the security it provides for root crons is not that important nowadays. If somebody/something else could change the PATH variable for the root user, then you have a lot bigger problems. I'm just saying that if you want a stable system that would not introduce breaking changes with updates - don't use full paths. Who will update them when binaries locations change? Who will update them when you switch to a different distro? Sorry to mods if this has to be moved to chat. – Fanatique May 28 '21 at 09:26
  • Since cron has its own, hard-coded PATH, many commands will only work if you use the full path to them, @Fanatique. So it is often a solution to "why is my crontab not running?". However, these are not good examples of, Shogun that since i) echo is a shell builtin, so using the full path to the binary instead is not a good idea and ii) all of the example commands you show should be in cron's path. You only need to use the full path for binaries not in /usr/bin or /bin. – terdon May 28 '21 at 09:49
  • @ tendon, you base your knowledge of cron on another post? Cron does NOT have it's own hard-coded path, you can set the paths. Please read some documentation. Here is some good documentation, where it states that */etc/crontab* is "empty by default" and to look at acancron man page for more info -> "https://www.man7.org/linux/man-pages/man8/cron.8.html. The anacron man page says that this is where you set *environment assignments*, such as PATH - > https://www.man7.org/linux/man-pages/man5/anacrontab.5.html. – Shōgun8 May 28 '21 at 10:08
  • @Shōgun8 please read the linked post more carefully. Of course you can change cron's PATH, I never said you couldn't. However, as explained in the linked post (which, by the way references the source code of the cron executable), cron has a hardcoded default PATH which does not depend on the standard PATH set in /etc/environment or any of the user-specific configuration files. So, you should either modify the PATH or use the full path to the executable when running things that are not in cron's default PATH. This is not the case for any of the commands listed in your answer. – terdon Jun 01 '21 at 15:04
  • */etc/crontab is "empty by default"* ------- This means it has no default PATH – Shōgun8 Jun 01 '21 at 15:12
  • Sigh. Again, please actually read the answers. They are linking to the actual source code of the program (cron) where you can clearly see the PATH is hardcoded. This has nothing to do with /etc/crontab or any other crontab it is about how the cron binary has been compiled. – terdon Jun 01 '21 at 16:01
  • You must speaking about the definition in pathnames.h where it defines a path as /bin:/usr/binif no other path has been selected. *IF* any other path has been selected, then it does not define those paths. So there is no assurance that those paths are hardcoded, so then you can't say that any paths are hardcoded. – Shōgun8 Jun 01 '21 at 18:54