Console session terminates while trying to terminate script - python

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.

Related

Run command on server using Plink and keep it running after disconnecting

I have a Raspberry Pi which I use to play a video on a loop. I have a button which I use to end the video to display the desktop wallpaper which I have as a static image.
To do this I use a simple Python script that launches omxplayer and loops waiting for the button to be pressed, when pressed it kills omxplayer, waits a while then re-starts the loop.
This all works fine.
I am wanting to use plink to launch this script from a Windows machine, and have used the following:
plink.exe -ssh pi#192.168.0.201 -pw ****** "sudo python /home/pi/ftp/files/button.py"
This launches the script no problem, but because the script does not 'end' the batch file just sits there.
I have other batch files using plink to kill the script and others to turn the monitor on & off using CEC all of which work fine because plink gets a return, but because the Python script runs indefinitely there is nothing returned, so plink just seems to hang.
So..Question is, can plink be told to send the command and terminate, regardless of response, or (and I've looked for this with no joy) is there a way of setting a timeout for plink to give up waiting for a response?
If I understand your question correctly (not sure), you want plink to start the the script on the server and exit (keeping the script running).
The plink is just an alternative SSH client, similar to OpenSSH ssh. So just use the same techniques you will find on Internet for ssh.
Two of zillions of questions on this topic:
How to run a command in background using ssh and detach the session
Use SSH to start a background process on a remote server, and exit session

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

Fabric - how to use an interactive shell on remote computer?

I am trying to use Fabric to run commands on a remote machine.
This works fine, until the command on the remote machine is interactive. In that case, Fabric return the interactive shell, but force me to type the info needed, while I am trying to send a command that does everything in remote, so I can automate the procedure.
Example:
from fabric.api import *
env.hosts=['myhost.mydomain']
env.user='root'
run(test1/myapp; exectask; exit)
I run a cli application on a remote machine, that uses interactive shell, so it is waiting for me to type the command (exectask); then once done, to exit, I call the exit command.
What happens now is that the app launch, Fabric show me the interactive UI and I still need to type exectask and after, exit.
How can I tell fabric to run that app, then pass the command to the interactive shell and then the exit to quit?
I see that Fabric has the prompt feature, but that's to ask the user to input data, while I want to just pass the commands and get the result back.
You might want to look into pexpect, a pure-Python module that works like expect. Essentially, it allows your program to spawn an external program or process, then control it just like a human was interacting with it. You program in what the program should expect to see (hence the name), then what action(s) to take.

Spawn a subprocess in foreground, even after python exits

Assume there exists a python script resolve_ip.py which magically returns the string IP of a machine we care about.
I'm interested in learning how to achieve the python equivalent of the following bash command:
user#host:~$ ssh $(./resolve_ip.py)
In this bash example, after the python script runs, it is replaced or rather substituted with its return value which is, in turn, provided as a input to the program ssh. The result is, the python program terminates and the user interacts with ssh initialization.
The problem is, this solution requires the use of either 2 scripts (a bash script to run ssh, combined with the python script to return the arguments) or alternatively human intervention to type the bash command directly as formatted above.
Question:
Is there a way, only using python, to start/fork an interactive service (like ssh), by using subprocess or some comparable module, and have this forked child process remain alive in the foreground, even after its parent (python) has sys.exit()'d?
Considerations:
In this case, the point of this question is not to script the submission of ssh credentials to ssh from within Python. It is how to spawn a subprocess which continues to run foregrounded after its parent/spawner terminates.
EDIT:
The following resources are related:
Run a program from python, and have it continue to run after the script is killed
how to spawn new independent process in python
Indefinite daemonized process spawning in Python
Python spawn off a child subprocess, detach, and exit
I think you want to "exec". Like this:
import resolve_ip
import os
host = resolve_ip.get_host_to_use() # you figure this part out
os.execlp('ssh', 'ssh', host)
That will replace the Python interpreter process image with the ssh process image, and keep running. So you will end up as if you had run ssh instead of Python, and the interpreter will no longer execute at all.

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