Gopsutil: 효율적인 시스템 모니터링 In Go
Grace Collins
Solutions Engineer · Leapcell

Introduction
gopsutil은 Golang으로 작성된 Python 라이브러리 psutil의 포팅 버전으로, 다양한 시스템 및 하드웨어 정보를 편리하게 얻을 수 있도록 도와줍니다. 다른 시스템 간의 차이점을 숨기고 뛰어난 이식성을 제공합니다. gopsutil을 사용하면 서로 다른 시스템에 대해 해당 시스템 메서드를 호출하기 위해 syscall을 사용할 필요가 없습니다. 더욱 좋은 점은 gopsutil의 구현에 cgo 코드가 포함되어 있지 않아 크로스 컴파일이 가능하다는 것입니다.
Quick Start
Installation
다음 명령을 실행하여 설치합니다:
$ go get github.com/shirou/gopsutil
Usage Example
package main import ( "fmt" "github.com/shirou/gopsutil/mem" ) func main() { v, _ := mem.VirtualMemory() fmt.Printf("Total: %v, Available: %v, UsedPercent:%f%%\n", v.Total, v.Available, v.UsedPercent) fmt.Println(v) }
gopsutil은 다양한 기능을 여러 하위 패키지로 나눕니다:
cpu
: CPU 관련;disk
: 디스크 관련;docker
: docker 관련;host
: 호스트 관련;mem
: 메모리 관련;net
: 네트워크 관련;process
: 프로세스 관련;macservices
: Mac 서비스 관련 (원래winservices
는 Windows 서비스에 해당하며, 여기서는 Mac 시스템에 맞게 수정되었습니다).
해당 기능을 사용하려면 해당 하위 패키지를 가져와야 합니다. 예를 들어 위의 코드에서 메모리 정보를 얻기 위해 mem
하위 패키지를 가져왔습니다. mem.VirtualMemory()
메서드는 메모리 정보 구조체 mem.VirtualMemoryStat
을 반환하며, 여기에는 다양한 필드가 포함되어 있습니다. 주요 사용 필드는 Total
(총 메모리), Available
(사용 가능한 메모리), Used
(사용된 메모리) 및 UsedPercent
(메모리 사용률)입니다. mem.VirtualMemoryStat
은 fmt.Stringer
인터페이스를 구현하여 메모리 정보를 JSON 형식으로 반환합니다. fmt.Println(v)
문은 자동으로 v.String()
을 호출하여 반환된 정보를 출력합니다. 프로그램이 다음을 출력한다고 가정합니다 (여기 데이터는 합리적인 가정 값입니다).
Total: 16441110528, Available: 8589934592, UsedPercent:47.730000% {"total":16441110528,"available":8589934592,"used":7851175936,"usedPercent":47.730000,"free":7959955456,"active":8220555264,"inactive":6815744000,"wired":1429770240,"laundry":0,"buffers":0,"cached":0,"writeback":0,"dirty":0,"writebacktmp":0,"shared":0,"slab":0,"sreclaimable":0,"sunreclaim":0,"pagetables":0,"swapcached":0,"commitlimit":0,"committedas":0,"hightotal":0,"highfree":0,"lowtotal":0,"lowfree":0,"swaptotal":0,"swapfree":0,"mapped":0,"vmalloctotal":0,"vmallocused":0,"vmallocchunk":0,"hugepagestotal":0,"hugepagesfree":0,"hugepagesize":0}
단위는 바이트입니다. 컴퓨터 메모리가 16GB이고 현재 사용률이 47.73%이며 사용 가능한 메모리가 8589934592B (즉, 8GB)라고 가정합니다.
CPU
CPU 코어 수는 물리적 코어 수와 논리적 코어 수로 나뉩니다. 물리적 코어 수는 마더보드에 있는 실제 CPU 수입니다. 물리적 CPU에 여러 코어가 있을 수 있으며, 이러한 코어를 논리적 코어라고 합니다. gopsutil의 CPU 관련 함수는 cpu
하위 패키지에 있습니다. 이 하위 패키지는 물리적 및 논리적 코어 수와 CPU 사용률을 얻기 위한 인터페이스를 제공합니다.
Counts(logical bool)
:false
를 전달하여 물리적 코어 수를 반환하고,true
를 전달하여 논리적 코어 수를 반환합니다.Percent(interval time.Duration, percpu bool)
:interval
시간 간격 내의 CPU 사용률을 얻는 데 사용됩니다.percpu
가false
이면 총 CPU 사용률을 얻고,percpu
가true
이면 각 CPU의 사용률을 각각 얻고[]float64
타입의 값을 반환합니다.
예를 들어:
func main() { physicalCnt, _ := cpu.Counts(false) logicalCnt, _ := cpu.Counts(true) fmt.Printf("physical count:%d logical count:%d\n", physicalCnt, logicalCnt) totalPercent, _ := cpu.Percent(3*time.Second, false) perPercents, _ := cpu.Percent(3*time.Second, true) fmt.Printf("total percent:%v per percents:%v", totalPercent, perPercents) }
위의 코드는 물리적 및 논리적 코어 수와 총 CPU 사용률 및 각 CPU의 3초 이내 사용률을 얻습니다. 프로그램 출력 (출력은 실행할 때마다 다를 수 있으며, 여기의 값은 가정됨):
physical count:12 logical count:12 total percent:[6.59835041239871] per percents:[15.77181208051725 14.04682274248692 11.03678929768094 7.692307692328751 3.6789297658885762 1.999999999998181 0.664451827243077 0 0 0 0 0]
Detailed Information
cpu.Info()
를 호출하면 CPU에 대한 자세한 정보를 얻을 수 있으며 []cpu.InfoStat
을 반환합니다:
func main() { infos, _ := cpu.Info() for _, info := range infos { data, _ := json.MarshalIndent(info, "", " ") fmt.Print(string(data)) } }
보기 쉽도록 결과를 JSON 형식으로 출력합니다:
{ "cpu": 0, "vendorId": "Apple", "family": "Apple Silicon", "model": "M1 Pro", "stepping": 0, "physicalId": "abcd1234", "coreId": "", "cores": 10, "modelName": "Apple M1 Pro", "mhz": 3200, "cacheSize": 32768, "flags": [], "microcode": "" }
결과에서 CPU가 3.2GHz의 주파수를 가진 Apple의 M1 Pro 시리즈임을 알 수 있습니다. 이것은 Mac에서 실행할 때 반환되는 결과이며, 내부적으로 github.com/StackExchange/wmi
라이브러리가 사용됩니다 (이 라이브러리가 Mac 시나리오에서 관련 기능이 여전히 있다고 가정하며, 실제로 조정해야 할 수도 있음). Linux에서는 각 논리 CPU가 InfoStat
구조체를 반환합니다.
Time Occupancy
cpu.Times(percpu bool)
를 호출하면 부팅 시간부터 총 CPU 및 각 개별 CPU의 시간 점유율을 얻을 수 있습니다. 총 값을 반환하려면 percpu = false
을 전달하고, 각 개별 CPU의 값을 반환하려면 percpu = true
를 전달합니다. 각 CPU의 시간 점유율은 TimeStat
구조체로 표시됩니다.
// src/github.com/shirou/gopsutil/cpu/cpu.go type TimesStat struct { CPU string `json:"cpu"` User float64 `json:"user"` System float64 `json:"system"` Idle float64 `json:"idle"` Nice float64 `json:"nice"` Iowait float64 `json:"iowait"` Irq float64 `json:"irq"` Softirq float64 `json:"softirq"` Steal float64 `json:"steal"` Guest float64 `json:"guest"` GuestNice float64 `json:"guestNice"` }
CPU
: CPU 식별자. 총 값이면 이 필드는cpu - total
이고, 그렇지 않으면cpu0
,cpu1
등입니다.User
: 사용자 시간 점유율 (사용자 모드);System
: 시스템 시간 점유율 (커널 모드);Idle
: 유휴 시간;- ……
예를 들어:
func main() { infos, _ := cpu.Times(true) for _, info := range infos { data, _ := json.MarshalIndent(info, "", " ") fmt.Print(string(data)) } }
보기 쉽도록 결과를 JSON 형식으로 출력합니다. 다음은 출력 중 하나입니다 (가정 값):
{ "cpu": "cpu0", "user": 123.45, "system": 234.56, "idle": 789.12, "nice": 0, "iowait": 0, "irq": 0, "softirq": 0, "steal": 0, "guest": 0, "guestNice": 0 }
Disk
disk
하위 패키지는 디스크 정보를 얻는 데 사용되며, IO 통계, 파티션 및 사용 정보를 얻을 수 있습니다. 다음은 하나씩 소개합니다.
IO Statistics
disk.IOCounters()
함수를 호출하면 반환된 IO 통계 정보는 map[string]IOCountersStat
유형으로 표시됩니다. 각 파티션은 구조체에 해당하며, 키는 파티션 이름이고 값은 통계 정보입니다. 여기서 통계 구조체의 일부 필드를 선택했으며, 주로 읽기 및 쓰기 횟수, 바이트 수 및 시간을 포함합니다.
// src/github.com/shirou/gopsutil/disk/disk.go type IOCountersStat struct { ReadCount uint64 `json:"readCount"` MergedReadCount uint64 `json:"mergedReadCount"` WriteCount uint64 `json:"writeCount"` MergedWriteCount uint64 `json:"mergedWriteCount"` ReadBytes uint64 `json:"readBytes"` WriteBytes uint64 `json:"writeBytes"` ReadTime uint64 `json:"readTime"` WriteTime uint64 `json:"writeTime"` // …… }
예를 들어:
func main() { mapStat, _ := disk.IOCounters() for name, stat := range mapStat { fmt.Println(name) data, _ := json.MarshalIndent(stat, "", " ") fmt.Println(string(data)) } }
출력에는 모든 파티션이 포함되어 있으며, 여기에는 하나만 표시됩니다 (가정 값):
disk0s2 { "readCount": 123456, "mergedReadCount": 0, "writeCount": 789012, "mergedWriteCount": 0, "readBytes": 5678901234, "writeBytes": 9876543210, "readTime": 200, "writeTime": 300, "iopsInProgress": 0, "ioTime": 0, "weightedIO": 0, "name": "disk0s2", "serialNumber": "1234567890ABCDEF", "label": "Macintosh HD" }
disk.IOCounters()
는 파티션을 식별하기 위해 가변 개수의 문자열 매개변수를 허용하며, 이 매개변수는 Mac에서 유효하지 않습니다 (원래 Windows 관련 설명이 조정되었습니다).
Partition
disk.PartitionStat(all bool)
함수를 호출하여 파티션 정보를 반환합니다. all = false
이면 실제 물리적 파티션 (하드 디스크, CD-ROM, USB 포함) 만 반환되고 다른 가상 파티션은 무시됩니다. all = true
이면 모든 파티션이 반환됩니다. 반환 유형은 []PartitionStat
이며, 각 파티션은 PartitionStat
구조체에 해당합니다.
// src/github.com/shirou/gopsutil/disk/ type PartitionStat struct { Device string `json:"device"` Mountpoint string `json:"mountpoint"` Fstype string `json:"fstype"` Opts string `json:"opts"` }
Device
: 파티션 식별자. Mac에서는 예를 들어disk0s2
형식입니다.Mountpoint
: 마운트 지점, 즉 이 파티션의 파일 경로의 시작 위치입니다.Fstype
: 파일 시스템 유형. Mac에서 일반적으로 사용되는 파일 시스템 유형에는 APFS 등이 있습니다.Opts
: 옵션은 시스템과 관련이 있습니다.
예를 들어:
func main() { infos, _ := disk.Partitions(false) for _, info := range infos { data, _ := json.MarshalIndent(info, "", " ") fmt.Println(string(data)) } }
Mac 컴퓨터의 출력 (첫 번째 파티션 만 표시됨, 가정 값):
{ "device": "disk0s2", "mountpoint": "/", "fstype": "APFS", "opts": "rw" }
위의 출력에서 첫 번째 파티션이 disk0s2
이고 파일 시스템 유형이 APFS임을 알 수 있습니다.
Usage
disk.Usage(path string)
를 호출하면 경로 path
가 있는 디스크의 사용량을 얻을 수 있으며 UsageStat
구조체를 반환합니다.
// src/github.com/shirou/gopsutil/disk.go type UsageStat struct { Path string `json:"path"` Fstype string `json:"fstype"` Total uint64 `json:"total"` Free uint64 `json:"free"` Used uint64 `json:"used"` UsedPercent float64 `json:"usedPercent"` InodesTotal uint64 `json:"inodesTotal"` InodesUsed uint64 `json:"inodesUsed"` InodesFree uint64 `json:"inodesFree"` InodesUsedPercent float64 `json:"inodesUsedPercent"` }
Path
: 경로, 전달된 매개변수입니다.Fstype
: 파일 시스템 유형입니다.Total
: 이 파티션의 총 용량입니다.Free
: 사용 가능한 용량입니다.Used
: 사용된 용량입니다.UsedPercent
: 사용률입니다.
예를 들어:
func main() { info, _ := disk.Usage("/Users") data, _ := json.MarshalIndent(info, "", " ") fmt.Println(string(data)) }
반환된 값은 디스크 사용량이므로 경로 /Users
와 디스크의 루트 경로는 유사한 결과를 반환하지만 구조체의 Path
필드만 다릅니다. 프로그램 출력 (가정 값):
{ "path": "/Users", "fstype": "APFS", "total": 499999999999, "free": 300000000000, "used": 199999999999, "usedPercent": 39.99, "inodesTotal": 0, "inodesUsed": 0, "inodesFree": 0, "inodesUsedPercent": 0 }
Host
host
하위 패키지는 부팅 시간, 커널 버전 번호, 플랫폼 정보 등과 같은 호스트 관련 정보를 얻을 수 있습니다.
Boot Time
host.BootTime()
은 호스트 부팅 시간의 타임 스탬프를 반환합니다.
func main() { timestamp, _ := host.BootTime() t := time.Unix(int64(timestamp), 0) fmt.Println(t.Local().Format("2006-01-02 15:04:05")) }
위의 코드는 먼저 부팅 시간을 얻은 다음 time.Unix()
를 통해 time.Time
유형으로 변환하고 마지막으로 시간을 2006 - 01 - 02 15:04:05
형식으로 출력합니다 (가정 값).
2025-03-15 16:30:15
Kernel Version and Platform Information
func main() { version, _ := host.KernelVersion() fmt.Println(version) platform, family, version, _ := host.PlatformInformation() fmt.Println("platform:", platform) fmt.Println("family:", family) fmt.Println("version:", version) }
Mac에서 실행할 때 출력 (가정 값):
22.6.0 platform: macOS 13.5 family: Darwin version: 22.6.0 ## Terminal Users `host.Users()`는 터미널을 통해 연결된 사용자의 정보를 반환하며, 각 사용자는 `UserStat` 구조체에 해당합니다. ```go // src/github.com/shirou/gopsutil/host/host.go type UserStat struct { User string `json:"user"` Terminal string `json:"terminal"` Host string `json:"host"` Started int `json:"started"` }
필드의 의미는 명확합니다. 다음은 예입니다.
func main() { users, _ := host.Users() for _, user := range users { data, _ := json.MarshalIndent(user, "", " ") fmt.Println(string(data)) } }
다음은 위의 코드를 실행한 후의 출력 결과라고 가정합니다 (실제 값은 시스템 상태 및 사용자 연결 상황에 따라 다릅니다).
{ "user": "leapcell", "terminal": "ttys001", "host": "localhost", "started": 565575675 }
Memory
빠른 시작 섹션에서는 mem.VirtualMemory()
를 사용하여 메모리 정보를 얻는 방법을 보여 주었으며, 이 함수는 물리적 메모리 정보만 반환합니다. mem.SwapMemory()
를 사용하여 스왑 메모리 정보를 얻을 수도 있으며, 정보는 SwapMemoryStat
구조체에 저장됩니다.
// src/github.com/shirou/gopsutil/mem/ type SwapMemoryStat struct { Total uint64 `json:"total"` Used uint64 `json:"used"` Free uint64 `json:"free"` UsedPercent float64 `json:"usedPercent"` Sin uint64 `json:"sin"` Sout uint64 `json:"sout"` PgIn uint64 `json:"pgin"` PgOut uint64 `json:"pgout"` PgFault uint64 `json:"pgfault"` }
이러한 필드의 의미는 비교적 이해하기 쉽습니다. 그중에서도 세 필드 PgIn
, PgOut
및 PgFault
를 강조해야합니다. 스왑 메모리는 페이지 단위입니다. 페이지 오류가 발생하면 운영 체제는 디스크에서 메모리로 일부 페이지를 로드하고 동시에 특정 메커니즘에 따라 메모리의 일부 페이지가 제거됩니다. PgIn
은 로드된 페이지 수를 나타내고 PgOut
은 제거된 페이지 수를 나타내고 PgFault
는 페이지 오류 수입니다.
예를 들어:
func main() { swapMemory, _ := mem.SwapMemory() data, _ := json.MarshalIndent(swapMemory, "", " ") fmt.Println(string(data)) }
다음은 실행 후의 출력 결과라고 가정합니다 (실제 값은 시스템 메모리 사용량에 따라 다름).
{ "total": 8589934592, "used": 2147483648, "free": 6442450944, "usedPercent": 25.00, "sin": 1024, "sout": 512, "pgIn": 2048, "pgOut": 1536, "pgFault": 100 }
Process
process
는 시스템에서 현재 실행중인 프로세스에 대한 정보를 얻고, 새 프로세스를 만들고, 프로세스에 대한 일부 작업을 수행하는 데 사용할 수 있습니다.
func main() { var rootProcess *process.Process processes, _ := process.Processes() for _, p := range processes { if p.Pid == 0 { rootProcess = p break } } fmt.Println(rootProcess) fmt.Println("children:") children, _ := rootProcess.Children() for _, p := range children { fmt.Println(p) } }
위의 코드는 먼저 process.Processes()
를 호출하여 현재 시스템에서 실행중인 모든 프로세스를 가져온 다음 Pid
가 0 인 프로세스를 찾습니다. (Mac 시스템에서는이 프로세스가 일반적으로 커널에서 시작된 첫 번째 프로세스입니다.) 마지막으로 Children()
을 호출하여 하위 프로세스를 반환합니다. 또한 프로세스 정보를 얻는 데 사용할 수있는 많은 방법이 있으며 관심있는 사용자는 관련 문서를 참조하여 자세히 이해할 수 있습니다.
Mac Services (Adjusted from the Original Windows Services Section)
macservices
하위 패키지 (원래 winservices
)는 Mac 시스템의 서비스 정보를 얻을 수 있습니다 (이러한 하위 패키지 및 해당 기능이 있다고 가정). macservices
에서 서비스는 Service
구조체에 해당합니다 (다음 구조체는 가정되며 실제로는 다를 수 있음).
// src/github.com/shirou/gopsutil/macservices/macservices.go type Service struct { Name string Config MacConfig Status ServiceStatus // contains filtered or unexported fields }
그중에서도 MacConfig
(Mac의 원래 mgr.Config
에서 조정됨)는 가상 구조이며이 구조는 서비스 유형, 시작 유형 (자동/수동) 및 이진 파일 경로와 같은 세부 정보를 기록합니다 (가상 구조는 다음과 같습니다).
// src/github.com/shirou/gopsutil/macservices/macconfig.go type MacConfig struct { ServiceType string StartType string BinaryPathName string Dependencies []string ServiceStartName string DisplayName string Description string }
ServiceStatus
구조는 서비스의 상태를 기록합니다 (가상 구조는 다음과 같습니다).
// src/github.com/shirou/gopsutil/macservices/macservices.go type ServiceStatus struct { State string Pid uint32 ExitCode int }
State
: 서비스 상태, 중지됨, 실행 중, 일시 중지 등;Pid
: 프로세스 ID;ExitCode
: 응용 프로그램 종료 상태 코드.
다음 프로그램은 시스템의 모든 서비스 이름, 이진 파일 경로 및 상태를 콘솔에 출력합니다 (가상 코드는 다음과 같습니다).
func main() { services, _ := macservices.ListServices() for _, service := range services { newservice, _ := macservices.NewService(service.Name) newservice.GetServiceDetail() fmt.Println("Name:", newservice.Name, "Binary Path:", newservice.Config.BinaryPathName, "State: ", newservice.Status.State) } }
macservices.ListServices()
를 호출하여 반환 된 Service
객체의 정보가 완전하지 않을 수 있습니다. NewService()
를 통해 서비스 이름으로 서비스를 만들고 GetServiceDetail()
메서드를 호출하여 서비스의 자세한 정보를 가져옵니다. ListService()
에서 반환 된 객체가 (자원 절약을 위해) 필요한 시스템 자원 핸들이 부족할 수 있고 GetServiceDetail()
메서드를 호출하면 프로그램 오류가 발생할 수 있으므로 service.GetServiceDetail()
을 직접 호출 할 수 없습니다.
Errors and Timeouts
대부분의 기능에는 기본 시스템 호출이 포함되므로 오류 및 시간 초과는 불가피합니다. 거의 모든 인터페이스에는 두 개의 반환 값이 있으며 두 번째 반환 값은 오류를 나타내는 데 사용됩니다. 이전 예에서는 코드를 단순화하기 위해 오류 처리를 무시했습니다. 그러나 실제 사용에서는 오류를 적절하게 처리하는 것이 좋습니다.
또한 대부분의 인터페이스는 쌍으로 제공됩니다. 하나는 context.Context
유형의 매개 변수가없고 다른 하나는 컨텍스트 제어를 위해이 유형의 매개 변수가 있습니다. 내부 호출 중에 발생하는 오류 또는 시간 초과를 적시에 처리하고 반환을 위해 오랫동안 기다리지 않도록 할 수 있습니다. 실제로 context.Context
매개 변수가없는 함수는 context.Background()
를 매개 변수로 사용하여 내부적으로 context.Context
매개 변수가있는 함수를 호출합니다. 예를 들어:
// src/github.com/shirou/gopsutil/cpu_mac.go func Times(percpu bool) ([]TimesStat, error) { return TimesWithContext(context.Background(), percpu) } func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { // ... }
Conclusion
gopsutil 라이브러리는 로컬 머신 정보를 얻는 데 편리함을 제공하며, 서로 다른 시스템 간의 호환성 문제를 잘 처리하여 통합된 인터페이스를 제공합니다. 공간 제약으로 인해 여기에 소개되지 않은 net
및 docker
와 같은 여러 하위 패키지도 있습니다. 관심있는 사용자는 스스로 탐색할 수 있습니다.
Leapcell: The Next-Gen Serverless Platform for Web Hosting, Async Tasks, and Redis
마지막으로 가장 적합한 Golang 배포 플랫폼인 **leapcell**을 추천합니다.
1. Multi-Language Support
- JavaScript, Python, Go 또는 Rust로 개발하십시오.
2. Deploy unlimited projects for free
- 사용량에 대해서만 지불하십시오. 요청도 없고 청구도 없습니다.
3. Unbeatable Cost Efficiency
- 유휴 비용이 없는 종량제
- 예: $25는 평균 응답 시간 60ms에서 694만 건의 요청을 지원합니다.
4. Streamlined Developer Experience
- 간편한 설정을 위한 직관적인 UI
- 완전 자동화된 CI/CD 파이프라인 및 GitOps 통합
- 실행 가능한 통찰력을 위한 실시간 지표 및 로깅.
5. Effortless Scalability and High Performance
- 고도의 동시성을 쉽게 처리하기 위한 자동 확장
- 운영 오버헤드가 없으므로 구축에만 집중하면 됩니다.
Leapcell Twitter: https://x.com/LeapcellHQ