#python #ssh #signals
#python #ssh #сигналы
Вопрос:
Я пытаюсь написать программу, которая будет запускать программу на удаленном компьютере с использованием ssh и передавать ей сигналы SIGINT, не прерывая мое ssh-соединение. Если бы я работал на терминале, то это было бы легко с чем-то вроде
ssh -t -t host "command to run"
Я попробовал это со следующим скриптом:
#!/bin/bash
ssh -t -t host "program $@"
и когда я запускаю это с терминала, это работает нормально, но когда proofgeneral запускает этот скрипт и отправляет ему 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>"
Есть ли что-то, что я делаю неправильно здесь для обработки сигнала? Я попытался поместить печать в обработчик signal 2, и он ее печатает, но это также приводит к отключению ssh (я получаю «Убит сигналом 2». печатается на консоли). Перенаправляет ли python сигнал своим дочерним элементам? Есть ли способ обойти это? Есть ли более простой способ сделать это?
Спасибо за любые указания.
Ответ №1:
os.setpgrp (посмотрите на справочную страницу setpgrp) в противном случае сигнал передается дочерним элементам