Tag: python

Linux Cronjob Doesn’t Execute Valid Python Script

Linux Cronjob Doesn’t Execute Valid Python Script

I’ve been using cron to execute a Python script used by my Raspberry Pi automatic cat feeder for some time now. After coming up with another script that needs to run on a regular schedule I added a second cronjob entry into the crontab.

That’s easy enough: first, in a terminal open the crontab to reveal existing jobs:

sudo nano crontab -e

Add the cronjob to the crontab by creating a new entry:

* * * * * /home/pi/Documents/Development/CatFeeder.py
* * * * * /home/pi/Documents/Development/Maintenance/Monitoring.py

The CatFeeder.py script has been running without a hitch, while the Monitoring.py script is the one being added.

After saving the file (this is nano, so CTRL+X, Y, Enter to save and exit) I expected the job to run every 60 seconds. However, nothing seemed to be happening. The new script never successfully executed. Meanwhile, the CatFeeder.py script was running flawlessly.

The script is an executable, I made sure of that by running chmod +x Monitoring.py, so that’s not the issue. I double-checked that the script ran without errors by invoking it manually: sudo python Monitoring.py. To no surprise the script ran as expected.

If the script runs fine, and a cronjob I already have in the crontab runs fine, then what gives?

SheBang #!: Specifying the Language Interpreter

There’s a very interesting line of code, or a comment rather, that I’ve noticed floating around in most of the Python scripts I’ve seen:

#!/usr/bin/env python

My tiny brain paid this line little attention at first, “how important could it be”, I thought. Enter the shebang #! character sequence. This sequence is treated as an interpreter directive by program loaders such as cron. That is, it specifies which interpreter to use when executing the script. 

Without this line of code the cronjob will not automatically use Python as the interpreter and will fail to execute the script. Add this line to the beginning of your script and watch your cronjob flourish!

What Was That You Said About the Script Running Without Issue?

It was previously mentioned that the Monitoring.py script executed without issue when invoked manually, like so:

sudo python Monitoring.py

This does indeed run without issue, even without the shebang #! line added to the file. However, the script name is preceded with the interpreter to use, python. If we execute the script a different way we’ll more accurately see what’s happening when the cronjob runs it.

In the terminal use the ./ command to execute the script:

./Monitoring.py

Without the shebang #!, Python is not used as the interpreter, and errors are shown in the terminal:

Now add the shebang #!/usr/bin/env python at the beginning of the script and execute it again. Unless your script has other syntactical problems it should run successfully.

Hi, I’m Sam.
I’m a programmer and a DIYer. When I’m not finding things to build I enjoy cooking, hiking, camping and traveling the world with my best friend. Say Hello!

Controlling a Servo Motor with Gmail and Raspberry Pi

Controlling a Servo Motor with Gmail and Raspberry Pi

You covered part one and part two (good work!), or maybe you didn’t and you found yourself here anyway (welcome). Part three is focused on the servo motor, primarily making it spin. Later in part four we’ll wrap things up by connecting it to the dispenser.

As always, let’s start with what it is we’re trying to accomplish here:

  • Connect the servo motor to the Raspberry Pi’s GPIO header pins
  • Write some code to make that motor functional
  • Tie in the GmailWrapper.py script we wrote in part two so the motor spins when the right email lands in your inbox

Here we go!

Connecting the Servo Motor to the Raspberry Pi

The servo motor has power, ground and control wires. Connect your male-to-female jumper cables to the servo. Now, using the GPIO diagram below as reference, connect the wires to the Pi’s GPIO headers as follows:

Note: this diagram is for Raspberry Pi’s with 40 pin GPIO, but the below works with 26 pin GPIO as well.

  • power connects to header pin 2 (5v power)
  • ground connects to header pin 6 (Ground)
  • control connects to header pin 12 (GPIO18)

GPIO Pinout Diagram

Here’s what mine looks like (don’t mind the zip tie):

Servo Connecting to Pi
Servo Connecting to Pi’s GPIO

 

Writing Code to Make the Servo Motor Spin

Before getting started, let’s update our Pi to the latest packages and install the GPIO library. Run this in the terminal:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install rpi.gpio

We’re all set. In the terminal, create a new python script using nano: sudo nano CatFeeder.py

Within the CatFeeder.py script, add the following code:

Save and exit the nano editor: CTRL+X, then Y, then Enter. Moment of truth, time to make that servo move! Let’s drop back into the Python interpreter, in the terminal:

I hope that went smooth for you, because I just got really excited. Welcome to physical computing! You moved a physical object with code, hell yeah.

GmailWrapper, Meet CatFeeder: Putting it all Together

Alright, so we’ve created a way to read emails, and we’ve created a way to move a servo motor. Now we need to combine the two so the servo motor moves when we read emails.

Open CatFeeder.py in nano and add the highlighted lines of code: sudo nano CatFeeder.py 

Save and exit the nano editor: CTRL+X, then Y, then Enter. As always, let’s give it a test. Send yourself an email with the subject feed cats. Drop into the python interpreter once the email arrives:

Did it work? It did? Excellent! If it didn’t, don’t be discouraged! Python’s support community is huge, you’ll find the answer. Plus, you can always leave a comment below.

Scheduling a Cron Job to Run Our Script Regularly

We have code to move our servo motor when the correct email lands in our inbox, but it currently only runs when we physically tell it to. Let’s fix that by setting up a cron job to run our script every 60 seconds.

In order for the cron job to execute our script, we need to make our script executable. This is done by issuing the following command in the terminal: chmod +x CatFeeder.py

Now we’ll add the cron job. In the terminal: crontab -e. Add the following after the very last commented line (comments start with #):

* * * * * /path/to/your/script/CatFeeder.py

We’re in the nano editor, so save and exit: CTRL+XYEnter. Easy as Pi (sorry). A job is now running every 60 seconds with the sole task of looking for emails and feeding cats. Don’t believe me? Give it a shot, send yourself an email with the subject feed cats.

A nicety of cron jobs is they’ll continue running automatically if your Pi ever restarts.

Scheduling an Email to be Sent Regularly

We have the code, we have the cron job. Sending an email on demand will cause the servo motor to spin, but what about spinning it on a schedule? That’s where we’ll make use of IFTTT. IFTTT stands for if this then that and allows you to connect two disparate systems based on what they call a “recipe” (trigger and action). For our purpose, we need the clock to trigger an email to be sent (action). Here’s what to do:

  1. Setup an account if you haven’t already
  2. Use IFTTT website or download the app to your phone and log in
  3. In the My Applets section, add a new applet
  4. You’ll see a screen saying if +this then that: click the +this button, then select the Date & Time service.
  5. Select the Every day at trigger, and select the time you’d like the cat feeder to activate, then hit next
  6. Now you’ll see +that, click it and find the Gmail service. You’ll need to connect the service to your Gmail account. Once finished, set the action to Send yourself an email with the subject Feed cats.
  7. Hit next, then Finish

There you have it, every day at the time you specified an email will be sent to your account. If you had any issues setting up the IFTTT recipe, check out this post for a really nice and in-depth walk-through.

Having fun? Here’s Other Ways to Send an Email

Alexa

Alexa integrates nicely with IFTTT. In the IFTTT app, create a new recipe with the trigger (+this) connecting to Alexa. You’ll need to connect the service like you did for Gmail. Once connected, set the action (+that) to send an email, like we did in the previous section. 

Hands free feeding at your ready: Alexa, trigger the cat feeder.

The DO Button App

Created by the IFTTT team, the DO Button app and accompanying widget provides a straightforward way to trigger the action. You! You’re the trigger. You setup a recipe, same as before, except you’ll notice there’s no +this. You are the +this. You open the app and click the button, it then triggers an email. This app can also be configured to show on your iPhone or Androids home screen, so triggering the email is even easier.

Conclusion and Next Steps

Part one has goals and items covered, part two has Gmail automation down, and part three provided the spinning of the motor. A lot has been done so far, we’re nearly there. Up for part four? That’s where I’m headed to connect the Pi and motor to the dispenser.

Hi, I’m Sam.
I’m a programmer and a DIYer. When I’m not finding things to build I enjoy cooking, hiking, camping and traveling the world with my best friend. Say Hello!

Reading Gmail with Raspberry Pi and IMAPClient

Reading Gmail with Raspberry Pi and IMAPClient

In part one we covered the basics of what we’re trying to build, and what you’ll need to get started. Here in part two we’ll be playing with some python code to interact with our Gmail account using IMAPClient. Later on, part three is focused on the servo motor, while part four connects it all to the food dispenser.

The goal of this part?

  • Setup your Gmail Account with 2-step authentication for a secure way to interact with it through code. 
  • Write some code to interrogate your inbox for an email and mark it as read when found using the IMAPClient library.

Let’s get to it!

Preparing Your Gmail Account with 2-step Authentication

This is not strictly necessary, but a good security practice. If you don’t mind your credentials being in plain text in your code, feel free to skip ahead.

Since we’re going to be using email as the trigger, we’ll need a way to securely log into our Gmail account from code. You could store your credentials in plain text within the code we write, but I strongly discourage that. Instead, make use of Gmail’s two-step authentication and app passwords

I created a new Gmail account for this purpose.

  1. Log into your gmail account
  2. Navigate to the Sign-in and security page
  3. Under the Signing in to Google section, click the 2-Step Verification menu, then follow the instructions to enable 2-Step Verification
  4. Back in the Sign-in and security page right under the 2-Step Verification button you’ll see App passwords
  5. Generate a password

The password you generated can be used to log into your Gmail account. We don’t need it right this second, but we’ll be using it to scan for an email that demands we feed the cats!

Writing Code to Read Your Gmail

Now that we have a Gmail account ready to rock, let’s write some code to interrogate it. We’re going to be using the IMAPClient python library for this purpose, and we’ll wrap the calls to this client in our own Python class.

Install IMAPClient now from the terminal: sudo pip install imapclient

Create the GmailWrapper.py Script

Now let’s create our Gmail wrapper class: nano GmailWrapper.py. Within the GmailWrapper.py script, add the following code:

Save and exit the nano editor: CTRL+Xthen Y, then Enter.

Verifying the GmailWrapper.py Class Works

Let’s do a test: our script is going to log into the Gmail account, search for email with a specific subject, then mark it as read. Before running the code, send yourself an email with the subject feed cats (the search is case-insensitive, by the way).

We’re going to use the Python interpreter to run our tests. In your terminal make sure you’re in the same directory as the GmailWrapper.py class we just created, then:

If everything went as planned your email should now be marked as read. Pretty neat!

Conclusion and Next Steps

Part one set the goals and outline. Now with part two wrapped up we have the ability to discern whether or not an email exists. With this power we can trigger certain events, such as spinning a servo motor. That’s exactly what we’re going to do in part three, I’ll meet you there.

Later on in part four we’ll be attaching the Pi and servo motor to the dispenser, but before we make anything permanent let’s get that servo spinning.

Hi, I’m Sam.
I’m a programmer and a DIYer. When I’m not finding things to build I enjoy cooking, hiking, camping and traveling the world with my best friend. Say Hello!