用Bash解析dhcpd.lease文件

用Bash解析dhcpd.lease文件,bash,parsing,grep,Bash,Parsing,Grep,我试图用Basel解析我的dhcpd.lease文件。典型条目如下所示: lease 192.168.20.4 { starts 6 2009/06/27 00:40:00; ends 6 2009/06/27 12:40:00; hardware ethernet 00:00:00:00:00:00; uid 00:00:00:00:00:00; client-hostname "examle-workstation1"; } lease 192.16

我试图用Basel解析我的dhcpd.lease文件。典型条目如下所示:

lease 192.168.20.4 {
    starts 6 2009/06/27 00:40:00;
    ends 6 2009/06/27 12:40:00;
    hardware ethernet 00:00:00:00:00:00;
    uid 00:00:00:00:00:00;
    client-hostname "examle-workstation1";
}
lease 192.168.20.5 {
    starts 6 2009/06/27 00:40:00;
    ends 6 2009/06/27 12:40:00;
    hardware ethernet 00:00:00:00:00:00;
}
dhcpd-leases
-- 192.168.20.0
-- 192.168.30.0
-- 192.168.40.0
[...]
我得到的所有信息都是MAC,我想要的是IP和客户端主机名。但是,可能没有客户端主机名。条目如下所示:

lease 192.168.20.4 {
    starts 6 2009/06/27 00:40:00;
    ends 6 2009/06/27 12:40:00;
    hardware ethernet 00:00:00:00:00:00;
    uid 00:00:00:00:00:00;
    client-hostname "examle-workstation1";
}
lease 192.168.20.5 {
    starts 6 2009/06/27 00:40:00;
    ends 6 2009/06/27 12:40:00;
    hardware ethernet 00:00:00:00:00:00;
}
dhcpd-leases
-- 192.168.20.0
-- 192.168.30.0
-- 192.168.40.0
[...]
我的第一个想法是grep lease属性、hardware ethernet属性和uid属性,并将它们放在一行中。然后解析它

但我的问题是,我有一个很大的文件,在许多文件中分配了许多条目。这棵树看起来像这样:

lease 192.168.20.4 {
    starts 6 2009/06/27 00:40:00;
    ends 6 2009/06/27 12:40:00;
    hardware ethernet 00:00:00:00:00:00;
    uid 00:00:00:00:00:00;
    client-hostname "examle-workstation1";
}
lease 192.168.20.5 {
    starts 6 2009/06/27 00:40:00;
    ends 6 2009/06/27 12:40:00;
    hardware ethernet 00:00:00:00:00:00;
}
dhcpd-leases
-- 192.168.20.0
-- 192.168.30.0
-- 192.168.40.0
[...]
所有我得到的都是从另一个文件中解析出来的Mac电脑。因此,我从这个列表开始,想用我的mac grep属性ip,mac:

for ENTRY in $MACLIST
do
    VAR$(cat "dhcpd-leases/10.148.$NETWORK.2/dhcpd.leases" | grep -E "$MAC|lease|client-hostname")
    echo $VAR
done
但这是因为$VAR中有很多条目,而且我无法正确解析这些文件

有人能帮忙吗

致意
Peter

如果您试图获取MAC和IP,最好使用
arp-s
命令,而不是查看DHCP租约文件。

假设您的MAC列表文件如下所示(例如,只有一个条目)

你的租约文件是这样的

$ cat file
lease 192.168.20.4 {
    starts 6 2009/06/27 00:40:00;
    ends 6 2009/06/27 12:40:00;
    hardware ethernet 00:00:00:00:00:00;
    uid 00:00:00:00:00:00;
    client-hostname "examle-workstation1";
}

lease 192.168.20.5 {
    starts 6 2009/06/27 00:40:00;
    ends 6 2009/06/27 12:40:00;
    hardware ethernet 00:00:00:00:00:00;
}

lease 192.168.20.6 {
    starts 6 2009/06/27 00:40:00;
    ends 6 2009/06/27 12:40:00;
    hardware ethernet 00:00:00:00:00:01;
    uid 00:00:00:00:00:01;
    client-hostname "examle-workstation2";
}


lease 192.168.20.7 {
    starts 6 2009/06/27 00:40:00;
    ends 6 2009/06/27 12:40:00;
    hardware ethernet 01:00:00:00:00:00;
}
你可以试试这个

awk 'BEGIN{
    while( (getline line < "maclist") > 0){
        mac[line]
    }
    RS="}"
    FS="\n"
}
/lease/{
    for(i=1;i<=NF;i++){
        gsub(";","",$i)
        if ($i ~ /lease/) {
            m=split($i, IP," ")
            ip=IP[2]
        }
        if( $i ~ /hardware/ ){
            m=split($i, hw," ")
            ether=hw[3]
        }
        if ( $i ~ /client-hostname/){
            m=split($i,ch, " ")
            hostname=ch[2]
        }
        if ( $i ~ /uid/){
            m=split($i,ui, " ")
            uid=ui[2]
        }
    }
    if ( ether in mac ){
        print "ip: "ip " hostname: "hostname " ether: "ether " uid: "uid
    }
} ' file

也可以完全满足您的需要,而无需重新发明轮子。:)

我喜欢awk,但当节目越来越大时,我就不那么喜欢了

因此,我找到了解析租约文件的另一种方法,首先找到一个unix命令链,该命令链将文件转换为两列格式,第一列是ip地址,第二列是mac地址:

egrep -o 'lease.*{|ethernet.*;' dhcpd.leases | awk '{print $2}' | xargs -n 2 | cut -d ';' -f 1
使用一个简单的awk命令,您就可以从mac地址获取ip地址。以下是作为shell函数构建的完整命令:

function f_mac_to_ip {

parseResult=$(egrep -o 'lease.*{|ethernet.*;' /var/lib/dhcp/db/dhcpd.leases | awk '{print $2}' | xargs -n 2 | cut -d ';' -f 1  | grep $1 | awk '{print $1}')
    echo "$parseResult"
}

我对租约的格式不太了解。如果有没有“ethernet”字段的条目,上述解析将无法工作。

不一定比@ghostdog74更好,但这里有一个转换为json的脚本:

#!/usr/bin/awk -f

# Start with array creation
BEGIN {
    printf "[";
}

# New lease: start object 
/^lease/ {
    # If that ip is unknown, create a new JSON object
    if (!known[$2]) {
        # if this object is not the first, print a comma
        if (!notFirst) {
            notFirst=1;
        } else {
            printf ",";
        }

        # create a new JSON object with the first key being the IP (column 2)
        printf "{\"ip\":\"%s\"", $2; known[$2]=1;

        # print subsequent lines, see below
        p=1;
    }
}

# If printing is enabled print line as a JSON key/value pair
p && /^  / {
    # Print key (first word)
    printf ",\"%s\":", $1;

    # Clean up the rest of the line: trim whitespace and trailing ;, remove " and escape \
    $1="";
    gsub(/\\/, "\\\\", $0);
    gsub(/"/, "", $0);
    gsub(/^[\t ]*/, "", $0);
    gsub(/;$/, "", $0);
    printf "\"%s\"", $0;
}

# End of lease: close JSON object and disable printing
/^\}$/ {
    if (p) {
        printf "}"
    }
    p=0
}

# Close the JSON array
END {
    print "]";
}
结果:

$ /opt/dhcpd.leases_to_json.awk /var/lib/dhcp/dhcpd.leases | jq .
[
  {
    "ip": "10.7.37.10",
    "starts": "3 2019/08/28 22:24:26",
    "ends": "3 2019/08/28 22:34:26",
    "cltt": "3 2019/08/28 22:25:32",
    "binding": "state active",
    "next": "binding state free",
    "rewind": "binding state free",
    "hardware": "ethernet xx:xx:xx:xx:xx:xx",
    "client-hostname": "zzzzzzz"
  },
  {
    "ip": "10.7.37.11",
    "starts": "3 2019/08/28 22:26:10",
    "ends": "3 2019/08/28 22:36:10",
    "cltt": "3 2019/08/28 22:26:10",
    "binding": "state active",
    "next": "binding state free",
    "rewind": "binding state free",
    "hardware": "ethernet xx:xx:xx:xx:xx:xx",
    "uid": "\\001pv\\377\\001\\005~",
    "client-hostname": "xxxx"
  }
]
这散发出一股反模式和相关反模式的味道。除非您专门连接多个输入文件,否则您应该需要零个
cat
实例,而且
grep
sed
和Awk中的实例很少超过一个,因为列表中的每个实例都有一个包含列表中上一个工具的所有功能的功能集(尽管某些转换(例如换行符)确实需要多次调用,因此有时两次甚至三次调用可能是合理的)。