Chris Hill
Chris Hill

Reputation: 195

Python script runs in bash, but not in cron?

I have written a python script that goes to reddit (using PRAW), goes to a specific subreddit, and downloads episodes of a podcast from Youtube using youtube-dl. I placed the script in my /bin folder, so I can run it from anywhere is bash. The problem is that it runs fine in bash, but not in cron at all. I've set it up in cron as like this:

0 */1 * * * PKA.py

Here is a copy of the stacktrace that cron puts in /var/mail:

Traceback (most recent call last):
     File "/bin/PKA.py", line 48, in <module>
    call(myCall)
  File "/usr/lib/python2.7/subprocess.py", line 522, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib/python2.7/subprocess.py", line 710, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1335, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

The crash happens at the system call. It clearly gives the error 'No such file or directory', but all of the directories are correct. I'm only using absolute paths, so that shouldn't be a problem. I'm having a really hard time figuring out the problem, and I'd appreciate any help you guys could give. Here is the full script:

#!/usr/bin/env python
import praw
import os
from subprocess import call

#Directories
PKA_DIR = '/home/chris/Storage/750g/PKA/'
PKA_DOWNLOADED = '/home/chris/Storage/750g/PKA/pka-downloaded'
PKN_DIR = '/home/chris/Storage/750g/PKN/'
PKN_DOWNLOADED = '/home/chris/Storage/750g/PKN/pkn-downloaded'

#Create the reddit instance
reddit = praw.Reddit(Deleted for privacy)
subreddit = reddit.subreddit(Deleted Subreddit Name)

for submission in subreddit.new(limit=5):
    isDownloaded = False
    with open(PKN_DOWNLOADED, 'r') as downloaded:
        for line in downloaded:
            if submission.url in line:
                isDownloaded = True
            if line in submission.url:
                isDownloaded = True
        if isDownloaded == False:
            title, episode = submission.title.split()
            if title == 'PKN':
                myTitle = 'PKN #%s'%(episode) + '.%(ext)s'
                myCall = ['youtube-dl', '-f ' 'bestvideo[ext=mp4]+bestaudio[ext=m4a]', '-o' '%s%s'%(PKN_DIR,myTitle), submission.url]
                call(myCall)
                with open(PKN_DOWNLOADED, 'a') as writeOut:
                    writeOut.write(submission.url + '\n')
    isDownloaded = False
    with open(PKA_DOWNLOADED, 'r') as downloaded:
        for line in downloaded:
            if submission.url in line:
                isDownloaded = True
            if line in submission.url:
                isDownloaded = True
        if isDownloaded == False:
            title, episode = submission.title.split()
            if title == 'PKA':
                myTitle = 'PKA #%s - '%(episode) + '%(title)s.%(ext)s'
                myCall = ['youtube-dl', '-f ' 'bestvideo[ext=mp4]+bestaudio[ext=m4a]', '-o' '%s%s'%(PKA_DIR,myTitle), submission.url]
                call(myCall)
                with open(PKA_DOWNLOADED, 'a') as writeOut:
                    writeOut.write(submission.url + '\n')

The programs signs into the bots account (I know this isn't necessary, I just wanted to try out the full features of PRAW), and navigates to the subreddit. It considers the most recent 5 posts, and pulls the youtube link from it. It checks the link against a text file database of previously downloaded episodes. If the episode has not been downloaded, it downloads it and adds it to the list. It puts all the necessary arguments into a list, and does a system call with call. I suspected the issue was due to permissions, but my searching has told me that cron runs jobs as root. The folder it's downloading to (`/home/chris/Storage/750g') are all on seperate drives, so that's why I thought permissions might have been a problem.

Any suggestions?

Upvotes: 0

Views: 196

Answers (1)

Philip Tzou
Philip Tzou

Reputation: 6438

The simplest solution is to use full absolute path for youtube-dl. In your case, use /usr/local/bin/youtube-dl instead of youtube-dl.

The reason:

Some Linux distributions, like Ubuntu, changes the original PATH variable to include commands in /usr/local/bin when user accessed the shell. However, cron passes a minimal set of environment variables to the job and keeps the original PATH[1].

Upvotes: 1

Related Questions