How to stop a python script launching many subprocesses from terminal - python

I have a python script which launches a sequence of subprocesses in a loop:
for c in cmds:
subprocess.call(c, shell=True)
When the script is running in terminal, I try to stop it with Ctrl+C or Ctrl+D, however, it will continue to launch next subprocess. How can I terminate the whole python script at once?

What likely happens is that ctrl-C is intercepted by you sub-process (running on the same terminal) and never gets to your Python script. What you can do is to check the return value of subprocess.call to see whether the child process was killed by a signal and decide whether you want to stop submitting new processes.

Related

When using the python script as CGI, Subprocess Popen not able to run background process

I am trying to run another Python script in background from a CGI python script and want this script to run the process in background without waiting for the other script to complete. Somehow when I am running the same from Linux shell, I can run the other python script in background. But when I tried doing the same through CGI, The front end keeps on loading until the other script completes and not just make it run in background.
I have tried running the same on the Linux Shell and it works. When I shifted to CGI that is when the script waits for the other process to complete.
python1.py:
command = [sys.executable,'python2.py', str(senddata)]
proc=subprocess.Popen(command,shell=False,stdin=None,stdout=None,stderr=None,close_fds=True)
print("Content-type: text/html\r\n\r\n")
print("The script is running in background! Expect an email in 10 minutes.")
python2.py:
This script takes 2-5 minutes to execute and then sends an email to the group.
The expected output is to have this message:
The script is running in background! Expect an email in 10 minutes.
And run python2.py in background without waiting for it to complete.
The webserver will keep the client response active (causing the client to stay in a "loading" state) until all of the output from the CGI program has been collected and forwarded to the client. The way the webserver knows that all output has been collected is that it sees the standard output stream of the CGI process being closed. That normally happens when the CGI process exits.
The reason why you're having this problem is that when subprocess.Popen is told to execute a program with stdout=None, the spawned program will share its parent's standard output stream. Here that means that your background program shares the CGI process's standard output. That means that from the webserver's point of view that stream remains open until both of the processes exit.
To fix, launch the background process with stdout=subprocess.PIPE. If the background process misbehaves if its stdout gets closed when the CGI process dies, try launching it with stdout=open('/dev/null') instead.
The background process's stdin and stderr will have the same issue; they will be shared with the CGI process. AFAIK sharing those will not cause trouble as long as the background process does not attempt to read from its standard input, but if it does do that (or if you just want to be cautious) you can treat them the same way as you treat stdout and either set them to subprocess.PIPE or associate them with /dev/null.
More detail is at https://docs.python.org/2/library/subprocess.html#popen-constructor

Cannot find daemon after daemonizing python script

I daemonized a python script using the daemonize python library, but now I cannot find the daemon that it spawned. I want to find the daemon and kill it to make some changes to the script.
I used the following to daemonize:
pidfile='/tmp/filename.pid'
daemon = Daemonize(app='filename',pid=pidfile, action=main)
print("daemon started")
daemon.start()
Open a terminal window and try the following:
ps ax | grep <ScriptThatStartedTheDaemon>.py
It should return the PID and the name of the process. Once you have the PID, do:
kill <pid>
Depending on how many times you've run your script, you may have multiple daemons running, in which case you'd want to kill all of them.
To make sure the process was terminated, run the first line of code again. The process with the PID that you killed shouldn't show up if it was successfully terminated.

Python hangs when executing a shell script that runs a process as a daemon

I am trying to use os.system (soon to be replaced with subprocess) to call a shell script (which runs a process as a daemon)
os.system('/path/to/shell_script.sh')
The shell script looks like:
nohup /path/to/program &
If I execute this shell script in my local environment, I have to hit enter before being returned to the console as the shell script is running a process as a daemon. If I do the above command in python, I also have to hit enter before being returned to the console.
However, if I do this in a python program, it just hangs forever.
How can I get the python program to resume execution after calling a shell script that runs a process as a daemon?
From here -
Within a script, running a command in the background with an ampersand (&)
may cause the script to hang until ENTER is hit. This seems to occur with
commands that write to stdout.
You should try redirecting your output to some file (or null if you do not need it), maybe /dev/null , if you really do not need the output.
nohup /path/to/program > /dev/null &
Why don't you trying using a separate thread?
Wrap up your process into something like
def run(my_arg):
my_process(my_arg)
thread = Thread(target = run, args = (my_arg, ))
thread.start()
Checkout join and lock for more control over the thread execution.
https://docs.python.org/2/library/threading.html

Console session terminates while trying to terminate script

I'm trying to write a Python code that is to check on network settings on a network switch. Expecting errors, I have included 'exit.sys()' commands in case an error or non-matching data shows up. However, while I want it to terminate and throw an exception in the script, it also terminates the CLI session (Putty). What would be the best command to be able to throw an exception and terminate only the script that is running on the switch without terminating Putty?
if isc_port.endswith('g'):
isc_port = isc_port[:-1]
elif isc_port.endswith('G'):
sys.exit("The ISC port is also configured as an MLAG port. Please correct.")
#return ELM
Calling sys.exit() only exits the (python) process. It does not (directly) affect putty or any other terminal (xterm, gnome-terminal, etc.).
PuTTY terminates when the connection it has is closed by the remote service. Often, eg with ssh or telnet, this occurs when the program that is run by logging in terminates. Usually the program is a shell (eg /bin/sh, /bin/bash, etc.), which when run interactively does not terminate until you type 'exit' (or send it EOF, typically Ctrl-D). When a shell is run non-interatively it will usually terminate when the command it runs terminates.
Perhaps you are using your python program as the shell when you log in? In that case, don't exit when you don't want to exit. Perhaps you have a shell script that runs your program, then exits, when you log in? If so, change that script to not exit.
Also, I have usually seen PuTTY keep the window open, so all output is still visibile, until you acknowledge the notice that the network connection was lost. It is the Windows DOS/cmd.exe window that I have seen close immediately upon termination of the program that it runs.

Why doesn't os.system ignore SIGINT?

I am reading Linux System Programming.
When introducing the system(command) function, the book states that during execution of the command, SIGINT is ignored.
So, assuming that os.system is just a wrapper of the underlying system function, I try the following:
loop.py
while True:
print 'You should not be able to CTRL+C me ;p'
test_loop.py
import os
os.system("python loop.py")
Now that I'm executing loop.py with system, I'm expecting SIGINT to be ignored, but when I use CTRL+C on the running program it still get killed.
Any idea why os.system differ from the system() function?
SIGINT is ignored by the application that calls system (for as long as system is executing). It's not ignored by the application that's spawned by system. So if you hit CTRL+c, that will abort the execution of loop.py, but not of test_loop.py. So if you add some code after the call to system, you'll see that that code will execute after you press CTRL+c.

Categories