mirror of
https://github.com/kubernetes/node-problem-detector.git
synced 2026-08-23 22:26:27 +00:00
Update dependencies and bump Go to v1.24.10
This commit is contained in:
+40
-45
@@ -8,12 +8,14 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/bits"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/yusufpapurcu/wmi"
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.org/x/sys/windows/registry"
|
||||
|
||||
"github.com/shirou/gopsutil/v4/internal/common"
|
||||
)
|
||||
@@ -75,6 +77,8 @@ const (
|
||||
smbiosEndOfTable = 127 // Minimum length for processor structure
|
||||
smbiosTypeProcessor = 4 // SMBIOS Type 4: Processor Information
|
||||
smbiosProcessorMinLength = 0x18 // Minimum length for processor structure
|
||||
|
||||
centralProcessorRegistryKey = `HARDWARE\DESCRIPTION\System\CentralProcessor`
|
||||
)
|
||||
|
||||
type relationship uint32
|
||||
@@ -179,61 +183,27 @@ func getProcessorPowerInformation(ctx context.Context) ([]processorPowerInformat
|
||||
|
||||
func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
|
||||
var ret []InfoStat
|
||||
var dst []win32_Processor
|
||||
q := wmi.CreateQuery(&dst, "")
|
||||
if err := common.WMIQueryWithContext(ctx, q, &dst); err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
var procID string
|
||||
for i, l := range dst {
|
||||
procID = ""
|
||||
if l.ProcessorID != nil {
|
||||
procID = *l.ProcessorID
|
||||
}
|
||||
|
||||
cpu := InfoStat{
|
||||
CPU: int32(i),
|
||||
Family: strconv.FormatUint(uint64(l.Family), 10),
|
||||
VendorID: l.Manufacturer,
|
||||
ModelName: l.Name,
|
||||
Cores: int32(l.NumberOfLogicalProcessors), // TO BE REMOVED, set by getSystemLogicalProcessorInformationEx
|
||||
PhysicalID: procID,
|
||||
Mhz: float64(l.MaxClockSpeed),
|
||||
Flags: []string{},
|
||||
}
|
||||
ret = append(ret, cpu)
|
||||
}
|
||||
|
||||
processorPackages, err := getSystemLogicalProcessorInformationEx(relationProcessorPackage)
|
||||
if err != nil {
|
||||
// return an error whem wmi will be removed
|
||||
// return ret, fmt.Errorf("failed to get processor package information: %w", err)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
if len(processorPackages) != len(ret) {
|
||||
// this should never happen, but it's kept for safety until wmi is removed
|
||||
return ret, nil
|
||||
return ret, fmt.Errorf("failed to get processor package information: %w", err)
|
||||
}
|
||||
|
||||
ppis, powerInformationErr := getProcessorPowerInformation(ctx)
|
||||
if powerInformationErr != nil {
|
||||
// return an error whem wmi will be removed
|
||||
// return ret, fmt.Errorf("failed to get processor power information: %w", err)
|
||||
return ret, nil
|
||||
return ret, fmt.Errorf("failed to get processor power information: %w", err)
|
||||
}
|
||||
|
||||
family, processorId, smBIOSErr := getSMBIOSProcessorInfo()
|
||||
if smBIOSErr != nil {
|
||||
// return an error whem wmi will be removed
|
||||
// return ret, smBIOSErr
|
||||
return ret, nil
|
||||
return ret, smBIOSErr
|
||||
}
|
||||
|
||||
for i, pkg := range processorPackages {
|
||||
logicalCount := 0
|
||||
maxMhz := 0
|
||||
model := ""
|
||||
vendorId := ""
|
||||
// iterate over each set bit in the package affinity mask
|
||||
for _, ga := range pkg.processor.groupMask {
|
||||
g := int(ga.group)
|
||||
forEachSetBit64(uint64(ga.mask), func(bit int) {
|
||||
@@ -246,12 +216,26 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
|
||||
maxMhz = m
|
||||
}
|
||||
}
|
||||
|
||||
registryKeyPath := filepath.Join(centralProcessorRegistryKey, strconv.Itoa(globalLpl))
|
||||
key, err := registry.OpenKey(registry.LOCAL_MACHINE, registryKeyPath, registry.QUERY_VALUE|registry.READ)
|
||||
if err == nil {
|
||||
model = getRegistryStringValueIfUnset(key, "ProcessorNameString", model)
|
||||
vendorId = getRegistryStringValueIfUnset(key, "VendorIdentifier", vendorId)
|
||||
_ = key.Close()
|
||||
}
|
||||
})
|
||||
}
|
||||
ret[i].Mhz = float64(maxMhz)
|
||||
ret[i].Cores = int32(logicalCount)
|
||||
ret[i].Family = strconv.FormatUint(uint64(family), 10)
|
||||
ret[i].PhysicalID = processorId
|
||||
ret = append(ret, InfoStat{
|
||||
CPU: int32(i),
|
||||
Family: strconv.FormatUint(uint64(family), 10),
|
||||
VendorID: vendorId,
|
||||
ModelName: model,
|
||||
Cores: int32(logicalCount),
|
||||
PhysicalID: processorId,
|
||||
Mhz: float64(maxMhz),
|
||||
Flags: []string{},
|
||||
})
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
@@ -461,6 +445,17 @@ func getPhysicalCoreCount() (int, error) {
|
||||
return len(infos), err
|
||||
}
|
||||
|
||||
func getRegistryStringValueIfUnset(key registry.Key, keyName, value string) string {
|
||||
if value != "" {
|
||||
return value
|
||||
}
|
||||
val, _, err := key.GetStringValue(keyName)
|
||||
if err == nil {
|
||||
return strings.TrimSpace(val)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func CountsWithContext(_ context.Context, logical bool) (int, error) {
|
||||
if logical {
|
||||
// Get logical processor count https://github.com/giampaolo/psutil/blob/d01a9eaa35a8aadf6c519839e987a49d8be2d891/psutil/_psutil_windows.c#L97
|
||||
|
||||
+130
-107
@@ -8,7 +8,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
@@ -20,9 +20,21 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
volumeNameBufferLength = uint32(windows.MAX_PATH + 1)
|
||||
volumePathBufferLength = volumeNameBufferLength
|
||||
maxWarningsInDrive = 5
|
||||
maxVolumeNameLength = uint32(windows.MAX_PATH + 1) // this should be a GUID (50), but for safety I keep max_path
|
||||
maxFileSystemNameLength = uint32(windows.MAX_PATH + 1)
|
||||
maxWarningsInDrive = 5
|
||||
)
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationa#parameters
|
||||
const (
|
||||
rw = "rw"
|
||||
ro = "ro"
|
||||
compress = "compress"
|
||||
)
|
||||
|
||||
const (
|
||||
firstPossibleDriveLetter = 'A'
|
||||
lastPossibleDriveLetter = 'Z'
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -96,110 +108,108 @@ func UsageWithContext(_ context.Context, path string) (*UsageStat, error) {
|
||||
// PartitionsWithContext returns disk partitions.
|
||||
// It uses procGetLogicalDriveStringsW to get drives with drive letters and procFindFirstVolumeW to get volumes without drive letters.
|
||||
// Since the api calls don't have a timeout, this method uses context to set deadline by users.
|
||||
func PartitionsWithContext(ctx context.Context, _ bool) ([]PartitionStat, error) {
|
||||
func PartitionsWithContext(_ context.Context, _ bool) ([]PartitionStat, error) {
|
||||
warnings := Warnings{Verbose: true}
|
||||
var errInitialCall error
|
||||
retChan := make(chan PartitionStat)
|
||||
quitChan := make(chan struct{})
|
||||
defer close(quitChan)
|
||||
processedPaths := make(map[string]struct{})
|
||||
partitionStats := []PartitionStat{}
|
||||
|
||||
getPartitions := func() {
|
||||
defer close(retChan)
|
||||
// Get drives with drive letters (including remote drives, ex: SMB shares)
|
||||
drives, err := getLogicalDrives()
|
||||
if err != nil {
|
||||
return partitionStats, err
|
||||
}
|
||||
|
||||
// Get drives with drive letters (including remote drives, ex: SMB shares)
|
||||
lpBuffer := make([]byte, 254)
|
||||
if diskret, _, err := procGetLogicalDriveStringsW.Call(
|
||||
uintptr(len(lpBuffer)),
|
||||
uintptr(unsafe.Pointer(&lpBuffer[0]))); diskret == 0 {
|
||||
errInitialCall = err
|
||||
return
|
||||
}
|
||||
for _, v := range lpBuffer {
|
||||
if v >= 65 && v <= 90 {
|
||||
path := string(v) + ":"
|
||||
if partitionStat, warning := buildPartitionStat(path); warning == nil {
|
||||
processedPaths[partitionStat.Mountpoint+"\\"] = struct{}{}
|
||||
select {
|
||||
case retChan <- partitionStat:
|
||||
case <-quitChan:
|
||||
return
|
||||
}
|
||||
} else {
|
||||
warnings.Add(warning)
|
||||
}
|
||||
}
|
||||
partitionStats = processLogicalDrives(drives, processedPaths, partitionStats, warnings)
|
||||
|
||||
// Get volumes without drive letters (ex: mounted folders with no drive letter)
|
||||
partitionStats = processVolumesMountedAsFolders(partitionStats, warnings, processedPaths)
|
||||
return partitionStats, warnings.Reference()
|
||||
}
|
||||
|
||||
func processVolumesMountedAsFolders(partitionStats []PartitionStat, warnings Warnings, processedPaths map[string]struct{}) []PartitionStat {
|
||||
volNameBuf := make([]uint16, maxVolumeNameLength)
|
||||
nextVolHandle, _, err := procFindFirstVolumeW.Call(
|
||||
uintptr(unsafe.Pointer(&volNameBuf[0])),
|
||||
uintptr(maxVolumeNameLength))
|
||||
if windows.Handle(nextVolHandle) == windows.InvalidHandle {
|
||||
warnings.Add(fmt.Errorf("failed to get first-volume: %w", err))
|
||||
return partitionStats
|
||||
}
|
||||
defer procFindVolumeClose.Call(nextVolHandle)
|
||||
for {
|
||||
mounts, err := getVolumePaths(volNameBuf)
|
||||
if err != nil {
|
||||
warnings.Add(fmt.Errorf("failed to find paths for volume %s", windows.UTF16ToString(volNameBuf)))
|
||||
continue
|
||||
}
|
||||
|
||||
// Get volumes without drive letters (ex: mounted folders with no drive letter)
|
||||
volNameBuf := make([]uint16, volumeNameBufferLength)
|
||||
nextVolHandle, _, err := procFindFirstVolumeW.Call(
|
||||
uintptr(unsafe.Pointer(&volNameBuf[0])),
|
||||
uintptr(volumeNameBufferLength))
|
||||
if windows.Handle(nextVolHandle) == windows.InvalidHandle {
|
||||
errInitialCall = fmt.Errorf("failed to get first-volume: %w", err)
|
||||
return
|
||||
}
|
||||
defer procFindVolumeClose.Call(nextVolHandle)
|
||||
for {
|
||||
mounts, err := getVolumePaths(volNameBuf)
|
||||
if err != nil {
|
||||
warnings.Add(fmt.Errorf("failed to find paths for volume %s", windows.UTF16ToString(volNameBuf)))
|
||||
for _, mount := range mounts {
|
||||
if _, ok := processedPaths[mount]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, mount := range mounts {
|
||||
if _, ok := processedPaths[mount]; ok {
|
||||
continue
|
||||
}
|
||||
if partitionStat, warning := buildPartitionStat(mount); warning == nil {
|
||||
select {
|
||||
case retChan <- partitionStat:
|
||||
case <-quitChan:
|
||||
return
|
||||
}
|
||||
} else {
|
||||
warnings.Add(warning)
|
||||
}
|
||||
if partitionStat, warning := buildPartitionStat(mount); warning == nil {
|
||||
partitionStats = append(partitionStats, partitionStat)
|
||||
} else {
|
||||
warnings.Add(warning)
|
||||
}
|
||||
}
|
||||
|
||||
volNameBuf = make([]uint16, volumeNameBufferLength)
|
||||
if volRet, _, err := procFindNextVolumeW.Call(
|
||||
nextVolHandle,
|
||||
uintptr(unsafe.Pointer(&volNameBuf[0])),
|
||||
uintptr(volumeNameBufferLength)); err != nil && volRet == 0 {
|
||||
var errno syscall.Errno
|
||||
if errors.As(err, &errno) && errno == windows.ERROR_NO_MORE_FILES {
|
||||
break
|
||||
}
|
||||
warnings.Add(fmt.Errorf("failed to find next volume: %w", err))
|
||||
if len(warnings.List) > maxWarningsInDrive {
|
||||
break
|
||||
}
|
||||
|
||||
volNameBuf = make([]uint16, maxVolumeNameLength)
|
||||
if volRet, _, err := procFindNextVolumeW.Call(
|
||||
nextVolHandle,
|
||||
uintptr(unsafe.Pointer(&volNameBuf[0])),
|
||||
uintptr(maxVolumeNameLength)); err != nil && volRet == 0 {
|
||||
var errno syscall.Errno
|
||||
if errors.As(err, &errno) && errno == windows.ERROR_NO_MORE_FILES {
|
||||
break
|
||||
}
|
||||
warnings.Add(fmt.Errorf("failed to find next volume: %w", err))
|
||||
if len(warnings.List) > maxWarningsInDrive {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return partitionStats
|
||||
}
|
||||
|
||||
go getPartitions()
|
||||
|
||||
var ret []PartitionStat
|
||||
for {
|
||||
select {
|
||||
case p, ok := <-retChan:
|
||||
if !ok {
|
||||
if errInitialCall != nil {
|
||||
return ret, errInitialCall
|
||||
}
|
||||
return ret, warnings.Reference()
|
||||
func processLogicalDrives(drives []string, processedPaths map[string]struct{}, partitionStats []PartitionStat, warnings Warnings) []PartitionStat {
|
||||
for _, drive := range drives {
|
||||
if drive != "" && drive[0] >= firstPossibleDriveLetter && drive[0] <= lastPossibleDriveLetter {
|
||||
v := drive[0]
|
||||
path := string(v) + ":"
|
||||
if partitionStat, warning := buildPartitionStat(path); warning == nil {
|
||||
processedPaths[partitionStat.Mountpoint+"\\"] = struct{}{}
|
||||
partitionStats = append(partitionStats, partitionStat)
|
||||
} else {
|
||||
warnings.Add(warning)
|
||||
}
|
||||
if !reflect.DeepEqual(p, PartitionStat{}) {
|
||||
ret = append(ret, p)
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return ret, ctx.Err()
|
||||
}
|
||||
}
|
||||
return partitionStats
|
||||
}
|
||||
|
||||
// getLogicalDrives retrieves all logical drives using GetLogicalDriveStringsW.
|
||||
// We first call GetLogicalDriveStringsW with a buffer length of 0 to get the required buffer size.
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getlogicaldrivestringsw
|
||||
func getLogicalDrives() ([]string, error) {
|
||||
bufferLen, _, err := procGetLogicalDriveStringsW.Call(
|
||||
uintptr(0),
|
||||
uintptr(0))
|
||||
if !errors.Is(err, windows.ERROR_SUCCESS) {
|
||||
return nil, err // The call failed with an unexpected error
|
||||
}
|
||||
lpBuffer := make([]uint16, bufferLen)
|
||||
// buffer can be longer than MAX_PATH
|
||||
_, _, err = procGetLogicalDriveStringsW.Call(
|
||||
uintptr(len(lpBuffer)),
|
||||
uintptr(unsafe.Pointer(&lpBuffer[0])))
|
||||
if !errors.Is(err, windows.ERROR_SUCCESS) {
|
||||
return nil, err // The call failed with an unexpected error
|
||||
}
|
||||
|
||||
drivesString := windows.UTF16ToString(lpBuffer)
|
||||
drives := strings.Split(drivesString, "\x00")
|
||||
return drives, nil
|
||||
}
|
||||
|
||||
func buildPartitionStat(path string) (PartitionStat, error) {
|
||||
@@ -213,16 +223,17 @@ func buildPartitionStat(path string) (PartitionStat, error) {
|
||||
if driveType == windows.DRIVE_REMOVABLE || driveType == windows.DRIVE_FIXED ||
|
||||
driveType == windows.DRIVE_REMOTE || driveType == windows.DRIVE_CDROM {
|
||||
volPath, _ := windows.UTF16PtrFromString(path + "/")
|
||||
volumeName := make([]byte, 256)
|
||||
fsName := make([]byte, 256)
|
||||
var serialNumber, maxComponentLength, fsFlags int64
|
||||
volumeName := make([]byte, maxVolumeNameLength)
|
||||
fsName := make([]byte, maxFileSystemNameLength)
|
||||
var fsFlags int64
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationw
|
||||
ret, _, err := procGetVolumeInformation.Call(
|
||||
uintptr(unsafe.Pointer(volPath)),
|
||||
uintptr(unsafe.Pointer(&volumeName[0])),
|
||||
uintptr(len(volumeName)),
|
||||
uintptr(unsafe.Pointer(&serialNumber)),
|
||||
uintptr(unsafe.Pointer(&maxComponentLength)),
|
||||
uintptr(0), // serial number
|
||||
uintptr(0), // max component length
|
||||
uintptr(unsafe.Pointer(&fsFlags)),
|
||||
uintptr(unsafe.Pointer(&fsName[0])),
|
||||
uintptr(len(fsName)),
|
||||
@@ -235,12 +246,12 @@ func buildPartitionStat(path string) (PartitionStat, error) {
|
||||
return PartitionStat{}, err
|
||||
}
|
||||
|
||||
opts := []string{"rw"}
|
||||
opts := []string{rw}
|
||||
if fsFlags&fileReadOnlyVolume != 0 {
|
||||
opts = []string{"ro"}
|
||||
opts = []string{ro}
|
||||
}
|
||||
if fsFlags&fileFileCompression != 0 {
|
||||
opts = append(opts, "compress")
|
||||
opts = append(opts, compress)
|
||||
}
|
||||
|
||||
return PartitionStat{
|
||||
@@ -265,7 +276,7 @@ func IOCountersWithContext(_ context.Context, names ...string) (map[string]IOCou
|
||||
return drivemap, err
|
||||
}
|
||||
for _, v := range lpBuffer[:lpBufferLen] {
|
||||
if v < 'A' || v > 'Z' {
|
||||
if v < firstPossibleDriveLetter || v > lastPossibleDriveLetter {
|
||||
continue
|
||||
}
|
||||
path := string(rune(v)) + ":"
|
||||
@@ -276,7 +287,7 @@ func IOCountersWithContext(_ context.Context, names ...string) (map[string]IOCou
|
||||
}
|
||||
szDevice := `\\.\` + path
|
||||
const IOCTL_DISK_PERFORMANCE = 0x70020
|
||||
h, err := windows.CreateFile(syscall.StringToUTF16Ptr(szDevice), 0, windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE, nil, windows.OPEN_EXISTING, 0, 0)
|
||||
h, err := windows.CreateFile(windows.StringToUTF16Ptr(szDevice), 0, windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE, nil, windows.OPEN_EXISTING, 0, 0)
|
||||
if err != nil {
|
||||
if errors.Is(err, windows.ERROR_FILE_NOT_FOUND) {
|
||||
continue
|
||||
@@ -316,16 +327,28 @@ func LabelWithContext(_ context.Context, _ string) (string, error) {
|
||||
|
||||
// getVolumePaths returns the path for the given volume name.
|
||||
func getVolumePaths(volNameBuf []uint16) ([]string, error) {
|
||||
volPathsBuf := make([]uint16, volumePathBufferLength)
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumepathnamesforvolumenamew
|
||||
// Consider that NTFS supports paths longer than windows.MAX_PATH
|
||||
returnLen := uint32(0)
|
||||
if result, _, err := procGetVolumePathNamesForVolumeNameW.Call(
|
||||
firstResult, _, volumePathFirstErr := procGetVolumePathNamesForVolumeNameW.Call(
|
||||
uintptr(unsafe.Pointer(&volNameBuf[0])),
|
||||
uintptr(0),
|
||||
uintptr(0),
|
||||
uintptr(unsafe.Pointer(&returnLen)))
|
||||
if firstResult == 0 && !errors.Is(volumePathFirstErr, windows.ERROR_MORE_DATA) {
|
||||
return nil, fmt.Errorf("failed to get volume paths size for volume %s: %w", windows.UTF16ToString(volNameBuf), volumePathFirstErr)
|
||||
}
|
||||
|
||||
volPathsBuf := make([]uint16, returnLen)
|
||||
ok, _, volumePathNamesErr := procGetVolumePathNamesForVolumeNameW.Call(
|
||||
uintptr(unsafe.Pointer(&volNameBuf[0])),
|
||||
uintptr(unsafe.Pointer(&volPathsBuf[0])),
|
||||
uintptr(volumePathBufferLength),
|
||||
uintptr(unsafe.Pointer(&returnLen))); err != nil && result == 0 {
|
||||
return nil, err
|
||||
uintptr(returnLen),
|
||||
uintptr(unsafe.Pointer(&returnLen)))
|
||||
if ok != 0 {
|
||||
return split0(volPathsBuf, int(returnLen)), nil
|
||||
}
|
||||
return split0(volPathsBuf, int(returnLen)), nil
|
||||
return nil, fmt.Errorf("failed to get volume paths for volume %s: %w", windows.UTF16ToString(volNameBuf), volumePathNamesErr)
|
||||
}
|
||||
|
||||
// split0 iterates through s16 upto `end` and slices `s16` into sub-slices separated by the null character (uint16(0)).
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
//go:build aix && ppc64 && cgo
|
||||
// +build aix,ppc64,cgo
|
||||
|
||||
// Guessed at from the following document:
|
||||
// https://www.ibm.com/docs/sl/ibm-mq/9.2?topic=platforms-standard-data-types-aix-linux-windows
|
||||
|
||||
+1
-1
@@ -442,7 +442,7 @@ func HostRootWithContext(ctx context.Context, combineWith ...string) string {
|
||||
}
|
||||
|
||||
// getSysctrlEnv sets LC_ALL=C in a list of env vars for use when running
|
||||
// sysctl commands (see DoSysctrl).
|
||||
// sysctl commands.
|
||||
func getSysctrlEnv(env []string) []string {
|
||||
foundLC := false
|
||||
for i, line := range env {
|
||||
|
||||
-18
@@ -4,32 +4,14 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ebitengine/purego"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func DoSysctrlWithContext(ctx context.Context, mib string) ([]string, error) {
|
||||
cmd := exec.CommandContext(ctx, "sysctl", "-n", mib)
|
||||
cmd.Env = getSysctrlEnv(os.Environ())
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
v := strings.Replace(string(out), "{ ", "", 1)
|
||||
v = strings.Replace(string(v), " }", "", 1)
|
||||
values := strings.Fields(string(v))
|
||||
|
||||
return values, nil
|
||||
}
|
||||
|
||||
func CallSyscall(mib []int32) ([]byte, uint64, error) {
|
||||
miblen := uint64(len(mib))
|
||||
|
||||
|
||||
-17
@@ -5,9 +5,6 @@ package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
@@ -28,20 +25,6 @@ func SysctlUint(mib string) (uint64, error) {
|
||||
return 0, fmt.Errorf("unexpected size: %s, %d", mib, len(buf))
|
||||
}
|
||||
|
||||
func DoSysctrl(mib string) ([]string, error) {
|
||||
cmd := exec.Command("sysctl", "-n", mib)
|
||||
cmd.Env = getSysctrlEnv(os.Environ())
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
v := strings.Replace(string(out), "{ ", "", 1)
|
||||
v = strings.Replace(string(v), " }", "", 1)
|
||||
values := strings.Fields(string(v))
|
||||
|
||||
return values, nil
|
||||
}
|
||||
|
||||
func CallSyscall(mib []int32) ([]byte, uint64, error) {
|
||||
mibptr := unsafe.Pointer(&mib[0])
|
||||
miblen := uint64(len(mib))
|
||||
|
||||
-15
@@ -7,7 +7,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -20,20 +19,6 @@ import (
|
||||
// cachedBootTime must be accessed via atomic.Load/StoreUint64
|
||||
var cachedBootTime uint64
|
||||
|
||||
func DoSysctrl(mib string) ([]string, error) {
|
||||
cmd := exec.Command("sysctl", "-n", mib)
|
||||
cmd.Env = getSysctrlEnv(os.Environ())
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
v := strings.Replace(string(out), "{ ", "", 1)
|
||||
v = strings.Replace(string(v), " }", "", 1)
|
||||
values := strings.Fields(string(v))
|
||||
|
||||
return values, nil
|
||||
}
|
||||
|
||||
func NumProcs() (uint64, error) {
|
||||
return NumProcsWithContext(context.Background())
|
||||
}
|
||||
|
||||
-17
@@ -4,28 +4,11 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func DoSysctrl(mib string) ([]string, error) {
|
||||
cmd := exec.Command("sysctl", "-n", mib)
|
||||
cmd.Env = getSysctrlEnv(os.Environ())
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
v := strings.Replace(string(out), "{ ", "", 1)
|
||||
v = strings.Replace(string(v), " }", "", 1)
|
||||
values := strings.Fields(string(v))
|
||||
|
||||
return values, nil
|
||||
}
|
||||
|
||||
func CallSyscall(mib []int32) ([]byte, uint64, error) {
|
||||
mibptr := unsafe.Pointer(&mib[0])
|
||||
miblen := uint64(len(mib))
|
||||
|
||||
-17
@@ -4,28 +4,11 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func DoSysctrl(mib string) ([]string, error) {
|
||||
cmd := exec.Command("sysctl", "-n", mib)
|
||||
cmd.Env = getSysctrlEnv(os.Environ())
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
v := strings.Replace(string(out), "{ ", "", 1)
|
||||
v = strings.Replace(string(v), " }", "", 1)
|
||||
values := strings.Fields(string(v))
|
||||
|
||||
return values, nil
|
||||
}
|
||||
|
||||
func CallSyscall(mib []int32) ([]byte, uint64, error) {
|
||||
mibptr := unsafe.Pointer(&mib[0])
|
||||
miblen := uint64(len(mib))
|
||||
|
||||
+7
-2
@@ -1,7 +1,10 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
package common
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
maxWarnings = 100 // An arbitrary limit to avoid excessive memory usage, it has no sense to store hundreds of errors
|
||||
@@ -33,9 +36,11 @@ func (w *Warnings) Reference() error {
|
||||
func (w *Warnings) Error() string {
|
||||
if w.Verbose {
|
||||
str := ""
|
||||
var sb strings.Builder
|
||||
for i, e := range w.List {
|
||||
str += fmt.Sprintf("\tError %d: %s\n", i, e.Error())
|
||||
sb.WriteString(fmt.Sprintf("\tError %d: %s\n", i, e.Error()))
|
||||
}
|
||||
str += sb.String()
|
||||
if w.tooManyErrors {
|
||||
str += fmt.Sprintf("\t%s\n", tooManyErrorsMessage)
|
||||
}
|
||||
|
||||
+6
-7
@@ -50,26 +50,25 @@ func IOCountersByFileWithContext(_ context.Context, pernic bool, filename string
|
||||
return nil, err
|
||||
}
|
||||
|
||||
parts := make([]string, 2)
|
||||
|
||||
statlen := len(lines) - 1
|
||||
|
||||
ret := make([]IOCountersStat, 0, statlen)
|
||||
|
||||
for _, line := range lines[2:] {
|
||||
// Split interface name and stats data at the last ":"
|
||||
separatorPos := strings.LastIndex(line, ":")
|
||||
if separatorPos == -1 {
|
||||
continue
|
||||
}
|
||||
parts[0] = line[0:separatorPos]
|
||||
parts[1] = line[separatorPos+1:]
|
||||
interfacePart := line[0:separatorPos]
|
||||
statsPart := line[separatorPos+1:]
|
||||
|
||||
interfaceName := strings.TrimSpace(parts[0])
|
||||
interfaceName := strings.TrimSpace(interfacePart)
|
||||
if interfaceName == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
fields := strings.Fields(strings.TrimSpace(parts[1]))
|
||||
fields := strings.Fields(strings.TrimSpace(statsPart))
|
||||
bytesRecv, err := strconv.ParseUint(fields[0], 10, 64)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
@@ -610,7 +609,7 @@ func getProcInodesAllWithContext(ctx context.Context, root string, maxConn int)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// decodeAddress decode addresse represents addr in proc/net/*
|
||||
// decodeAddress decode address represents addr in proc/net/*
|
||||
// ex:
|
||||
// "0500000A:0016" -> "10.0.0.5", 22
|
||||
// "0085002452100113070057A13F025401:0035" -> "2400:8500:1301:1052:a157:7:154:23f", 53
|
||||
|
||||
+1
-1
@@ -237,7 +237,7 @@ func (p *Process) getKProc() (*unix.KinfoProc, error) {
|
||||
|
||||
// call ps command.
|
||||
// Return value deletes Header line(you must not input wrong arg).
|
||||
// And splited by Space. Caller have responsibility to manage.
|
||||
// And split by Space. Caller have responsibility to manage.
|
||||
// If passed arg pid is 0, get information from all process.
|
||||
func callPsWithContext(ctx context.Context, arg string, pid int32, threadOption, nameOption bool) ([][]string, error) {
|
||||
var cmd []string
|
||||
|
||||
Reference in New Issue
Block a user