首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >更改DenyHosts报告:从Python调用外部命令

更改DenyHosts报告:从Python调用外部命令
EN

Stack Overflow用户
提问于 2012-03-21 08:16:25
回答 2查看 492关注 0票数 1

首先,我不知道Python的第一件事.所以我真的可以用你的任何指点。我确实知道一些Perl、Bash脚本和一些C++。

我正在运行DenyHosts (http://denyhosts.sourceforge.net/),它不时地通过电子邮件向我发送一条消息,即IP地址添加到/etc/deny.host。例如:

代码语言:javascript
复制
Added the following hosts to /etc/hosts.deny:

87.215.133.109 (unknown)

----------------------------------------------------------------------

到目前为止还不错,但是我想在这条消息中加上IP地址的国家。为此,我创建了一个小型Perl脚本,用于输出国家:

代码语言:javascript
复制
/usr/local/bin/geo-ip.pl --short 87.215.133.109
Netherlands

所以我要做的就是从Python调用这个Perl脚本,然后在消息字符串中填充结果。我找到了我怀疑需要修改的源代码,但正如消息顶部所宣布的,我不知道Python的第一件事。

这是在report.py中调用子例程的主程序的一个片段。

deny_hosts.py:

代码语言:javascript
复制
#print deny_hosts
new_denied_hosts, status = self.update_hosts_deny(deny_hosts)
if new_denied_hosts:
    if not status:
        msg = "WARNING: Could not add the following hosts to %s" % self.__prefs.get('HOSTS_DENY')
    else:
        msg = "Added the following hosts to %s" % self.__prefs.get('HOSTS_DENY')
    self.__report.add_section(msg, new_denied_hosts)
    if self.__sync_server: self.sync_add_hosts(new_denied_hosts)
    plugin_deny = self.__prefs.get('PLUGIN_DENY')
    if plugin_deny: plugin.execute(plugin_deny, new_denied_hosts)

我觉得这个零钱应该在这里找个地方。report.py定义了add_section:

代码语言:javascript
复制
def add_section(self, message, iterable):
    self.report += "%s:\n\n" % message
    for i in iterable:
        if type(i) in (TupleType, ListType):
            extra = ": %d\n" % i[1]
            i = i[0]
        else:
            extra = ""
        if self.hostname_lookup:
            hostname = self.get_hostname(i)
            debug("get_host: %s", hostname)
        else: hostname = i

        self.report += "%s%s\n" % (hostname, extra)

        if self.use_syslog:
            syslog.syslog("%s - %s%s" %(message, hostname, extra))
    self.report += "\n" + "-" * 70 + "\n"

请帮助我更改代码,这样它就会发出如下消息:

代码语言:javascript
复制
Added the following hosts to /etc/hosts.deny:

87.215.133.109 (Netherlands, unknown)

----------------------------------------------------------------------

EDIT3:,这就是我解决它的方法。输出与原始消息相同。更改源后,需要重新启动守护进程(sudo /etc/init.d/denyhost重新启动)

代码语言:javascript
复制
    def add_section(self, message, iterable):
    # added geo-ip
    # moving this from statement to the top of the file makes pycheck generate
    # a lot of errors, so I left it here.
    from subprocess import Popen, PIPE
    # end geo-ip hack import
    self.report += "%s:\n\n" % message
    for i in iterable:
        if type(i) in (TupleType, ListType):
            extra = ": %d\n" % i[1]
            i = i[0]
        else:
            extra = ""
        if self.hostname_lookup:
            hostname = self.get_hostname(i)
            debug("get_host: %s", hostname)
        else: hostname = i

        # self.report += "%s%s\n" % (hostname, extra)
        # JPH: added geo-ip
        geocmd = "/usr/local/bin/geo-ip.pl --short %s" % i
        country = Popen( geocmd, shell=True, stdout=PIPE).communicate()[0]
        country = country.strip()
        self.report += "%s%s\n%s\n" % (hostname, extra, country)
        # end geo-ip hack            

        if self.use_syslog:
            syslog.syslog("%s - %s%s" %(message, hostname, extra))
    self.report += "\n" + "-" * 70 + "\n"

还可以帮助我理解我改变了什么,这样我今天也可以学到一些Python。

EDIT2:为了共享到geo-ip.pl脚本http://wirespeed.xs4all.nl/mediawiki/index.php/Geo-ip.pl的链接

EDIT1:重新编译是在源代码更改时自动完成的,从而回答了下面的问题。第二个问题是,我在系统中找到了两个匹配的文件:

  • /usr/share/denyhosts/DenyHosts/report.py
  • /usr/share/denyhosts/DenyHosts/report.pyc

其中.py是源代码,我怀疑.pyc实际上正在执行。因此,当我更改源代码时,如果以后不以某种方式编译它,我不会感到惊讶。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-03-21 08:27:51

我将只回答您问题的具体部分,即如何通过python调用您的perl脚本并获得输出。这个信息的位置太模糊了,我从你的片段里猜不出来……

代码语言:javascript
复制
from subprocess import Popen, PIPE

hostIP = "87.215.133.109"
cmd = "/usr/local/bin/geo-ip.pl --short %s" % hostIP
output = Popen(cmd, shell=True, stdout=PIPE).communicate()[0]

## alternate form ##
# cmd = ["/usr/local/bin/geo-ip.pl, "--short", hostIP]
# output = Popen(cmd, stdout=PIPE).communicate()[0]

print output.strip() 
# Netherlands

更新

由于我同时在Popen行上做了一些事情,而且您对python (基于下面的评论)是新手,所以我想为您细分一下这一行.

代码语言:javascript
复制
# this call to Popen actually returns a 
# Popen object with a number of methods and attributes
# to interact with the process that was just created
p = Popen(cmd, shell=True, stdout=PIPE)

# communicate() is a method of a Popen object which
# allows you to wait for the return output of the pipes
# that you named (or send data to stdin)
# It blocks until data is ready and returns a tuple (stdout, stderr)
stdout, stderr = p.communicate()

# We only wanted the stdout in this case, so we took the first index
output = p.communicate()[0]

# output is a string, and strings have the strip() method to remove 
# surrounding whitespace
stripped_output = output.strip()
票数 2
EN

Stack Overflow用户

发布于 2012-03-21 08:28:42

这可能会起作用:

代码语言:javascript
复制
import subprocess
country = subprocess.check_output(
    ["/usr/local/bin/geo-ip.pl", "--short", "87.215.133.109"])
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9800833

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档