Python script doesn't run background process, when called by cron - python

I have a python script, runned by cron:
"*/5 * * * * python /home/alex/scripts/checker > /dev/null &";
It has several purposes, one of them is to check certain programs in ps list and run them if they are not there. The problem is that script when runned by cron not executed programs in backgroung correctly, all of them are in ps list look like:
/usr/bin/python /home/alex/exec/runnable
So they look like python scripts. When I launch my python script manually it seems that it executes runnable in background corretcly, but with cron nothing works.
Here's the example of code:
def exec(file):
file = os.path.abspath(file)
os.system("chmod +x " + file)
cmd = file
#os.system(cmd)
#subprocess.Popen([cmd])
subprocess.call([cmd])
I tried different approaches but nothing seems to work right.
Some code update:
pids = get_pids(program)
if pids == None:
exec(program)
print 'Restarted'

Related

How to use batch file to run multiple python scripts simultaneously

I have many python scripts and it is a pain to run each one of them individually by clicking them. How to make a batch file to run them all at once?
just make a script like this backgrounding each task (on windows):
start /B python script1.py
start /B python script2.py
start /B python script3.py
on *nix:
python script1.py &
python script2.py &
python script3.py &
Assuming non of your script requires human interaction to run
Use the start command to initiate a process.
#echo off
start "" foo.py
start "" bar.py
start "" baz.py
Re comment: “is there way to start these minimized?”
You can always ask about how a command works by typing the command name followed by a /?. In this case, start /? tells us its command-line options include:
MIN Start window minimized.
Hence, to start the application minimized, use:
start "" /MIN quux.py
Multiprocessing .py files simultaneously
Run as many .py files simultaneously as you want. Create for each .py a .bat to start the python file. Define all the .bat files in the list of lists. The second parameter in the list is a delay to start the .bat file. Don't use zero for the delay. It works fine. On this way You leave parallelism to the operating system which is very fast and stable. For every .bat you start opens a command window to interact with the User.
from apscheduler.schedulers.background import BackgroundScheduler
import datetime as dt
from os import system
from time import sleep
parallel_tasks = [["Drive:\YourPath\First.bat", 1], ["Drive:\YourPath\Second.bat", 3]]
def DatTijd():
Nu = dt.datetime.now()
return Nu
def GetStartTime(Nu, seconds):
StartTime = (Nu + dt.timedelta(seconds=seconds)).strftime("%Y-%m-%d %H:%M:%S")
return StartTime
len_li = len(parallel_tasks)
sleepTime = parallel_tasks[len_li - 1][1] + 3
Nu = DatTijd()
for x in range(0, len_li):
parallel_tasks[x][0] = 'start cmd /C ' + parallel_tasks[x][0]
# if you want the command window stay open after the tasks are finished use: cmd /k in the line above
delta = parallel_tasks[x][1]
parallel_tasks[x][1] = GetStartTime(Nu, delta)
JobShedul = BackgroundScheduler()
JobShedul.start()
for x in range(0, len_li):
JobShedul.add_job(system, 'date', run_date=parallel_tasks[x][1], misfire_grace_time=3, args=[parallel_tasks[x][0]])
sleep(sleepTime)
JobShedul.shutdown()
exit()
Example.bat
echo off
Title Python is running [Your Python Name]
cls
echo "[Your Python Name] is starting up ..."
cd Drive:\YourPathToPythonFile
python YourPyFile.py

.profile in Ubuntu is running desired Python script, but script is not working as usual?

I'm creating a background changer for Ubuntu using Python, mostly for fun. When I run the script from the shell, it works and alternates the background between images in a certain folder. Now I am trying to run the script through .profile so that it runs upon login. The script is definitely running--I put a print statment in the relevant function, and when I hit 'alt, ctrl, f3', I see the output of the print statement--but for whatever reason, the background will not change when the function is called this way. I don't think it's a matter of running it from a non-local directory, either--as I said, if I run 'python program/python/desktop_changer/main.py', the desktop changer runs just fine.
Here are the relevant parts of the function:
if __name__ == "__main__":
time.sleep(15)
os.chdir(os.path.dirname(os.path.realpath(__file__)))
while True:
#Set pic, set timer, run continously
for img in os.listdir('pics/'):
#This next line is functional when I hit 'alt, ctrl, f3', outputting the paths for new images every ten seconds
print(os.path.abspath('pics/' + img))
set_gnome_wallpaper(os.path.abspath('pics/' + img))
time.sleep(float(10))
And set_gnome_wallpaper():
def set_gnome_wallpaper(file_path):
command = "gsettings set org.gnome.desktop.background picture-options 'zoom' && gsettings set org.gnome.desktop.background picture-uri file://'%s'" % file_path
subprocess.call(command, shell=True)
And in ~/.profile: (SPE and 20 are irrelevant arguments and their uses are commented out until I can get this running correctly)
python /home/chessie/program/python/desktop_changer/main.py SPE 20 &

How to run an interactive Python script as cron job?

I have a Python script, say test.py which interacts with the user everytime it is executed.
test.py
#!/usr/bin/env python3
def foo():
a = input()
print("Hello, {}".format(a))
if __name__ == '__main__':
foo()
I want to run this script every 5 minutes. So, I tried adding it to my crontab but it seems that this doesn't work as I am not prompted to enter an input.
I have tested my crontab and it is working fine.
Should I use libraries such as schedule for this task?
What would be the ideal way of going about in this scenario?
NOTE: I want a cross platform solution which works on MacOSX and GNU/Linux.
Your could try the python module pexpect (http://pexpect.sourceforge.net/doc/) -- the usage is something like :
import pexpect
child = pexpect.spawn(script/python file etc...)
child.expect('Here goes the prompt you would expect')
child.sendline('What you want to send to it')
its not possible to have cron interact interactively on your server.
Delink your application:
Setup a db (like MySQL), have test.py run via cron every 5 mins to check if a new entry is made in the db: then, have a local application that saves user prompt information to your db.
If it is running via cron or schedule, it will not be running on your terminal, it will run as a background process. Therefore, it cannot be interactive and you will not be prompted.
If you just want to put a delay of 5 minutes, have you looked at the Linux "sleep" command or using python's "time.sleep"? In this way you can keep a terminal open and just have the job run in intervals.
To keep it simple:
#!/usr/bin/env python3
import time
def foo():
a = input()
print("Hello, {}".format(a))
if __name__ == '__main__':
while True:
foo()
time.sleep(300) # Sleeps 300 seconds
You can get a script and use that in the crontab:
#!/bin/bash
/usr/bin/python3 /home/user/project/test.py << EOF
some input here
EOF
Your crontab will look like
* * * * * /home/user/project/test.sh >> /home/user/project/LOG 2>&1

Launch a single python script as different processes differing by command line arguments

I have python script that takes command line arguments. The way I get the command line arguments is by reading a mongo database. I need to iterate over the mongo query and launch a different process for the single script with different command line arguments from the mongo query.
Key is, I need the launched processes to be:
separate processes share nothing
when killing the process, I need to be able to kill them all easily.
I think the command killall -9 script.py would work and satisfies the second constraint.
Edit 1
From the answer below, the launcher.py program looks like this
def main():
symbolPreDict = initializeGetMongoAllSymbols()
keys = sorted(symbolPreDict.keys())
for symbol in keys:
# Display key.
print(symbol)
command = ['python', 'mc.py', '-s', str(symbol)]
print command
subprocess.call(command)
if __name__ == '__main__':
main()
The problem is that mc.py has a call that blocks
receiver = multicast.MulticastUDPReceiver ("192.168.0.2", symbolMCIPAddrStr, symbolMCPort )
while True:
try:
b = MD()
data = receiver.read() # This blocks
...
except Exception, e:
print str(e)
When I run the launcher, it just executes one of the mc.py (there are at least 39). How do I modify the launcher program to say "run the launched script in background" so that the script returns to the launcher to launch more scripts?
Edit 2
The problem is solved by replacing subprocess.call(command) with subprocess.Popen(command)
One thing I noticed though, if I say ps ax | grep mc.py, the PID seem to be all different. I don't think I care since I can kill them all pretty easily with killall.
[Correction] kill them with pkill -f xxx.py
There are several options for launching scripts from a script. The easiest are probably to use the subprocess or os modules.
I have done this several times to launch things to separate nodes on a cluster. Using os it might look something like this:
import os
for i in range(len(operations)):
os.system("python myScript.py {:} {:} > out.log".format(arg1,arg2))
using killall you should have no problem terminating processes spawned this way.
Another option is to use subprocess which has got a wide range of features and is much more flexible than os.system. An example might look like:
import subprocess
for i in range(len(operations)):
command = ['python','myScript.py','arg1','arg2']
subprocess.call(command)
In both of these methods, the processes are independent and share nothing other than a parent PID.

Python and call Matlab script outside of Python with arguments

I feel like i am almost there but need the extra push! I am trying to call a MATLAB script from Python (I'm not worried about the output of the MATLAB script - it runs independently). However, i must be able to send an input into the MATLAB script from python.
Right now I have(in python):
myvartoinput = 55
cmd = 'myscript.m'
process = Popen(["matlab", "-nosplash", "-nodesktop", "-r", cmd], shell=True)
process.communicate()
# Also, how do i 'exit' the MATLAB so it doesn't continue to run
I am not sure how to add "myvartoinput" into the 'myscript.m' file. Also, did I call the script correctly? Finally, i would like it to "exit" so it doesn't stay open in the background on my pc. Any help would be appreciated!
I have solved it differently:
import os
import subprocess
myvartoinput = 55
subprocess.call(['matlab', '-wait','-nosplash','-nodesktop','-r','myscript(\'%s\')' %(myvartoinput )])
Arguments:
'-wait' - python waits till Matlab executes script and continues;
'-nodesktop' - only matlab command window is called;
'-nosplash' - suppresses the display of the splash screen;
'-r' - argument after which follows name of a script
More info here: http://se.mathworks.com/help/matlab/matlab_env/startup-options.html

Categories

Resources