stop python program when ssh pipe is broken

2024/9/23 4:30:23

I'm writing a python script with an infinite while loop that I am running over ssh. I would like the script to terminate when someone kills ssh. For example:

The script (script.py):

while True:# do something

Will be run as:

ssh foo ./script.py

When I kill the ssh process, I would like the script on the other end to stop running.

I have tried looking for a closed stdout:

while not sys.stdout.closed:# do something

but this didn't work.

How do I achieve this?

Edit:

The remote machine is a Mac which opens the program in a csh:

502 29352 ??         0:00.01 tcsh -c python test.py
502 29354 ??         0:00.04 python test.py

I'm opening the ssh process from a python script like so:

p = Popen(['ssh','foo','./script.py'],stdout=PIPE)while True:line = p.stdout.readline()# etc

EDIT

Proposed Solutions:

  1. Run the script with while os.getppid() != 1

This seems to work on Linux systems, but does not work when the remote machine is running OSX. The problem is that the command is launched in a csh (see above) and so the csh has its parent process id set to 1, but not the script.

  1. Periodically log to stderr

This works, but the script is also run locally, and I don't want to print a heartbeat to stderr.

  1. Run the script in a pseduo tty with ssh -tt.

This does work, but has some weird consequences. Consider the following:

remote_script:

#!/usr/bin/env python
import os
import time
import syswhile True:print time.time()sys.stdout.flush()time.sleep(1)

local_script:

#!/usr/bin/env python
from subprocess import Popen, PIPE
import timep = Popen(['ssh','-tt','user@foo','remote_script'],stdout=PIPE)while True:line = p.stdout.readline().strip()if line:print lineelse:breaktime.sleep(10)

First of all, the output is really weird, it seems to keep adding tabs or something:

[user@local ~]$ local_script 
1393608642.71393608643.711393608644.71Connection to foo closed.

Second of all, the program does not quit the first time it receives a SIGINT, i.e. I have to hit Ctrl-C twice in order to kill the local_script.

Answer

Okay, I have a solution for you

When the ssh connection closes, the parent process id will change from the pid of the ssh-deamon (the fork that handles your connection) to 1.

Thus the following solves your problem.

#!/usr/local/bin/pythonfrom time import sleep
import os#os.getppid() returns parent pid
while (os.getppid() != 1):sleep(1)pass

Can you confirm this is working in your end too :)

edit

I saw you update.

This is not tested, but to get this idea working on OSX, you may be able to detect if the process of the csh changes. The code below only illustrates an idea and has not been tested. That said i think it would work, but it would not be the most elegant solution. If a cross platform solution using signals could be found, it would be preferred.

def do_stuff():sleep(1)if sys.platform == 'darwin':tcsh_pid = os.getppid()sshfork_pid = psutil.Process(tcsh_pid).ppidwhile (sshfork_pid == psutil.Process(tcsh_pid).ppid)do_stuff()elif sys.platform == 'linux':while (os.getppid() != 1):sleep(1)
else:raise Exception("platform not supported")sys.exit(1)
https://en.xdnf.cn/q/71863.html

Related Q&A

How do I export a TensorFlow model as a .tflite file?

Background information:I have written a TensorFlow model very similar to the premade iris classification model provided by TensorFlow. The differences are relatively minor: I am classifying football ex…

Using plotly in Jupyter to create animated chart in off-line mode

Ive been trying to get the "Filled-Area Animation in Python" example to work using plotly in offline mode in a Jupyter notebook. The example can be found here: https://plot.ly/python/filled-a…

Django: How to unit test Update Views/Forms

Im trying to unit test my update forms and views. Im using Django Crispy Forms for both my Create and Update Forms. UpdateForm inherits CreateForm and makes a small change to the submit button text. Th…

Why is Python faster than C++ in this case?

A program in both Python and C++ is given below, which performs the following task: read white-space delimited words from stdin, print the unique words sorted by string length along with a count of eac…

Python - write headers to csv

Currently i am writing query in python which export data from oracle dbo to .csv file. I am not sure how to write headers within file. try:connection = cx_Oracle.connect(user,pass,tns_name)cursor = con…

Opening/Attempting to Read a file [duplicate]

This question already has answers here:PyCharm shows unresolved references error for valid code(31 answers)Closed 5 years ago.I tried to simply read and store the contents of a text file into an array,…

How to pass custom settings through CrawlerProcess in scrapy?

I have two CrawlerProcesses, each is calling different spider. I want to pass custom settings to one of these processes to save the output of the spider to csv, I thought I could do this:storage_setti…

numpy how to slice index an array using arrays?

Perhaps this has been raised and addressed somewhere else but I havent found it. Suppose we have a numpy array: a = np.arange(100).reshape(10,10) b = np.zeros(a.shape) start = np.array([1,4,7]) # ca…

How to import _ssl in python 2.7.6?

My http server is based on BaseHTTPServer with Python 2.7.6. Now I want it to support ssl transportation, so called https.I have installed pyOpenSSL and recompiled python source code with ssl support. …

Unexpected Indent error in Python [duplicate]

This question already has answers here:Im getting an IndentationError (or a TabError). How do I fix it?(6 answers)Closed 4 years ago.I have a simple piece of code that Im not understanding where my er…