解析 virsh 输出

问题描述 投票:0回答:3

有没有办法强制

virsh
以可解析的方式打印信息?喜欢
json

我想编写一个单行 shell 命令来获取虚拟机的 IP 地址,但 virsh 打印它的方式对脚本不太友好:

# virsh domifaddr myvm
 Name       MAC address          Protocol     Address
-------------------------------------------------------------------------------
 vnet1      52:54:00:b9:58:64    ipv4         192.168.130.156/24

我正在寻找一种方法来强制它至少不打印标题,这样我就可以轻松地从输出中获取“192.168.130.156”

这是我能做的最好的事情:

# virsh -q domifaddr myvm | awk '{print $4}' | cut -d/ -f 1
192.168.130.156
virsh
3个回答
2
投票

一种选择是在您想要从中提取 IP 信息的域上安装

qemu-guest-agent

从那里,您可以在主机上执行以下命令以获取 JSON 格式的详细网络接口列表:

ubuntu@host:~$ virsh qemu-agent-command my-guest '{"execute":"guest-network-get-interfaces"}'
{"return":[{"name":"lo","ip-addresses":[{"ip-address-type":"ipv4","ip-address":"127.0.0.1","prefix":8},{"ip-address-type":"ipv6","ip-address":"::1","prefix":128}],"statistics":{"tx-packets":22,"tx-errs":0,"rx-bytes":2816,"rx-dropped":0,"rx-packets":22,"rx-errs":0,"tx-bytes":2816,"tx-dropped":0},"hardware-address":"00:00:00:00:00:00"},{"name":"eth0","ip-addresses":[{"ip-address-type":"ipv4","ip-address":"1.2.3.4","prefix":22},{"ip-address-type":"ipv6","ip-address":"abcd::1234:ee:ab12:e31d","prefix":64}],"statistics":{"tx-packets":11231,"tx-errs":0,"rx-bytes":40717370,"rx-dropped":0,"rx-packets":19744,"rx-errs":0,"tx-bytes":890354,"tx-dropped":0},"hardware-address":"01:02:00:03:04:05"}]}

您的 json 可以按照您想要的方式进行解析。


0
投票

我今天遇到了这个问题,所以我写了一个快速程序来做到这一点。

https://github.com/a-h/virshjson

输出表相当容易解析,通过查找包含列名的标题,并记下位置,跳过输出的连字符行,然后使用存储的位置来提取字段。

package virshjson

import (
    "bufio"
    "errors"
    "io"
    "regexp"
    "strings"
)

var ErrMalformedHeader = errors.New("malformed input header")
var ErrMalformedSeparator = errors.New("malformed input separator")
var ErrMalformedBody = errors.New("malformed input body")

type field struct {
    name  string
    start int
}

var fieldsRegexp = regexp.MustCompile(`.+?(\s{2,}|$)`)

func getFields(s string) (fields []field) {
    matches := fieldsRegexp.FindAllStringIndex(s, -1)
    for _, match := range matches {
        start, end := match[0], match[1]
        fields = append(fields, field{
            name:  strings.TrimSpace(s[start:end]),
            start: start,
        })
    }
    return fields
}

var separatorRegexp = regexp.MustCompile(`^\-+$`)

func Convert(input io.Reader) ([]map[string]any, error) {
    scanner := bufio.NewScanner(input)
    // Read headers.
    scanner.Scan()
    if scanner.Err() != nil {
        return nil, scanner.Err()
    }
    fields := getFields(scanner.Text())
    if len(fields) == 0 {
        return nil, ErrMalformedHeader
    }

    // Read the line of hyphens.
    scanner.Scan()
    if scanner.Err() != nil {
        return nil, scanner.Err()
    }
    if !separatorRegexp.MatchString(scanner.Text()) {
        return nil, ErrMalformedSeparator
    }

    // Read lines until an empty one.
    data := make([]map[string]any, 0)
    for scanner.Scan() {
        if scanner.Err() != nil {
            return nil, scanner.Err()
        }
        if len(scanner.Text()) == 0 {
            continue
        }
        value := make(map[string]any)
        for i, field := range fields {
            end := len(scanner.Text())
            if i < len(fields)-1 {
                end = fields[i+1].start
            }
            value[field.name] = strings.TrimSpace(scanner.Text()[field.start:end])
        }
        data = append(data, value)
    }

    return data, nil
}

给定输入:

 Name       MAC address          Protocol     Address
-------------------------------------------------------------------------------
 vnet1      52:54:00:c9:ae:a5    ipv4         192.168.122.110/24

工具输出:

[
 {
  "Address": "192.168.122.110/24",
  "MAC address": "52:54:00:c9:ae:a5",
  "Name": "vnet1",
  "Protocol": "ipv4"
 }
]

0
投票

不幸的是,

virsh domifaddr
命令不提供机器可读的输出模式。

但是,您可以使用 libvirt Python API 来获取访客的 IP 地址:

python -c 'import sys; import libvirt; con = libvirt.open("qemu:///system"); dom = con.lookupByName(sys.argv[1]); print(dom.interfaceAddresses(libvirt.VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE).popitem()[1]["addrs"][0]["addr"])' myvm

它基本上是

virsh domifaddr
的轻型版本。

注意:libvirt Python 包可能安装在可用 libvirt 的系统上,因为 virt-install 和 virt-manager 依赖于它。 (至少在 Fedora 系统上)

© www.soinside.com 2019 - 2024. All rights reserved.