0

I am running a script using crontab at reboot but somehow the part of the code where some file is being sent to a S3 bucket in AWS, doesn't work. I have included an initial wifi check in the same script and shows not connected to any network (in the cronjob log file), although on the Raspi's head I can see it is connected to the network. Infact the code works great if it is run from the code editor without any issues. I am wondering how to fix it.

3 Answers 3

0

Basically you can't. There are literally thousands of similar Questions on this site.

Current Linux (since 2015) uses systemd which runs processes asynchronously at boot - so you can no longer guarantee that anything is running when your script is executed. (My Pi3B+ shows network-online.target @1min 31.799s)

The only reliable solution is to write a systemd script that includes After=network.target. This unfortunately is more complex.

Some use a brute force approach and include a delay in cron scripts.

There used to be some useful guides on https://www.raspberrypi.com/ but unfortunately general Linux guides seem to have been removed so you should look at or search on https://unix.stackexchange.com/questions

There is an option in raspi-config to wait for network on boot which may work, but I haven't used and am unsure how this interacts with cron.

One Answer which may help is https://raspberrypi.stackexchange.com/a/121944/8697

1

The cause of your issue is due to the fact that cron does not have situation awareness. cron is doing the job it was designed to do, but its job does not include being aware of whether or not the network services your job needs is available.

Since you posted this question, I'll guess this is a surprise to you. It was also a surprise to me when I learned it many years ago. Today however, the situation is different; rather odd and needlessly complicated - to my way of thinking. Nevertheless, there is a solution to your issue that is not complicated: You may simply ask cron to sleep for a while until your network is available. This is simply done by structuring your @reboot job in crontab as follows:

Simple Answer:

@reboot  /usr/bin/sleep 60; <your current crontab entry> 

This command will delay the start of your cron job for 60 seconds. There is nothing magic about 60 seconds; it may be 10 seconds, or it may be 180 seconds - this will depend on how quickly your network services become available to your RPi. Play around with values until you find one that works reliably for your situation.

This is not an efficient solution - it is a simple solution. There are many alternatives to this solution; in fact your question indicates you may have implemented one in the code for your job/script by performing a wifi check. This solution will work perfectly well if you put that test in a loop (perhaps with a sleep command) that defers proceeding until the network services are available.

FWIW, in an effort to provide some additional context, my view of the bigger picture follows:

Why is this necessary, and what are other alternatives?

cron has been around for quite a long time. It was designed to schedule jobs; i.e. to cause them to be started at a specified time. It was never a cron requirement to analyze the jobs it scheduled to learn what resources they required - that was the responsibility of the user who programmed the job - as you have begun to do in your wifi check.

In Unix & Linux, starting services has always been the responsibility of init. In most modern Linux systems - since 2015 - the role of init has been filled by a program called systemd. In other words systemd controls the sequence in which services are started during the boot process, and systemd is responsible for knowing the point in time (or sequence) at which network services become available.

In fact, crond itself is started by systemd during the boot process. Consequently, since systemd - as the init system for Linux - is responsible for sequencing the start of all services (including crond and networking services), it is reasonable to expect that crond would not be started until network services were available. Unfortunately, the cognoscenti behind systemd have not done this. No one seems to know why, but the question has been asked frequently with few clear or concise answers.

To be sure, it is possible for users/admins to modify the unit file for crond to cause it to start later in the boot process - after network services become available. However, you'll first need to invest the time necessary to learn the vocabulary, syntax and design of systemd to make that change. It's not simple, but it can be done if you feel the benefits justify the investment of your time.

0

I have included an initial wifi check in the same script and shows not connected to any network

Sounds like you just want your script to do the wifi check in a loop waiting for the network to come up. Something like:

echo Waiting for wifi...
while ! wifi_check; do
  sleep 1
done
echo Got wifi, continuing

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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