Program execution with crontab - python

Hardware setup (computer, etc)
Ubuntu server 18.04.1
Serial To Usb Converter with 8 ports
Python version
2.7.15r1
Python program description
When the program starts to create some threads:
Create one thread for the Modbus server.
Run 1 thread for each serial port connected (/dev/ttyUSBn) and start read the data.
Problem explanation
When I run the script using the normal command (python2.7 myProgram.py) it work, so the modbus server start and I can read the value, and I can also see the usb-serial convert blink on the TX-RX leds.
If I check the readed data they are correct, so the program is working properly.
The problem come out when I set up a crontab job that run my python script!
The modbus server start properly, but I can't see the usb-serial converter leds blink and the python program don't print the readed data. That means the program is not working on the "serial" side.
To create the job I has used the following commands:
crontab -e
selected nano (default option)
added at the end of the file the cron command: #reboot /usr/bin/python2.7 /myProgram.py
I can't figure out where the problem is, the program is not catching the exception and the process is still running until I stop it manually. If I stop it and run it manually after that it start and work properly.
To help you:
I have also tried to run it using **systemctl**, the problem is the same.
At boot the service start and if I check it I can read: Active(running), but the software is not reading from the serial port.
The questions are:
How can I solve it?
There is something wrong with the crontab job?
Maybe crontab job can't access the /dev/ directory? How can I solve this?
I'm very confused about that, I hope the question is properly created and formatted.
EDIT 30/11/18:
I have removed the crontab command, and create a service to run the program using this procedure.
If I run the command: service supervision start I can see that the process is running correctly and on htop I have only 4 processes.
In this case, the program is not reading from the serial port, but the modbus server is working. You can see that I have just 4 processes and the cpu load is too high.
If I run it manually with the command: python2.7 LibSupervisione.py
The output of the htop command is:
Here you can see that I have more processes, 1 for each thread that I create and the load on the cpu is properly distributed.

Your script probably requires a Console or some Environment variables, but in a systemd started process you dont have these automatically.
The easiest way would be to prepend /usr/bin/bash -c "your command" in your System unit in the field ExecStart to enable a Shell like Environment likle this:
ExecStart=/bin/bash -c "/usr/bin/python2.7 /myProgram.py"
WorkingDirectory=yourWorkingDir
Why do you Need to use cron? Use a systemd timer instead.

If you could run your code with the service like this: sudo service <service-name> start and get a good status using sudo service <serivice-name> status, you can test it in crontab -e like this (run every 5 minutes for test):
*/5 * * * * service <service-name> start
*/10 * * * * service <service-name> stop
Then using #rebote after with the above test.
OR:
Finally, if you want to run your code/service at the system startup, do it instead of cron jon:
Edit the rc.local file with an editor with the sudo permission, then:
#!/bin/sh -e
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
service <service-name> start
exit 0
[NOTE]:
This is the procedure of creating a service from your code.

Related

run a python script on raspberry pi turned on

I am working on raspberry pi 3 about 3 months , I had a problem when I started working with it.
I couldn't find an efficient and safe way to run a python script on raspberry when it turns on(without monitor and mouse and keyboard).At the moment I have added "$sudo run myscript.py &" at /etc/profile but sometimes when I turn it on my script doesn't run until I connect monitor and mouse and keyboard to it and run the script with GUI and after that it works fine (again without mouse and keyboard).
I want to know is there any solution that I will be sure my script will run after I turn raspberry pi on?
Thanks a lot
You will want to setup a service and user sudo service <my_service> [start, stop, restart] to get it working on startup. See here for reference.
The /etc/profile is executed when new shell session in being started, so unless you start at least single shell session your script will not be run. Moreover it will be terminated when session stops, and if you start multiple sessions then the script will also be started for each session, which is probably not what you want.
Depending on your init system you would need to create SysVinit or systemd service. Assuming you use systemd based distro (which is currently default for most Linux distributions) you need to do following:
Step 1: Place your script in location from which it will be executed by service. For example /usr/local/bin/ may be good choice.
Step 2: Create service file. Assuming you want to name it myscript.service, create file at following path /etc/systemd/system/myscript.service with following content:
[Unit]
Description=myscript
[Service]
ExecStart="/usr/bin/python /usr/local/bin/myscript.py"
[Install]
WantedBy=multi-user.target
Step 3: Reload systemd daemon and enable your service:
systemctl daemon-reload
systemctl enable myscript
Now after you restart your system, your service should be automatically started. You can verify that using command systemctl status myscript, which returns service status.

Watchdog for specific python process

I am working on Ubuntu 16.04 and I have a python running process in the background
python myFunction.py
From time to time, myFunction process gets killed for unknown reason, however, I want to restart it automatically. I have multiple python process running in the background, and I do not know which one runs myFunctions.py (e.g. by using the pgrep command).
Is it possible? Can I make a bash or python script to restart the command python myFunction.py whenever the python process running it gets killed?
You can look at Supervisord which is (from its own documentation) :
a client/server system that allows its users to monitor and control a
number of processes on UNIX-like operating systems
Supervisord will keep your script in check. If it crashes, it will restart it again. If your raspberry reboots it will make sure the scripts starts automically after booting.
It works based on a config file formatted like this (more info in the docs) :
[program:myFunction]
command=/path_to_script/myFunction.py
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/myFunction.log
stderr_logfile=/var/log/myFunction.error.log
directory=/path_to_script
I hope this will help you

Python Script that was called from bash startup script stops after 20mins of running,

I have a python script that has a While True: in it that I would like to have run on startup on a raspberry pi running Jessie.
So far I have a startup bash script in /etc/init.d called startup.sh which contains
sudo python3 /home/pi/Desktop/Scripts/bluez3.py &
When the raspberry pi starts up, the script does run but after 20 minutes the script seems to stop. I have logging in my script and the time-stamp stops exactly 20 mins in.
I did some reading and I think the best option would be to create the python script as a service on the raspberry pi. However, I have not been able to find a decent tutorial about how to do this (and my lack of python knowledge).
My question is, is there another way to resolve my problem or does anyone know of a good tutorial on how to make the python script into a service.
Thanks!
given the name of your script, I'm guessing it's related to some bluetooth stuff. It's likely that after 20 min, whatever you're checking/needing in your script gets unaccessible and throws an exception or something like that. Like a resource being locked, or a bt device being disconnected or a module being unloaded or unavailable or [insert edge case reason here]…
that being said, in between creating a systemd service, you can first play with supervisorctl which is just an apt install supervisor away.
then if you really want to launch it as a service, you can find plenty of examples in /lib/systemd/system/*.service, like the following:
[Unit]
Description=Your service
Wants=
After=bluetooth.target # I guess you need bluetooth initialised first
[Service]
ExecStart=/usr/bin/python3 /home/pi/Desktop/Scripts/bluez3.py
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=always
[Install]
WantedBy=multi-user.target
which I customized from the sshd.service file 😉

Sent Data with Modem on Booting Beagle

I want to run my python program sent data to server with websocket. I want run my program on booting, so I put my program in crontab with this code :
crontab -e
#reboot /usr/bin/python /usr/local/bin/vcs/vcs.py
#reboot bash /usr/local/bin/vcs/onmodem.sh
in on modem.sh there is the code:
sleep (120)
wvdial &
I got ppp0 but my vcs.py didn't sent any data. Then I try to run my program without booting, my program run and sent data.
How this problem can solved?
Thankyou for the advise
If you want to run your program at startup, I suggest to create a dedicated service.
System and service manager
You can define your service by using the following lines, or directly call you script named modem.sh
ExecStartPre=/bin/sh -c 'sleep 120'
ExecStart=/usr/bin/wvdial &

GUI not opening

I have written a python script which scans my gmail INBOX for a particular mail, and if that mail is present it opens up a GUI. I have tested this script and works correctly.
I want to run this script whenever the network connection is established. So, I have added a script in the dispatch.d directory of the NetworkManager. My bash script is shown below.
#!/bin/bash
#/etc/NetworkManager/dispatcher.d/90filename.sh
IF=$1
STATUS=$2
if [ "$IF" == "wlan0" ]; # for wireless internet
then
case "$2" in
up)
logger -s "NM Script up triggered"
python /home/rahul/python/expensesheet/emailReader.py
logger -s "emailReader completed"
exitValue=$?
python3.2 /home/rahul/python/expensesheet/GUI.py &
logger -s "GUI completed with exit status $exitValue"
;;
down)
logger -s "NM Script down triggered"
#place custom here
;;
pre-up)
logger -s "NM Script pre-up triggered"
#place custom here
;;
post-down)
logger -s "NM Script post-down triggered"
#place custom here
;;
*)
;;
esac
fi
I have used tkinter to design my GUI.
My problem is that, emailReader(which has no GUI) gets executed correctly, but GUI.py doesn't get executed. It exits with the exit status 1.
Can somebody throw some light on this matter and explain what I'm doing wrong?
NetworkManager is a process that is running on a virtual terminal, outside of your X-server.
(e.g. NetworkManager get's started on bootup before your window manager gets started; they are totally unrelated).
therefore, any script started by NetworkManager will not (directly) be able to access the GUI. (it is very similar to what you get when you change from your desktop to a virtual terminal (e.g. Ctrl-Alt-1), and then try to run your GUI from there: you will most likely get an error like "Can't open display".
if you want to start a GUI-program, you have 2 possibilities
tell a notification daemon (a sub-process of your window-manager) to start your GUI
tell your GUI to start on the correct display (the one, where your desktop is running)
i'd go for the first solution (notification daemons are designed for that very purpose), but how to do it, heavily depends on the window-manager you use.
the 2nd solution is a bit more dirty and involves potential security breaches but basically try something like starting DISPLAY=:0.0 myguiapp.py instead of starting myguiapp.py (this assumes you are running an X-server on localhost:0.0).
you can check whether this works by simply launching the command with the DISPLAY-line from a virtualterminal.
to get the display you are actually using, simply run echo $DISPLAY in a terminal within your X-server.
usually, remote connections are disabled to your running Xserver (as it allows non-proviliged users to take over your desktop - everything from starting new GUI-programs (which is what you want) to installing keyloggers); if that's the case check man xhost (or go for solution #1)
UPDATE
for the 1st solution, you probably want to check out libraries like libnotify (there's python bindings in python-notify and python-notify2).
if you want more than simple "notification popups", you probably have to dig into D-BUS.
a simple example (haven't tested it personally, though), can be found here.

Categories