wip: 重新整理 install cmd

This commit is contained in:
zhaoyupeng
2026-01-13 20:13:29 +08:00
parent fcbaa5be2f
commit 760784a5ac
15 changed files with 957 additions and 665 deletions

157
pkg/syscheck/disk.go Normal file
View File

@@ -0,0 +1,157 @@
package syscheck
import (
"context"
"crypto/rand"
"fmt"
"io"
"os"
"strconv"
"time"
"golang.org/x/sys/unix"
)
// GetDiskSpace returns available disk space in bytes for the root partition
func GetDiskSpace(ctx context.Context) (int64, error) {
var stat unix.Statfs_t
if err := unix.Statfs("/", &stat); err != nil {
return 0, fmt.Errorf("failed to get disk space: %w", err)
}
// Available space = Available blocks * Block size
availableSpace := int64(stat.Bavail) * int64(stat.Bsize)
return availableSpace, nil
}
// GetDiskSpeed measures disk read/write speed by writing and reading a 1GB test file
// Returns read speed and write speed in bytes per second
func GetDiskSpeed(ctx context.Context) (int64, int64, error) {
const (
testSize = 1024 * 1024 * 1024 // 1GB
bufferSize = 1024 * 1024 // 1MB buffer
)
tmpFile := "/tmp/diskspeed_test_" + strconv.FormatInt(time.Now().UnixNano(), 10)
defer func() {
// Clean up test file
_ = os.Remove(tmpFile)
}()
// Test write speed
writeSpeed, err := measureWriteSpeed(ctx, tmpFile, testSize, bufferSize)
if err != nil {
return 0, 0, fmt.Errorf("failed to measure write speed: %w", err)
}
// Test read speed
readSpeed, err := measureReadSpeed(ctx, tmpFile, bufferSize)
if err != nil {
return 0, 0, fmt.Errorf("failed to measure read speed: %w", err)
}
return readSpeed, writeSpeed, nil
}
// measureWriteSpeed writes test data to a file and measures the speed
func measureWriteSpeed(ctx context.Context, filename string, totalSize, bufferSize int64) (int64, error) {
// Create file
file, err := os.Create(filename)
if err != nil {
return 0, fmt.Errorf("failed to create test file: %w", err)
}
defer file.Close()
// Prepare buffer with random data
buffer := make([]byte, bufferSize)
if _, err := rand.Read(buffer); err != nil {
return 0, fmt.Errorf("failed to generate random data: %w", err)
}
// Start timing
startTime := time.Now()
var written int64
// Write data in chunks
for written < totalSize {
// Check context cancellation
select {
case <-ctx.Done():
return 0, ctx.Err()
default:
}
// Write buffer
n, err := file.Write(buffer)
if err != nil {
return 0, fmt.Errorf("failed to write data: %w", err)
}
written += int64(n)
}
// Sync to ensure data is written to disk
if err := file.Sync(); err != nil {
return 0, fmt.Errorf("failed to sync file: %w", err)
}
// Calculate speed
duration := time.Since(startTime)
speed := int64(float64(written) / duration.Seconds())
return speed, nil
}
// measureReadSpeed reads the test file and measures the speed
func measureReadSpeed(ctx context.Context, filename string, bufferSize int64) (int64, error) {
// Open file
file, err := os.Open(filename)
if err != nil {
return 0, fmt.Errorf("failed to open test file: %w", err)
}
defer file.Close()
// Get file size
fileInfo, err := file.Stat()
if err != nil {
return 0, fmt.Errorf("failed to stat file: %w", err)
}
totalSize := fileInfo.Size()
// Prepare buffer
buffer := make([]byte, bufferSize)
// Start timing
startTime := time.Now()
var totalRead int64
// Read data in chunks
for {
// Check context cancellation
select {
case <-ctx.Done():
return 0, ctx.Err()
default:
}
// Read buffer
n, err := file.Read(buffer)
if err == io.EOF {
break
}
if err != nil {
return 0, fmt.Errorf("failed to read data: %w", err)
}
totalRead += int64(n)
}
// Calculate speed
duration := time.Since(startTime)
speed := int64(float64(totalRead) / duration.Seconds())
// Verify we read the entire file
if totalRead != totalSize {
return 0, fmt.Errorf("read size mismatch: expected %d, got %d", totalSize, totalRead)
}
return speed, nil
}