0

I have this cron scheduled:

0 * * * * ping -D -O -c 3492 8.8.8.8 | grep received > /home/user/.direc/packet_drops.txt

The command works fine when run manually and exports to the .txt file fine after the ping completes.

When run in the cron, the file remains empty. I have tried the manual command and the cron under the same user, same issue.

What am I missing? I've tried redirecting error output too, and it still remains empty.

5
  • Add full path of ping+grep commands ?
    – steve
    May 17, 2020 at 18:53
  • Have you checked your logs? Not sure about where to look on your system; possibly /var/log/cron or, if it's a systemd-based version, via journalctl.
    – fra-san
    May 17, 2020 at 20:08
  • @fra-san The log just says: May 17 23:00:01 localhost CROND[6755]: (user) CMD (ping -D -O -c 3492 8.8.8.8 | grep received > /home/user/.direc/packet_drops.txt)
    – Zeno
    May 18, 2020 at 3:28
  • AFAIK (possibly not always true, depending on cron's implementation) both permission (related to writing to a file) and binary-not-found errors should be logged. If we rule them out, a wild guess could be that, when you look at the file, the current job execution has already truncated it (it happens as soon as the job starts). You should be able to check this by appending (>>) to packet_drops.txt, instead of truncating (>) it.
    – fra-san
    May 18, 2020 at 8:44
  • @fra-san That seems to be it. It's appending now. I'll just need to figure out a way to clear the file before each write.
    – Zeno
    May 19, 2020 at 2:35

2 Answers 2

0

As noted in comments to your question, the likely reason your /home/user/.direc/packet_drops.txt file was empty when you looked at it is because it had already been truncated by the next execution of your cron job.

The pipeline is set up as soon as the job starts, and redirection is performed as part of that initial setup. ping is started every one hour and runs for 3492 seconds, thus giving you just a (theoretical) 108 seconds hourly window for reading packet_drops.txt before it gets truncated.

A way to only have a log file overwritten when a long-running job terminates (as you seemed to ask for in a comment) is to print its output to a temporary file and replace the destination file when the job ends.

It is easier to manage it as a script:

#!/bin/sh

trap 'rm -f -- "$tmpfile"' EXIT
tmpfile=$(mktemp)
ping -D -O -c 3492 8.8.8.8 | grep received >"$tmpfile"
cat -- "$tmpfile" >/home/user/.direc/packet_drops.txt

and define a simpler cron job (it has less ways to fail and is thus easier to debug):

0 * * * * /path/to/script

Alternatively, to keep the brevity of a one-liner, you may leverage awk's ability to manipulate files:

ping -D -O -c 3492 8.8.8.8 | awk -v file=/h..s.txt '/received/ { print >file }'

(File name shortened only for readability of this code block).

This AWK script still truncates the output file, but it only does it when a line matching received is found in the input data.

0

Crontabs have a minimal set of environment variables. It is possible that the cronjob can't find the ping or grep command. You can check your environment variables in a cronjob with a simple command:

* * * * * env &> /tmp/cron-env.txt

Wait until this job run once and remove it again. Search in the output for the PATH variable and check if the path for the ping and grep command is contained.

You can find the path for these commands with:

whereis <command>

If they are not included you can add PATH variables to your cronjob:

PATH=/bin:/usr/sbin:/usr/bin:/sbin:
* * * * * some-cron-job
2
  • Ping is in /usr/bin for me, and the environmental variables does contain that. I verified it with your cron test.
    – Zeno
    May 18, 2020 at 3:27
  • @Zeno did you tried to add /usr/bin to you PATH variable in the conrojob?
    – Jaaakob
    May 18, 2020 at 9:10

This site is temporarily in read-only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .