开发者

Catch & Ignore Signal

I'm trying to write a program that will run a program on a remote machine using ssh and pass it SIGINT signals without killing my ssh connection. If I was running on a terminal, then this would be easy with something like

ssh -t -t host "command to run"

I tried this with the following script:

#!/bin/bash

ssh -t -t host "program $@"

and when I run that from the terminal it works fine, but when proofgeneral runs this script and sends it SIGINT it just ends up killing the program (I guess it can't allocate a terminal?).

I've got the following mess of code:

CTRL_C = "<CTRL-C>"

def endpoint(proc, handler):
    signal.signal(2, signal.SIG_IGN)

    inp = ""
    out = ""
    err = ""

    inp_from_fd = sys.stdin.fileno()
    inp_to_fd   = proc.stdin.fileno()
    out_from_fd = proc.stdout.fileno()
    out_to_fd   = sys.stdout.fileno()
    err_from_fd = proc.stderr.fileno()
    err_to_fd   = sys.stderr.fileno()

    while True:
       try:
           ins,outs,_ = select.select([inp_from_fd, out_from_fd, err_from_fd],
                                      [inp_to_fd, out_to_fd, err_to_fd],
                                      [])
           for fd in ins:
               if fd == inp_from_fd:
                   k   = os.read(fd, 1024)
                   if k == "":
                       os.close(proc.stdin.fileno())
                       return
                   inp = inp + k
               elif fd == out_from_fd:
                   k   = os.read(fd, 1024)
                   out = out + k
               elif fd == err_from_fd:
                   k   = os.read(fd, 1024)
                   err = err + k
               else:
                   assert False
           for fd in outs:
               if fd == inp_to_fd:
                   while CTRL_C in inp:
                       proc.send_signal(2)
                       p = inp.find(CTRL_C)
                       inp = inp[0:p] + inp[p+len(CTRL_C):]
                   k = os.write(fd, inp)
                   inp = inp[k:]
               elif fd == out_to_fd:
                   k = os.write(fd, out)
                   out = out[k:]
               elif fd == err_to_fd:
                   k = os.write(fd, err)
                   err = err[k:]
               else:
                   assert False
       except select.error:
           pass
       except KeyboardInterrupt:
           handler()
       except IOError, e:
           pass

def usage(args):
    print "must specify --client or --server" 

if __name__ == '__main__':
    if len(sys.argv) == 1:
        usage(sys.argv)
    elif sys.argv[1] == '--server':
        proc = subprocess.Popen(sys.argv[2:],
                    开发者_开发百科            stdin=subprocess.PIPE,
                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        def INT():
            proc.stdin.write(CTRL_C)
            proc.stdin.flush()
        endpoint(proc, INT)
    elif '--client' in sys.argv:
        proc = subprocess.Popen(sys.argv[2:],
                                stdin=subprocess.PIPE,
                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        import time
        time.sleep(1)
        def INT():
            pass
        endpoint(proc, INT)
    else:
        usage(sys.argv)

which I'm invoking using something like:

remote.py --client ssh -t -t host "remote.py --server <program-to-run> <args>"

Is there something that I'm doing wrong here to handle the signal? I've tried putting a print in the signal 2 handler and it does print it, but it is also killing ssh (I'm getting "Killed by signal 2." printed on the console). Is python forwarding the signal to it's children? Is there a way to get around this? Is there an easier way to do this?

Thanks for any pointers.


os.setpgrp (look at setpgrp manpage) otherwise the signal is propagated to children

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜