1

最初に、subprocess モジュールを使用する方が良いことはわかっていますが、他の人のコードを編集していて、新しいモジュールのインポートを避けるなど、変更をできるだけ少なくしようとしています。したがって、可能な限り、現在インポートされているモジュール (os、sys、およびパス) に固執したいと思います。

現在、コードは次のとおりです (postfix-to-mailman.py という名前のファイルにあり、一部のユーザーにはなじみがあるかもしれません)。

if local in ('postmaster', 'abuse', 'mailer-daemon'):
  os.execv("/usr/sbin/sendmail", ("/usr/sbin/sendmail", 'first@place.com'))
  sys.exit(0)

これは正常に動作します (ただし、sys.exit(0) は呼び出されない可能性があるため、不要であると思います)。

これにより、現在のプロセスが /usr/sbin/sendmail への呼び出しに置き換えられ、引数 /usr/sbin/sendmail (argv[0] 自体) と 'someaddress@someplace.com' が渡され、次に環境が渡されます。現在のプロセス (sys.stdin の電子メール メッセージを含む) を子プロセスに送信します。

私がやりたいことは、基本的に、これを行う前にメッセージの別のコピーを送信することです。実行が停止するため、execv を再度使用することはできません。だから私は次のことを試しました:

if local in ('postmaster', 'abuse', 'mailer-daemon'):
  os.spawnv(os.P_WAIT, "/usr/sbin/sendmail", ("/usr/sbin/sendmail", 'other@place.com'))
  os.execv("/usr/sbin/sendmail", ("/usr/sbin/sendmail", 'first@place.com'))
  sys.exit(0)

ただし、メッセージは other@place.com に送信されますが、first@place.com には送信されません。

spawn を使用すると子プロセスが開始され、現在のプロセスが返されたときに (または P_NOWAIT が使用されている場合は待機せずに) 実行が継続されると思っていたので、これには驚きました。

ちなみに、最初に os.P_NOWAIT を試してみたのですが、other@place.com で受信したメッセージが空だったので、少なくとも P_WAIT を使用すると、メッセージはそのまま通過しました。しかし、それでも問題である first@place.com に送信されることはありませんでした。

回避できるなら os.system を使用したくないです。回避できるならシェル環境に行きたくないからです (セキュリティの問題、パフォーマンスの可能性? 私はここで妄想的であることを認めますが、 os.system を避けることができます)。

私が考えることができる唯一のことは、os.spawnv への呼び出しが何らかの形で sys.stdin の内容を消費/空にしていることですが、それも実際には意味がありません。アイデア?

4

2 に答える 2

1

意味がないかもしれませんが、そうであるように見えます

import os

os.spawnv(os.P_WAIT,"/usr/bin/wc", ("/usr/bin/wc",))
os.execv("/usr/bin/wc", ("/usr/bin/wc",))

$ cat j.py | python j.py 
       4       6     106
       0       0       0

その場合、あなたはこのようなことをするかもしれません

import os
import sys

buf = sys.stdin.read()
wc = os.popen("usr/sbin/sendmail other@place.com","w")
wc.write(buf)
wc.close()
wc = os.popen("usr/sbin/sendmail first@place.com","w")
wc.write(buf)
wc.close()
sys.exit(0)
于 2010-07-17T01:25:58.773 に答える
0

sys.stdin はパイプであり、それらはシークできないため、そのファイルのようなオブジェクトを巻き戻してその内容を再度読み取ることはできません。実際に sendmail(1) を 2 回呼び出すには、stdin の内容を、できれば一時ファイルに保存する必要がありますが、データのサイズが制限されていることが保証されている場合は、代わりにメモリに保存することができます。

しかし、なぜトラブルを経験するのですか?メールのコピーを個別にキューに入れておく必要がありますか (必要な場合はその理由)? sendmail(1) の最初の呼び出しに必要な受信者を追加するだけです。追加の受信者は、電子メール ヘッダーには表示されません。

if local in ('postmaster', 'abuse', 'mailer-daemon'):
  os.execv("/usr/sbin/sendmail", ("/usr/sbin/sendmail", 
                                  'first@place.com',
                                  'otheruser@example.com'))
  sys.exit(0)

ああ、何らかの理由で os.execv() が失敗した場合、sys.exit(0) 行が実行されます。これは、/usr/sbin/sendmail が実行できない場合に発生します。たとえば、実行可能ファイルが存在しないか、実際には実行可能でない場合です。つまり、これは注意が必要なエラー状態です。

于 2010-08-08T13:38:31.207 に答える