2013-03-04 31 views
6

retry.py olarak adlandırılan başarısız olduğunda komutları yinelemek için basit bir sarmalayıcı komut dosyası yazdım. Ancak çocuk komutunun çıktısını görmek istediğimden bazı pty hileleri çekmek zorunda kaldım. Bu rsync gibi programlar için iyi çalışır, ancak scp gibi diğerleri, ilerleme ölçer gibi şeyler göstermek için ek test uygular. Ben sarıcı komut dosyası olsa çalıştırdığınızda başarısızTerminal ön plan işlem grubunu bir pty altında çalıştığım bir işlem için nasıl ayarlayabilirim?

getpgrp() == tcgetpgrp(STDOUT_FILENO); 

:

scp kodu geniş olan bir test vardır.

./tty_tests 
isatty reports 1 
pgrps are 13619 and 13619 

ve: Ben tcsetpgrp (kullanarak denedim

./retry.py -v -- ./tty_tests 
command is ['./tty_tests'] 
isatty reports 1 
pgrps are 13614 and -1 
child finished: rc = 0 
Ran command 1 times 

) Pty fd yıllardan ancak bu konuda bir IOCTL olarak biter sen benim basit tty_test.c test durumu ile görebileceğiniz gibi ptys için bir -EINVAL sonuçlanır. Mümkünse Python subprocess makinelerini kullanmaya devam etmeyi tercih edersem ya da bunun için manüel olarak fork/execve'ing yapılması gerekecek mi?

from argparse import ArgumentParser 
import os 
import signal 
import subprocess 
import itertools 

# your argumentparser stuff goes here 

def become_tty_fg(): 
    os.setpgrp() 
    hdlr = signal.signal(signal.SIGTTOU, signal.SIG_IGN) 
    tty = os.open('/dev/tty', os.O_RDWR) 
    os.tcsetpgrp(tty, os.getpgrp()) 
    signal.signal(signal.SIGTTOU, hdlr) 

if __name__ == "__main__": 
    args = parser.parse_args() 

    if args.verbose: print "command is %s" % (args.command) 
    if args.invert and args.limit==None: 
     sys.exit("You must define a limit if you have inverted the return code test") 

    for run_count in itertools.count(): 
     return_code = subprocess.call(args.command, close_fds=True, 
             preexec_fn=become_tty_fg) 
     if args.test == True: break 
     if run_count >= args.limit: break 
     if args.invert and return_code != 0: break 
     elif not args.invert and return_code == 0: break 

    print "Ran command %d times" % (run_count) 

setpgrp() çağrı aynı oturumda yeni bir süreç grubunu oluşturur:

cevap

9

Sana alt sürecine yepyeni pty sağlamanız gerekir yoksa buna programınızı kısmak inanıyorum Böylece, yeni işlem kullanıcıdan ctrl-c/ctrl-z/etc alır ve yeniden deneme komut dosyanız olmaz. Daha sonra tcsetpgrp(), yeni işlem grubunu kontrol eden tty üzerindeki ön plana dönüştürür. Yeni işlem, bir SIGTTOU olur (setpgrp(), bir arka plan işlem grubunda olduğu için), bu işlem normalde işlemi durdurur, bu nedenle SIGTTOU göz ardı edilir. SIGTTOU işleyicisini, beklenmeyen bir sinyal tablosuyla karıştırılan alt işlem olasılığını en aza indirmek için, daha önce olduğu gibi geri getirdik.

Alt işlem şu anda tty için önalan grubunda olduğundan, tcgetpgrp() ve getpgrp() değeri aynı olacaktır ve isatty (1) doğru olacaktır (retry.py öğesinden devraldığı stdout varsayılarak) bir tty). Alt işlem ile tty arasındaki proxy trafiğine gerek duymazsınız, bu da tüm olay işleme ve fcntl-nonblocking ayarını iptal etmenizi sağlar.

+0

Ben denemek için bir verdi ve herhangi bir etkisi yoktur: > retry.py -v - komut [ '/home/ajb/mysrc/retry.git olan ~/mysrc/retry.git/tty_tests/tty_tests '] isatty raporları 1 pgrps 28268 ve -1 çocuk tamamlandı: rc = 0 Ran komutu 1 kez – stsquad

+0

Bazı kodun tamamını yapıştırabilir misiniz? –

+0

OH! Sorunuzdaki retry.py'ye bir bağlantı verdiğinizi fark ettim. Ben sadece yardımcı olmaya çalışıyorum ve hostname gibi görünen bir şeyden bir bağlantı yapmak için stackoverflow olduğunu düşündüm. Bir bakacağım. –