I have a python script to record a .mp4 file with picamera2 which executes and save correctly when run through the editor (thonny) and through the terminal. However, when I schedule it through crontab to run at boot (or through bash.rc) the script runs (I hear the camera click on) but no file is saved in either the home directory or the directory that I've called in the python script. Is there some piece that I'm missin in cron to get it to actually save?

import time
import os
from picamera2 import Picamera2
from picamera2.encoders import H264Encoder
from picamera2.outputs import FfmpegOutput
timestr = time.strftime("%Y%m%d-%H%M%S")

picam2 = Picamera2()
video_config = picam2.create_video_configuration()

encoder = H264Encoder(10000000)
output = FfmpegOutput(timestr+'.mp4', audio=True, )

picam2.start_recording(encoder, output)

I've also tried getting putting this into a shell script and scheduling the shell to run in cron. Same issue - the shell will run the python script successfully and save a file appropriately when executed from terminal, but not when scheduled:

cd /
cd home/pi/
/usr/bin/python3 /home/pi/VideoPythonTest.py
cd /

Cron call:

@reboot sh /home/pi/launcher.sh     

2 Answers 2


Not quite sure as there are undisclosed details in your Q, but usually issues like this come down to a difference in the PATH settings. In other words, compare the PATH in your interactive shell vs the PATH in your user crontab. See this answer for how to check your environments.

One thing to try is to set a PATH environment in your launcher.sh script to be the same as your interactive shell. Is that clear? If not, let us know.

Another possibility is wrt timing; i.e. cron has no awareness of whether the facilities needed by your Python script are available at boot. There are (in general) two ways to handle this: 1. write a systemd unit; 2. "the easy way".

The "easy way" is to modify your crontab as follows:

@reboot sleep 30; /usr/bin/python3 /home/pi/VideoPythonTest.py >> /home/pi/my_crontab_log 2>&1

I think one of these will fix your problem, and I'm nearly positive that both used together will - I'd probably try this one first. If that doesn't get you where you want to be, try the first (change the PATH). As a last resort, you can make both mods.


Try this as your shell script - instead of the one you have now:

export PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin
# sleep 30
/usr/bin/python3 /home/pi/VideoPythonTest.py >> /home/pi/VidPyTest.log 2>&1

What does this do?
#!/bin/bash: "shebang"; it tells the os to use bash to process the following commands

export PATH=$PATH...; changes the default PATH in cron to be roughly the same as the PATH of your interactive shell

# sleep 30; this cmd is commented out, but you may need to use it depending on when systemd brings up other resources/services your .py program uses

/usr/bin/python3 /home/pi/VideoPythonTest.py >> /home/pi/VidPyTest.log 2>&1; calls python3 to process your .py program, and redirects (>>) stdout and stderr (2>&1) to the designated (.log) file. If your job fails for some reason, the .log file contents may be useful for troubleshooting.

Please let us know if this works or not. If not, please post the output of the .log file.

  • Thanks! I added the sleep modification to the crontab, and am still not getting the file to write out to proper spot. I went through checking the environment in crontab, and got the following return: env report follows for user LANGUAGE=en_US.UTF-8 HOME=/root LOGNAME=root PATH=/usr/bin:/bin LANG=en_US.UTF-8 SHELL=/bin/sh LC_ALL=en_US.UTF-8 PWD=/root env report for user concluded Having HOME = /root seems like it could be the probelm? Could you elaborate on what you mean by "PATH environment in your launcher.sh to be the same as the interactive shell?"
    – roconnor
    Dec 12, 2022 at 17:22
  • @roconnor: The PATH is an element of the environment; i.e. PATH=/usr/bin:/bin in your comment. Do a bit of research on the PATH environment variable to understand its role. Briefly: Your system must know where to find any executable you call. Since it works from your interactive shell (which has a different PATH than cron, one solution is to add its PATH to your shell script. When I get back from dinner, I'll add an edit to my answer with a change to your shell script. that may work.
    – Seamus
    Dec 13, 2022 at 1:00

Why do you do: os.chdir? Just provide a full path to FfmpegOutput instead. Also, it looks like you are trying to write to a SD card. Is it already mounted when the cron runs? The crons will run when the matching systemd service (crond) starts, but there may be other stuff still waiting to be run.

Another problem may be that you run the cron in a different user. If the video capture works manually with the pi user, then no need to use root. Make sure the cron job runs as pi, not a different user.

Things you can do troubleshoot further:

  • send cron job output to a log (as already described by @seamus)
  • run the cron job in a screen session: first install GNU screen, then you can schedule a command like this in your crontab: /usr/bin/screen -dmS "picamera" bash -c '/home/pi/launcher.sh'; exec bash. This will start the job in a detached screen window. Then you can use screen -r to "join" that session when the Pi has booted, and screen -ls to list the active sessions (normally only one). The second command: ; exec bash is to make sure the screen does not exit even if the previous command failed.

It is also possible to log the console output from the screen session to a file. Look at the doc for the .screenrc file.

I don't know how /home/pi/launcher.sh differs from /home/pi/VideoPythonTest.py so you may have to adjust the command accordingly

Your Answer

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

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