Summary
I've got a python script that writes a row to a sqlite3 database. I would like to run it with crontab, but can't get it working.
What I've tried so far
crontab -l
* * * * * /opt/homebrew/bin/python3 /Users/natemcintosh/dev/battery_condition/get_battery_condition.py
* * * * * /opt/homebrew/bin/python3 /Users/natemcintosh/dev/battery_condition/testing_cron.py
The first command is the one that appends to the database row. I can copy and paste that command at the command line, run it, and it adds the row. It does not run every minute. The contents of /Users/natemcintosh/dev/battery_condition/get_battery_condition.py
are
# /Users/natemcintosh/dev/battery_condition/get_battery_condition.py
import subprocess
import re
import sqlite3
import datetime
def get_conds():
# Run the command to get battery info
command = "system_profiler SPPowerDataType".split()
response = subprocess.run(command, check=True, capture_output=True)
response = str(response.stdout)
# Get just the parts of interest
cycle_count = re.findall(r"Cycle Count: (\d+)", response)[0]
condition = re.findall(r"Condition: (\w+)", response)[0]
max_capacity = re.findall(r"Maximum Capacity: (\d+)", response)[0]
now = str(datetime.datetime.now().isoformat())
return [now, cycle_count, condition, max_capacity]
def append_row_to_db(db_name: str, items: list):
conn = sqlite3.connect(db_name)
with conn:
conn.execute("INSERT INTO battery_condition VALUES (?,?,?,?)", items)
conn.close()
if __name__ == "__main__":
# Get the condition
battery_condition = get_conds()
# Append to the file
filename = "/Users/natemcintosh/dev/battery_condition/battery_condition.db"
append_row_to_db(filename, battery_condition)
The second command is a test script that does work.
#/Users/natemcintosh/dev/battery_condition/testing_cron.py
import datetime
if __name__ == "__main__":
with open("/Users/natemcintosh/Desktop/crontest.txt", "a+") as f:
now = str(datetime.datetime.now().isoformat())
f.write(f"{now}\n")
Every minute, a new line appears in /Users/natemcintosh/Desktop/crontest.txt
with the current date and time. I've also tried having the test script write to other locations on disk, and they all seem to work.
With the help of Gordon Davisson, I've figure out the issue. When I call subprocess.run(command, check=True, capture_output=True)
, the command did not have the full path to the executable.
It used to be
command = "system_profiler SPPowerDataType".split()
I got the full path to the system_profiler
command with
$ which system_profiler
/usr/sbin/system_profiler
And fixed the line in my python script to be
command = "/usr/sbin/system_profiler SPPowerDataType".split()
The tool now runs successfully!