2012-04-05 15 views
3

私が実装しているデーモンクラスの例では、記述子のリダイレクトに使用されています。ファイル記述子のリダイレクトが固まっています

sys.stdout.flush()      
sys.stderr.flush()      
si = file(self.stdin, 'r')    
so = file(self.stdout, 'a+')    
se = file(self.stderr, 'a+', 0)   
os.dup2(si.fileno(), sys.stdin.fileno()) 
os.dup2(so.fileno(), sys.stdout.fileno()) # This line doesn't work 
os.dup2(se.fileno(), sys.stderr.fileno()) 

os.dup2(so.fileno(), sys.stdout.fileno())は機能しません。エラーは発生しません。この行の後のコードは実行されません。

私はクラスにのみ問題領域が含まれ、この例を簡素化:ちょうどスタックos.dup2(so.fileno(), sys.stdout.fileno())コードの後

class Deamon(object): 
    def __init__(self, pidfile, stdout='/dev/null'): 
     self.pidfile = pidfile 
     self.stdout = stdout 
    def get_stdout(self): 
     so = file(self.stdout, 'a+') 
     os.dup2(so.fileno(), sys.stdout.fileno()) 
     print 'executed' 

を。 どうしてですか? (@のC2H5OHコード実装と)

編集stop方法で

try:               
     pid = os.fork()            
     if pid > 0:             
      # exit first parent          
      sys.exit(0)            
    except OSError, e:            
     sys.stderr.write(           
       'fork #1 failed: %d (%s)\n' % (e.errno, e.stderror) 
       )             
     sys.exit(1)             

    os.chdir("/")             
    os.setsid()              
    os.umask(0)              


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

    # redirect standart file descriptors       
    os.setsid()              
    sys.stdin.flush()            
    sys.stdout.flush()            
    sys.stderr.flush()            

    dev_null = os.open(os.devnull, os.O_RDWR)      
    os.dup2(dev_null, sys.stdin.fileno())       
    print 'executed 1'            
    os.dup2(dev_null, sys.stdout.fileno())       
    print 'executed 2'            
    os.dup2(dev_null, sys.stderr.fileno())       
    os.close(dev_null)  

    # write pidfile 
    # FIXME: file is not writes!      
    atexit.register(self.delpid)     
    pid = str(os.getpid())      
    file(self.pidfile, 'w+').write("%s\n" % pid) 

私がしようとアウトしているself.pidfileの既存:

def stop(self):     
    print file(self.pidfile, 'r') 

これは、エラーを発生させている。

IOError: [Errno 2] No such file or directory: '/tmp/deamon-example.pid'

The proble mはそこにまだあります。ドキュメント上

+0

ところで、Pythonのドキュメントは、 '' file() 'の代わりに' 'open()'を使うことを推奨しています(http://docs.python.org/library/functions.html#file) – C2H5OH

答えて

4

あなたはPythonのファイルを混合している、これはトラブルを求めている、オペレーティングシステムのファイルディスクリプタを処理します。

あなたは(直接割り当てが完全に動作しない場合がありますので、他のモジュールは、それへの参照を取得した場合、)sys.stdoutをリダイレクトするos.dup2()を使用しての正しいですが、あなたはos.open()で、オペレーティング・システム・レベルでファイルを開く必要があります。

は、ここでは私の職場で使うデーモン化コードです:

if os.fork() > 0: 
    os._exit(0) 
os.setsid() 
sys.stdin.flush() 
sys.stdout.flush() 
sys.stderr.flush() 
null = os.open(os.devnull, os.O_RDWR) 
os.dup2(null, sys.stdin.fileno()) 
os.dup2(null, sys.stdout.fileno()) 
os.dup2(null, sys.stderr.fileno()) 
os.close(null) 

あなたは、いくつかのファイルに標準出力をリダイレクトするだけではなく、事前に定義された定数os.devnullの別のファイル名を使用したい場合

+0

私はあなたの提案を実装しようとします。問題は今解決されていません。最初の使用後にdup2、dev_nullが閉じますか?それは問題ですか?あなたのコードのいくつかをメインデーモンクラスに追加しました。解決して理解してください。 – I159

+0

あなたの質問を再読み込みした後、_getting stuck_について何を正確に理解していますか?実行が最初の 'dup2()'を超えていないことをどのように知っていますか?標準出力を '/ dev/null'にリダイレクトすると' print'-edは表示されません。実行をトレースするには、ファイルにロギングする必要があります。 – C2H5OH

+0

もう一度、私は私の質問を変更しました。問題のある行コードが実行されないと、pidfileは書き込みではなくなります。上記の質問を参照してください。どうもありがとうございます! – I159

3

http://docs.python.org/library/os.html#os.dup2

は言う:

os.dup2(fd, fd2) Duplicate file descriptor fd to fd2, closing the latter first if necessary.だから、この行: os.dup2(so.fileno(), sys.stdout.fileno()) は明らかに効果的にすべての出力をシャットダウンしsys.stdoutを閉じています。コードは「固まっている」と表示されますが、出力が表示されていないだけです。すなわち、エラーはない。その上で

、あなたはとにかく/dev/nullに標準出力をリダイレクトしている:

def __init__(self, pidfile, stdout='/dev/null'): 
    #... 
    self.stdout = stdout   # <--self.stdout points to /dev/null 
def get_stdout(self): 
    so = file(self.stdout, 'a+') # <-- opening /dev/null for append? 
    # even if the next line worked, you're appending to /dev/null and you wouldn't see any output 
    os.dup2(so.fileno(), sys.stdout.fileno()) 
+0

私は実装しようとしています@ C2H5OHの助言とあなたのアドバイスも考慮してください。 'tmp = tempfile.TemporaryFile() os.dup2(tmp.fileno()、sys.stdin.fileno()) os.dup2(tmp.fileno()、sys.stdout.fileno()) os.dup2 (tmp.fileno()、sys.stderr.fileno()) ' >この行:os.dup2(so.fileno()、sys.stdout.fileno())は明らかにsys.stdoutを終了しています。この動作を変更するには? – I159

+0

@ I159:その動作を変更する方法はわかりません。おそらくC2H5OHの答えにもっと注意を払うべきです。彼はより多くの経験とより良い洞察力を持っているように思えます。がんばろう。 – alan

+0

ありがとうございました!私はprint文を使ってデーモン化されたプログラムをトレースしていましたが、それらはos.dup2(so.fileno()、sys.stdout.fileno())の行の後に停止しました。それ以降はログファイルに直接書き込んだので、プログラムは引き続き実行されていました。 – BuvinJ

関連する問題