Я пытаюсь написать программу, которая будет запускать программу на удаленном компьютере, используя ssh, и передавать ей сигналы SIGINT, не разрушая мое соединение ssh. Если бы я работал на терминале, это было бы легко с чем-то вроде
ssh -t -t host "command to run"
Я пробовал это с помощью следующего скрипта:
#!/bin/bash
ssh -t -t host "program $@"
и когда я запускаю его из терминала, он работает нормально, но когда корректор запускает этот скрипт и отправляет его SIGINT, он просто завершает работу программы (я думаю, он не может выделить терминал?).
У меня следующий беспорядок кода:
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)
который я вызываю, используя что-то вроде:
remote.py --client ssh -t -t host "remote.py --server <program-to-run> <args>"
Есть ли что-то, что я делаю здесь неправильно, чтобы обработать сигнал? Я попытался поместить отпечаток в обработчик сигнала 2, и он печатает его, но он также убивает ssh (на консоли выводится сообщение «Убито сигналом 2»). Питон передает сигнал своим детям? Есть ли способ обойти это? Есть ли более простой способ сделать это?
Спасибо за любые указатели.