Reload or restart python script in a bash shell - python

I'm a brand new noob in python universe, so don't judge me too fast :-)
I'm trying to force a python script to reload or restart at the beggining of a bash script.
I've tried :
pkill -f myscript.py
and
killall myscript.py
and others...
Actually, I would like to make run the same script that call .wav files after having changed those .wav files... If I don't reload the script or restart it, it keeps playing the old files.
Maybe, there is other solutions.
Here is the script I want to reload (it's a button script playing music for my daughter)
#!/usr/bin/env python3
import pygame
from gpiozero import LED, Button
from signal import pause
pygame.init()
button_sounds = {Button(2): pygame.mixer.Sound("/home/pi/gpio-music-box/samples/1.wav"),
Button(3): pygame.mixer.Sound("/home/pi/gpio-music-box/samples/2.wav"),
Button(4): pygame.mixer.Sound("/home/pi/gpio-music-box/samples/3.wav"),
Button(17): pygame.mixer.Sound("/home/pi/gpio-music-box/samples/4.wav")}
for button, sound in button_sounds.items():
button.when_pressed = sound.play
pause()
And here is my bash script :
#!/bin/bash
***HERE THE COMMAND I NEED !***
rm -r /home/pi/gpio-music-box/samples/*
cp -r /home/pi/gpio-music-box/comptines/* /home/pi/gpio-music-box/samples/
/home/pi/gpio-music-box/music.py
Thank you very much, and scuze my english, I'm french :-)
Andy

try this
#!/bin/bash
pid=$(ps auxwww | grep nameOfScript.py | grep -v grep | awk '{print $2}')
kill -9 $pid
rm -r /home/pi/gpio-music-box/samples/*
cp -r /home/pi/gpio-music-box/comptines/* /home/pi/gpio-music-box/samples/
nohup /home/pi/gpio-music-box/music.py &
Have a nice day

Firstly, you can reduce a lot of the "noise" from ps by using output formatting. You can then stop the need for using both grep and awk by using awk to do the searching also.
ps -eo "%p %a" | awk '/nameOfScript.py/ && $1 != PROCINFO["pid"] { print "kill -9 "$1 }'
This forces ps to only print the pid (%p) and the full command (%a). The output is then piped to awk where is searches for lines with the name of the script contained. It discounts any entries with the current process id of awk and then uses this to print a kill command with the relevant process id.
Once you have verified that the kill command displays as expected, you can use awk's system function to actually run the command through:
ps -eo "%p %a" | awk '/prometheous-things.py/ && $1 != PROCINFO["pid"] { system("kill -9 "$1) }'

Related

How to tag to a python command run in a bash shell

Is it possible to tag a python program run from the command line?
Context: Said command will be run with nohup in the background, and will be killed and restarted at midnight via cron. My intention is to pipe ps into egrep for said tag, grab the pid, and kill -9 before restarting.
minimal, complete, and verifiable example
Start a python web server:
$ nohup python -m http.server 8888 &
Add a tag to the command. Note that -tag is just my imagination at work.. this is what I want:
$ nohup python -m http.server 8888 & -tag "ced72ca0-cd19-11ea-87d0-0242ac130003"
grep for tag:
$ ps aux | egrep "ced72ca0-cd19-11ea-87d0-0242ac130003"
...grab the pid from this, and kill -9
Because you're saying that you want to kill the processes through isolated cron jobs at nidnight, I guess that the $! based solutions in the linked questions (like (How to get the process ID to kill a nohup process?)) are no option for you.
In order to identity your HTTP server processes, your idea is to 'tag' them with a unique ID so the cron jobs will find them.
What you could do in your specific case is to make use of the fact that the listening TCP sockets are unique on your given machine, and retrieve the associated pid through netstat.
A bash script along the lines of:
#!/bin/bash
port=${1:-"8888"}
IP=${2:-"0.0.0.0"}
pid=`netstat -antp 2>/dev/null | grep -E "^(\S+\s+){3}$IP:$port\s+\S+\s+LISTEN" | sed -E 's/ˆ(\S+\s+){6}([0-9]+).*$/\2/'`
[[ -n "$pid" ]] && kill -TERM $pid
... that you parameterize with IP and port through your cronjob.
You can put code in file with name ced72ca0-cd19-11ea-87d0-0242ac130003,
#!/bin/bash
python -m http.server
set it executable
chmod +x ced72ca0-cd19-11ea-87d0-0242ac130003
run it
nohup ced72ca0-cd19-11ea-87d0-0242ac130003 &
and then you can kill it
pkill ced72ca0-cd19-11ea-87d0-0242ac130003
or even using only beginning of filename
pkill ced
EDIT:
Because new script doesn't get any arguments so you can run it with any argument(s) - ie. some tag/word
nohup ced72ca0-cd19-11ea-87d0-0242ac130003 hello_world &
and then you can kill it using -f
pkill -f hello_world
or even using part of word
pkill -f hello
pkill -f world
This way you can even use normal name for script and add tag
nohup my_script ced72ca0-cd19-11ea-87d0-0242ac130003 &
and kill with -f
pkill -f ced72ca0-cd19-11ea-87d0-0242ac130003
or using only part of word
pkill -f ced

how to kill python program in linux using name of the program

when i use ps -ef |grep i get the current running programs
if below shown are the currently running programs.How can i stop a program using the name of the program
user 8587 8577 30 12:06 pts/9 00:03:07 python3 program1.py
user 8588 8579 30 12:06 pts/9 00:03:08 python3 program2.py
eg. If i want to stop program1.py then how can i stop the process using the program name "program1.py"
.If any suggestions on killing the program with python will be great
By using psutil is fairly easy
import psutil
proc = [p for p in psutil.process_iter() if 'program.py' in p.cmdline()]
proc[0].kill()
To find out the process from the process name filter through the process list with psutil like in Cross-platform way to get PIDs by process name in python
Try doing this with the process name:
pkill -f "Process name"
For eg. If you want to kill the process "program1.py", type in:
pkill -f "program1.py"
Let me know if it helps!
Assuming you have pkill utility installed, you can just use:
pkill program1.py
If you don't, using more common Linux commands:
kill $(ps -ef | grep program1.py | awk '{print $2}')
If you insist on using Python for that, see How to terminate process from Python using pid?
grep the program and combine add pipe send the output in another command.
1. see program ps -ef.
2.search program grep program.
3. remove the grep that you search because is appear in the search process grep -v grep.
4.separate the process to kill with awk awk '{ print $2 }'
5. apply cmd on the previous input xarks kill -9
ps -ef | grep progam | grep -v grep | awk '{ print $2 }' | xargs kill -9
see here for more:
about pipe , awk, xargs
with python you can use os:
template = "ps -ef | grep {program} | grep -v grep | awk '{{ print $2 }}' | xargs kill -9"
import os
os.system(template.format(program="work.py"))

How to kill python script with bash script

I run a bash script with which start a python script to run in background
#!/bin/bash
python test.py &
So how i can i kill the script with bash script also?
I used the following command to kill but output no process found
killall $(ps aux | grep test.py | grep -v grep | awk '{ print $1 }')
I try to check the running processes by ps aux | less and found that the running script having command of python test.py
Please assist, thank you!
Use pkill command as
pkill -f test.py
(or) a more fool-proof way using pgrep to search for the actual process-id
kill $(pgrep -f 'python test.py')
Or if more than one instance of the running program is identified and all of them needs to be killed, use killall(1) on Linux and BSD
killall test.py
You can use the ! to get the PID of the last command.
I would suggest something similar to the following, that also check if the process you want to run is already running:
#!/bin/bash
if [[ ! -e /tmp/test.py.pid ]]; then # Check if the file already exists
python test.py & #+and if so do not run another process.
echo $! > /tmp/test.py.pid
else
echo -n "ERROR: The process is already running with pid "
cat /tmp/test.py.pid
echo
fi
Then, when you want to kill it:
#!/bin/bash
if [[ -e /tmp/test.py.pid ]]; then # If the file do not exists, then the
kill `cat /tmp/test.py.pid` #+the process is not running. Useless
rm /tmp/test.py.pid #+trying to kill it.
else
echo "test.py is not running"
fi
Of course if the killing must take place some time after the command has been launched, you can put everything in the same script:
#!/bin/bash
python test.py & # This does not check if the command
echo $! > /tmp/test.py.pid #+has already been executed. But,
#+would have problems if more than 1
sleep(<number_of_seconds_to_wait>) #+have been started since the pid file would.
#+be overwritten.
if [[ -e /tmp/test.py.pid ]]; then
kill `cat /tmp/test.py.pid`
else
echo "test.py is not running"
fi
If you want to be able to run more command with the same name simultaneously and be able to kill them selectively, a small edit of the script is needed. Tell me, I will try to help you!
With something like this you are sure you are killing what you want to kill. Commands like pkill or grepping the ps aux can be risky.
ps -ef | grep python
it will return the "pid" then kill the process by
sudo kill -9 pid
eg output of ps command:
user 13035 4729 0 13:44 pts/10 00:00:00 python (here 13035 is pid)
With the use of bashisms.
#!/bin/bash
python test.py &
kill $!
$! is the PID of the last process started in background. You can also save it in another variable if you start multiple scripts in the background.
killall python3
will interrupt any and all python3 scripts running.

Restart kivy-program respectively python with inotify

I fear that my question is a duplicate but I can't find the answer. Maybe you can help me?
I would like to restart my kivy-program if I save the kv or py file.
I tried with
inotifywait -mq -e close_write /home/name/kivy/ | while read FILE
do
pkill python
python /home/name/kivy/main.py
done
If I change a file the first time, main.py starts, but if I change it again I need to close the program by hand before it restarts.
Instead of pkill python I also tried to use
kill $(ps aux | pgrep '[p]ython' | awk '{print $2}')
but with the same result and the problem that the mintMenu.py is closing, too.
Should I use something totally different to inotify?
I'm using entr to achieve the same thing. Once installed (e.g. via brew), just run the following command in your work directory /home/name/kivy/:
find . -name "*.py" -or -name "*.kv" | entr sh -c "pkill -f python main.py ; python main.py &"

Starting/stopping a background Python process wtihout nohup + ps aux grep + kill

I usually use:
nohup python -u myscript.py &> ./mylog.log & # or should I use nohup 2>&1 ? I never remember
to start a background Python process that I'd like to continue running even if I log out, and:
ps aux |grep python
# check for the relevant PID
kill <relevantPID>
It works but it's a annoying to do all these steps.
I've read some methods in which you need to save the PID in some file, but that's even more hassle.
Is there a clean method to easily start / stop a Python script? like:
startpy myscript.py # will automatically continue running in
# background even if I log out
# two days later, even if I logged out / logged in again the meantime
stoppy myscript.py
Or could this long part nohup python -u myscript.py &> ./mylog.log & be written in the shebang of the script, such that I could start the script easily with ./myscript.py instead of writing the long nohup line?
Note : I'm looking for a one or two line solution, I don't want to have to write a dedicated systemd service for this operation.
As far as I know, there are just two (or maybe three or maybe four?) solutions to the problem of running background scripts on remote systems.
1) nohup
nohup python -u myscript.py > ./mylog.log 2>&1 &
1 bis) disown
Same as above, slightly different because it actually remove the program to the shell job lists, preventing the SIGHUP to be sent.
2) screen (or tmux as suggested by neared)
Here you will find a starting point for screen.
See this post for a great explanation of how background processes works. Another related post.
3) Bash
Another solution is to write two bash functions that do the job:
mynohup () {
[[ "$1" = "" ]] && echo "usage: mynohup python_script" && return 0
nohup python -u "$1" > "${1%.*}.log" 2>&1 < /dev/null &
}
mykill() {
ps -ef | grep "$1" | grep -v grep | awk '{print $2}' | xargs kill
echo "process "$1" killed"
}
Just put the above functions in your ~/.bashrc or ~/.bash_profile and use them as normal bash commands.
Now you can do exactly what you told:
mynohup myscript.py # will automatically continue running in
# background even if I log out
# two days later, even if I logged out / logged in again the meantime
mykill myscript.py
4) Daemon
This daemon module is very useful:
python myscript.py start
python myscript.py stop
Do you mean log in and out remotely (e.g. via SSH)? If so, a simple solution is to install tmux (terminal multiplexer). It creates a server for terminals that run underneath it as clients. You open up tmux with tmux, type in your command, type in CONTROL+B+D to 'detach' from tmux, and then type exit at the main terminal to log out. When you log back in, tmux and the processes running in it will still be running.

Categories

Resources