Unable to run python script with cron - python

I am trying to run a simple python script with cron and I cannot for the life of me get it to work. I am running Ubuntu 18.04.
I know there are many questions (and answers) on this. I have looked at a number of them and I still cannot get it to work.
My python script is:
#!/usr/bin/env python
from tkinter import messagebox
messagebox.showinfo('MessageBox','Hello world!')
I have followed Unable to Run Python Script In Cron and changed the permissions as follows:
chmod +x /home/brb/bugs/projects/cron/hello.py
I can successfully run this from the command line as follows:
brb#bishop:~$ /home/brb/bugs/projects/cron/hello.py
Inside crontab I have tried to execute the script in 2 different ways as follows (every 2 or 3 minutes to try and pin down which one works...)
*/2 * * * * /home/brb/bugs/projects/cron/hello.py
*/3 * * * * /usr/bin/env python /home/brb/bugs/projects/cron/hello.py
Nothing happens.
I followed http://www.jessicayung.com/automate-running-a-script-using-crontab/ and tried to inspect the error file as follows:
cd ../..
cd var/mail
nano $brb
and I observe a message in nano that says
[ Directory '.' is not writable ]
I am not sure which directory '.' is, perhaps it is var/mail. In any case, not sure how to make it writable. I will google chmod some more to get this writable I guess, but that still doesn't solve why cron is not working when it looks like all the examples I've seen...
EDIT:
I followed How to run an X program from outside the X session (e.g. from the console or SSH) as per the comment from triplee and, not really knowing what I am doing, I attempted to change my display permissions as follows:
brb#bishop:~$ export XAUTHORITY=/home/brb/.Xauthority
brb#bishop:~$ export DISPLAY=':0'
My cron job is still not work...

Your problem is twofold:
cronjob has does not know where it could be displaying a graphical app (which X server or DISPLAY to use.
This can be addressed by making sure DISPLAY is set in the environment of you script. Run echo $DISPLAY in a terminal running in your X session. :0 is a very likely it.
Even if it knows the correct DISPLAY, it does (should) not have access to it. If you are running the cronjob under the same user as the one running your target X session. If it is a different user, and it has access to your user's home, you could reuse it's authority file by setting XAUTHORITY to point to it.
You can also export necessary information from your running session (renewed with each session), type this into a terminal there: xauth list $DISPLAY and add it for your cron running user: xauth add displayname protocolname hexkey (using those three values as returned by xauth list.

Related

Python scripts couldn't work with crontab

I'm new to stackoverflow and really hope to get answers to my question about crontab.
I'm using MacbookAir in BigSur(don't know if it affects)And my crontab just couldn't run python scripts below.
f = open("test_crontab.txt",'w+')
f.write("Success")
f.close()
But I could run this script with Spyder.
I could edit crontab with crontab -e, and my code in vi crontab was
13 01 * * * /bin/zsh /Users/myusername/Documents/Lynn\'s\ Python\ work/shopee/test.py >>/Users/myusername/Desktop/out.log 2>>/Users/tzulingkuo/Desktop/err.log
But it failed to generate txt file.
The messages in err.log were like below:
/Users/*myusername*/Documents/Lynn's Python work/shopee/test.py:5: missing end of string
/Users/*myusername*/Documents/Lynn's Python work/shopee/test.py:6: unknown username ''
I've searched stackoverflow for two nights and couldn't find the solution. I major in finance and I have no friends studying computer science.
Could anyone help me 🥺
Any help is reaaaaally appreciated!
Since that's a python script, you need to run it in python, not /bin/zsh. zsh is trying to interpret it as a shell script, but the syntax is all wrong, so you get errors.
The simplest way to fix this to replace /bin/zsh in your crontab entry with /usr/bin/python (assuming you're using the built-in Python version 2; if you have installed Python version 3 and want to use that, run which python at the command line to find its path).
But it's generally better to add a shebang line to your python script, and let that control how it's run. Add this as the very first line of the script:
#!/usr/bin/python
(Again, if you want to use Python 3, replace the path part with the path for the Python 3 interpreter.) Then make the script executable with chmod +x /Users/myusername/Documents/Lynn\'s\ Python\ work/shopee/test.py, and just remove the /bin/zsh part from the crontab entry.
BTW, you're probably going to have trouble with paths. By default, cron jobs run with their working directory set to your home directory, so when the script opens test_crontab.txt, that's going to be interpreted as /Users/myusername/test_crontab.txt. If you want it down in the Documents/Lynn's Python work/shopee directory, you'll have to specify that explicitly.
You may also run into trouble with missing environment variables. If you're setting any environment variables in your shell initialization scripts that configure Python, add libraries, etc, those won't be set up in the cron job's environment.

Why using crontab I get "-bash: Applications: command not found"?

I'm trying to schedule a simple python script on MacOS using crontab. I have seen lot of guides and answers to other questions here in SO but still can't get my task to work. Actually I'm not so familiar with terminal and this kind of stuff but it didn't seem so difficult so I'm hoping to solve it.
I followed two different approaches.
First approach:
I use the command crontab -e on the terminal
In VIM I press I for Insert and paste the following:
* * * * * /usr/bin/python mypath/ap.py
Press "esc" and ":qw" to close VIM window.
crontab -l shows my cron entry as expected, BUT nothing happens from the script (it is supposed to create a txt file).
Second approach:
I paste this line in the terminal:
* * * * * /usr/bin/python mypath/ap.py >> mypath/MyCronLog.txt 2>&1
In this way I can see a txt file where I can read the log and eventual errors. MyCronLog.txt shows: -bash: Applications: command not found or -bash: ap.py: command not found.
My python script is located in a folder on my dekstop (I don't know if it matters).
Moreover I run my python script from terminal and it works perfectly.
Any suggestion is appreciated!
EDIT 1:
The path of my python script is the following:
/Users/myname/Desktop/ap/ap.py
EDIT 2:
"/opt/anaconda3/bin/python" in place of "/usr/bin/python" but nothing has changed.
The problem seems to be in your python script. I guess the txt-file is created but in the wrong folder. When cron calls a python script, the working directory is NOT the directory of that script (see here). Look here for a workaround.
EDIT:
The behavior of your script might depend on the directory from which you call it (not an ideal way to write scripts). When you are in /Users/myname/Desktop/ap and call python ap.py, this might lead to something different than calling python ap/ap.py from /Users/myname/Desktop
You can verify this by calling this short script:
import os
print(os.getcwd())
I can imagine that your script crashes when called by cron while it works if you call it from the containing directory.

Running a tkinter GUI using crontab

I have a simple GUI (created using tkinter) that I want to run at a specific time of day on a Raspberry pi 3. Bellow is the code snippet I used in crontab. I invoked the crontab manager using sudo crontab -e.
0 18 * * * cd /home/pi/gui && python3 gui.py
For the moment, I can execute the GUI by invoking it directly via the Pi's command line. However, it doesn't work when I try to do it using cron. I also tried to switch to a basic python script (writing to a file) and that worked. Is there a specific weird interaction that I need to be aware of?
My setup: raspberry pi 3, python 3, raspi-screen, tkinter (latest version as far as I know)
The sudo will run without a tty and display that is why you command won't work.
Try having xvfb installed and use
0 18 * * * cd /home/pi/gui && xvfb-run python3 gui.py
Update-1: 22-Jun-18
If you want to use your actual display then you need to make sure that you use below command
XAUTHORITY=/home/<user>/.Xauthority DISPLAY=:0 python3 gui.py
And also make sure the cron is for your user. The default DISPLAY is :0.
When you have a XServer (GUI display), you cannot just connect to it without an authorization. When system start it creates a file and that location is stored in environment variable XAUTHORITY.
When you run a cron, you have limited environment variables. There is no existing XAUTHORITY or DISPLAY defined
to be able to connect to display you need. So you need to define every environment variable that would be required by your program
So you define DISPLAY=:0 to select the default display and you need to set XAUTHORITY=/home/<user>/.Xauthority to prove that you are authorized to connect to the display
Raspbian 10 (buster): the only missing part - in my case - was to inform the cron-job using gtk, which display it has to use, by inserting
DISPLAY=:0. I used a bash-script to start the python script using tk; This could be a python script as well.
#reboot DISPLAY=:0 /home/pi/path/to/my/script.sh start
Useful for debugging:
#reboot DISPLAY=:0 /home/pi/path/to/my/script.sh start >> home/pi/Desktop/cron.log (in one line)
Using cron as user pi (not as root), it was necessary to place the cron.log file in some /home/pi/... folder to give writing access for the log-files.
Maybe Raspbian needs some time to setup everything before an applicaiton can be started; I used:
#reboot sleep 10 && DISPLAY=:0 /home/pi/path/to/my/script.sh start
In place of #reboot the usual cron settings can be used, e.g.:
*/5 * * * *(rest of line see above)
for every 5 minutes to start.

Cron job can't run bash script (that shells python script requiring xsession) that runs perfectly well from console

I am using dryscrape in a python script. The python script is called in a bash script, which is run by cron. For those who may not be aware, dryscrape is a headless browser (use QtWebkit in the background - so requires an xsession).
Here are the main points concerning the issue I'm having
When I run the python script from the command line, it works
When I run the bash script from the command line, it works too
I figured out that this may have something to do with different environments between my command prompt and when the cron job is running, so I modified my bash script to source my .profile as follows:
#/bin/bash
. /full/path/to/my/home/directory/.profile
python script_to_run.py
This is what my cronjob crontab entry looks like:
0,55 14-22 * * 1-5 /path/to/script.sh >> $(date "+/path/to/logs/\%Y\%m\%d.mydownload.log" )
By the way, I know that the job is being run (I can see entries in /var/log/syslog, and the script also writes to a log file - which is where I get the error message below):
In all cases, I got the following error message:
Could not connect to X server. Try calling dryscrape.start_xvfb()
before creating a session
I have installed the prerequisites, on my machine (obviously - since it runs at the command line). At the moment, I have run out of ideas.
What is causing the script to run fine at the console, and then fail when run by cron?
[[Relevant Details]]
OS: Linux 16.0.4 LTS
bash: version 4.3.46(1)
cron user: myself (i.e. same user at the command prompt)
dryscrape: version 1.0.1
The solution to this was to call the dryscrape.start_xvfb() method before starting the dryscrape session.
Cron user does not have display, so you cannot run any command which requires a display.
You need to modify the python script to do not use any type of display (check carefully, because some python commands, even though they do not open any display , they internally check for this variable).
The best way to test is to ssh into the machine without Display, and check if you can run it from there without erros.

django-chronograph script wont run from cron job or manually due to permissions issue

I've created a custom management command as a py file, in the usual place.
chronograph is installed in the right place and syncd ok.
I've created the cron job as the following
* * * * * /home/shofty/virtualenvs/webbricks/bin/chronograph -e /home/shofty/virtualenvs/webbricks/bin/activate_this.py -p /home/shofty/virtualenvs/webbricks/website
ive also tried the following, as i think it may be correct but not whats in the documentation
* * * * * /home/shofty/virtualenvs/webbricks/bin/chronograph -e /home/shofty/virtualenvs/webbricks/bin/activate_this.py -p /home/shofty/virtualenvs/webbricks/website/manage.py cron
I've added the manage.py cron because its what you run to tell the chronograph function to look for jobs that need running. if im in my virtual env and i run manage.py cron it works and the job runs.
both jobs are failing to run, but when i try to run them manually, as su or my user, they fail due to permissions denied. not sure what permission they're referring to. anyone come across this before?
The answer for this was that chronograph.sh has been superseded by chronograph. despite this supposedly being able to activate an env, it wasn't doing it early enough to import argparse which as far as i can tell isn't inbuilt to python 2.5 but is in 2.6. then its just down to getting the right combination of arguements for the chronograph script, which for reference is a -p and an -e but not an -s.
also i had to run the script as root but targetting the script inside the users virtualenv.
finally i also had to add site paths for packages directory to the chronograph script as it couldnt find argparse until i did that.
You may find this comes in handy for issue you have with file permissions. File permission basics
Have you tried running the cron job as the appropriate user/service?
To edit crontab entries of other Linux users, login to root and use -u {username} -e as shown below.
root#dev-db# crontab -u otheruser -e
#monthly /home/otheruser/fedora/bin/monthly-backup
00 09-18 * * * /home/otheruser/ubuntu/bin/check-db-status
As you're using a virtual environment:
Included is a script called chronograph.sh. Copy this file
to your project directory.
cp chronograph.sh ~/virtualenvs/webbricks/chronograph.sh
You need to open up this script and modify the path to your virtual environment's activate
script::
$PROJECT_PATH"/home/shofty/virtualenvs/webbricks/bin/activate"
Make sure that this file is executable and then update your crontab to execute the
script.
chmod a-x chronograph.sh
Then:
crontab -e
* * * * * /home/shofty/virtualenvs/webbricks/chronograph.sh /home/shofty/virtualenvs/webbricks/website
Make sure that you pass /path/to/your/project to the script as the first argument.
This should ensure that cron shouldn't have problems finding your project directory.
Is it os permission denied or are your receiving a 403? If it is a 403 I think is most likely caused by Django's CSRF protection. If your script is posting to a particular view, make sure to mark it as csrf_exempt
If the permission denied is at the file system / operating system level then I don't really know.

Categories