2011-05-15 29 views
27

Tôi đã thử chạy những thứ như thế này:Chạy chương trình từ trăn, và có nó tiếp tục chạy sau khi kịch bản được giết

subprocess.Popen(['nohup', 'my_command'], 
       stdout=open('/dev/null', 'w'), 
       stderr=open('logfile.log', 'a')) 

này hoạt động nếu kịch bản mẹ thoát một cách duyên dáng, nhưng nếu tôi giết script (Ctrl-C), tất cả các tiến trình con của tôi cũng bị giết. Có cách nào để tránh điều này không?

Nền tảng tôi quan tâm là OS X và Linux, sử dụng Python 2.6 Python 2.7.

Trả lời

22

Cách thông thường để thực hiện việc này trên hệ thống Unix là rẽ nhánh và thoát ra nếu bạn là cha mẹ. Hãy xem os.fork(). Bạn có thể xem here để biết thêm thông tin.

Dưới đây là một chức năng mà không được công việc:

def spawnDaemon(func): 
    # do the UNIX double-fork magic, see Stevens' "Advanced 
    # Programming in the UNIX Environment" for details (ISBN 0201563177) 
    try: 
     pid = os.fork() 
     if pid > 0: 
      # parent process, return and keep running 
      return 
    except OSError, e: 
     print >>sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror) 
     sys.exit(1) 

    os.setsid() 

    # do second fork 
    try: 
     pid = os.fork() 
     if pid > 0: 
      # exit from second parent 
      sys.exit(0) 
    except OSError, e: 
     print >>sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror) 
     sys.exit(1) 

    # do stuff 
    func() 

    # all done 
    os._exit(os.EX_OK) 
+0

Nếu tôi ngã ba, và sau đó tôi giết một nửa của ngã ba (thay vì cho phép nó để thoát), sẽ giết chết quá trình mới? – James

+1

Được rồi, sau khi đọc thêm: điều này đòi hỏi phải gấp hai lần để tránh nhận tín hiệu? Tôi khá giống như quá trình cha mẹ để duy trì tương tác --- công việc của nó là để theo dõi các quá trình mà nó sinh sản --- điều đó là không thể nếu nó phải loại bỏ vỏ. – James

+0

Cảm ơn! Tôi đã thêm triển khai của tôi vào câu trả lời của bạn. – James

-6

Run subprocess.Popen() trong một thread riêng biệt.

+0

Điều này dường như không hoạt động. – James

39

Quy trình con nhận được SIGINT giống như quy trình cha mẹ của bạn vì nó nằm trong cùng một nhóm quy trình. Bạn có thể đặt đứa trẻ vào nhóm quá trình riêng của nó bằng cách gọi os.setpgrp() trong tiến trình con. Lập luận preexec_fn popen là hữu ích ở đây:

subprocess.Popen(['nohup', 'my_command'], 
       stdout=open('/dev/null', 'w'), 
       stderr=open('logfile.log', 'a'), 
       preexec_fn=os.setpgrp 
       ) 

(preexec_fn là dành cho un * chỉ x-oids Có dường như là một tương đương thô cho Windows "creationflags = CREATE_NEW_PROCESS_GROUP", nhưng tôi chưa bao giờ thử nó..)

+0

Cảm ơn câu trả lời của bạn; nó hoạt động cho tôi! Tuy nhiên, tôi tò mò tại sao lệnh của tôi dừng lại (quá trình chết) sau một thời điểm nào đó, nếu tôi bỏ qua 'stdout' &' stderr' agruments. – danuker

Các vấn đề liên quan