1

首先让我说,我知道使用 subprocess 模块会更好,但我正在编辑其他人的代码,并且我正在尝试进行尽可能少的更改,其中包括避免导入任何新模块。因此,如果可能的话,我想坚持使用当前导入的模块(操作系统、系统和路径)。

代码当前(在一个名为 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,因为如果可以避免,我宁愿不使用 shell 环境(安全问题,可能的性能?我承认我在这里很偏执,但是如果我可以避免 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) 两次,您需要保存 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 回答