Starting a Python script on a raspberry via plink (not responding crontab) - python

I have written a script.py, which opens a tk window and draws with turtle in the canvas the window contains. I want to start this script via a plink using:
plink.exe -pw raspberry pi#pi-fisch00 python /home/pi/script.py
But I always receive an error:
script.py line 32, in <module> root = Tk()
no display name and no $DISPLAY environment variable
I think the same error is causing that the crontab is not executing the script.py.
My entry in the crontab:
*/1 * * * * python /home/pi/script.py
The syntax should be right, because other scripts are working and if I put python /home/pi/script.py in the cmd manually everything is fine. The script.py gets executed. How can I fix this and let the crontab execute the script.py? Why can't I execute the script.py via plink?

Look at the error message you are getting:
no display name and no $DISPLAY environment variable
You are attempting to run something that requires an X11 display, which isn't going to be available from within cron's context (and likely not via plink either, unless you are running an X11 display server locally and have enabled X11 forwarding).
Typically, if you have something that needs access to the display you need to run it from within an existing desktop session. There are ways to work around this; for some thoughts on that topic see:
https://unix.stackexchange.com/questions/25684/how-to-access-x-display-from-a-cron-job-when-using-gdm3
https://unix.stackexchange.com/questions/10121/open-a-window-on-a-remote-x-display-why-cannot-open-display

Related

DietPI: _tkinter.TclError: no display name and no $DISPLAY environment variable

i want to run a python script on dietPI. I chose dietPI because i want to boot fast.
When i run a simple tkinter program i get the error _tkinter.TclError: no display name and no $DISPLAY environment variable
Ive already tried setting a display variable like so: export DISPLAY=:0
(i tried other numbers aswell)
but then i get _tkinter.TclError: couldn't connect to display ":0.0"
Any help?
This took me all day to get working. (I also posted this same answer on a different SE site here: https://raspberrypi.stackexchange.com/a/118928/60683)
Note: This is for raspbian, with main user account using the default username ("pi")
Here are the steps in order:
Name your python file main.py and drag your python file to the desktop.
Next, create a new plain text file and add the following contents:
#!/bin/bash
python3 /home/pi/Desktop/main.py
Save this text file as launch.command on the desktop. This is shell script to launch your python file. By default it won't work, we have to chmod it (next step)
Run terminal and run the following command:
chmod u+x /home/pi/Desktop/launch.command
Now double clicking launch.command (and selecting execute) will launch your python file.
At this point, we are ready to get it launching on boot. If you've done any other launch attempts prior to this please undo all of those file changes you had done.
Open terminal and run the following:
sudo nano /etc/systemd/system/myproject.service
We are just going to call it myproject for now, don't change any of this until after you get it working, then feel free to attempt a rename
In the window that pops up, copy paste the following exactly:
[Unit]
Description=Start Myproject
After=graphical.target
Wants=graphical.target
[Service]
User=pi
Group=pi
ExecStart=/bin/bash -c "export DISPLAY=:0; export XAUTHORITY=/home/pi/.Xauthority; /home/pi/Desktop/launch.command"
[Install]
WantedBy=graphical.target
Now press ctrl+x to exit-and-save, it will prompt you to save changes, type "y", the filename should already be entered as .../myproject.service, if it is then press enter and it will save and exit, if the file name is blank it messed up (this just happens sometimes), quit terminal and try all of this again, sorry.
Now in terminal enter:
sudo systemctl daemon-reload
Then
sudo systemctl enable myproject.service
Lastly
sudo reboot
On launch, before anything else shows (after the boot up splash screen shows of course, but before desktop shows) your GUI will now launch, congrats!
I recommend you launch it full screen, to do that edit your python file to use this:
root.attributes('-fullscreen', True)
NOTE, 'root' is likely not what you called your TK() init.... at the end of your code you have something like XXXX.mainloop(), change 'root' to whatever XXXX is, stick this right after your init of TK()
Once you've reboot, you are likely stuck in the app (especially if you launched it full screen), things like alt+f4 or alt+f11 won't kill your program. To exit, press the windows/menu button on your keyboard, the access panel will appear you and can go to accessories>terminal to launch a new terminal window, then run the following:
sudo systemctl stop myproject.service
The program will be killed and you will be back to your standard desktop...
NOW, to prevent it from launching again on bootup, simply rename your launch.command file to DISABLED_launch.command and when you're ready to start launching on bootup again set the name back.
Go get a drink, you've earned it.
Also, you can obviously put these places other than desktop but MAKE SURE you always use the full path in any of these commands, don't use the '~/..' shortcut.

Unable to run python script with cron

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.

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.

Execute python script directly, shorcut and execute from startup

I did a application with Python 3 using Tkinter gui, on Raspbian with the RPi. I have three questions:
1) I've turned the python script into executable using:
chmod -x path/myfile.py
I've declared on the first line of script
#!/usr/bin/env python3
When I double click onthe script it pops up a windows asking if I want to execute normally or on the terminal. If i chose Execute, the script runs normally.
Is there any way to execute normally directly, without asking?
2) How do i create a shortcut on my Desktop to execute my python script?
I've created a file on the desktop and I edited the following:
[Desktop Entry]
Type=Application
Encoding=UTF-8
Name=Name of the shortcut
Comment=Comment
Icon=path/pic.gif
Exec=python3 path/myfile.py
Terminal=false
The picture if the shortcut works, but the script it's not launched. It appears the hourglass and nothing happens.
3) How do I make a python script launch when at the startup of Raspbian?
I've already edited the
/etc/xdg/lxsession/LXDE/autostart
and also the
/etc/xdg/lxsession/LXDE-pi/autostart
with:
#python3 path/myfile.py
on the last line of the file. Rebooting the system, nothing happens.
Thank you for your help.

Categories