package utils import ( "errors" "fmt" "os" "os/exec" "sort" "strconv" "strings" "time" logger "xcecli/config" "go.uber.org/zap" ) // ParseInt parses a string to an integer func ParseInt(s string) (int, error) { return strconv.Atoi(s) } // ParseTim parse time string // support input format: // - "15:04" - only hour and minute, use current year, month and day // - "01-02 15:04" - month and day with hour and minute, use current year // - "03 15:04" - day with hour and minute, use current year and month // - "2006-01-02 15:04" - full year, month and day with hour and minute // output format: "2006-01-02 15:04" func ParseTime(timeStr string) (string, error) { // standard output format outputFormat := "2006-01-02 15:04 CST" // try formats formats := []string{ "2006-01-02 15:04:05", // full format, strictest "2006-01-02 15:04", // full format, strictest "01-02 15:04", // month and day with hour and minute, use current year "02 15:04", // day with hour and minute, use current year and month "15:04", // only hour and minute, use current year, month and day } // get current time, for filling missing fields now := time.Now() // try each format for _, format := range formats { parsedTime, err := time.Parse(format, timeStr) if err == nil { // parse successfully, fill missing fields according to the format resultTime := time.Date( now.Year(), now.Month(), now.Day(), parsedTime.Hour(), parsedTime.Minute(), 0, 0, time.Local, ) // adjust year, month and day according to the format switch format { case "2006-01-02 15:04:05": // full format, use parsed year, month and day resultTime = time.Date( parsedTime.Year(), parsedTime.Month(), parsedTime.Day(), parsedTime.Hour(), parsedTime.Minute(), parsedTime.Second(), 0, time.Local, ) case "2006-01-02 15:04": // full format, use parsed year, month and day resultTime = time.Date( parsedTime.Year(), parsedTime.Month(), parsedTime.Day(), parsedTime.Hour(), parsedTime.Minute(), 0, 0, time.Local, ) case "01-02 15:04": // month and day with hour and minute format, use current year and parsed month and day resultTime = time.Date( now.Year(), parsedTime.Month(), parsedTime.Day(), parsedTime.Hour(), parsedTime.Minute(), 0, 0, time.Local, ) case "02 15:04": // day with hour and minute format, use current year and month and parsed day resultTime = time.Date( now.Year(), now.Month(), parsedTime.Day(), parsedTime.Hour(), parsedTime.Minute(), 0, 0, time.Local, ) case "15:04": // hour and minute format, use current year, month and day // already set, no need to change } // return standard format time string return resultTime.Format(outputFormat), nil } } // all formats failed //return "", fmt.Errorf("invalid time format. Expected formats: HH:MM, DD HH:MM, MM-DD HH:MM, or YYYY-MM-DD HH:MM") return "", errors.New("the time format can be [HH:MM, DD HH:MM, MM-DD HH:MM, YYYY-MM-DD HH:MM]") } // SystemLimits type SystemLimits struct { CPULimit int // CPU time limit (seconds) FileLimit int // file descriptor limit DataLimit int // data segment limit StackLimit int // stack size limit CoreLimit int // core file size limit ProcessLimit int // process limit ThreadLimit int // thread limit MemLimit int // virtual memory limit SwapLimit int // swap limit } // NewSystemLimits create a new SystemLimits instance func NewSystemLimits() *SystemLimits { return &SystemLimits{} } // define the command mapping var limitCommands = map[string]string{ "cpu_limit": "ulimit -t", "file_limit": "ulimit -n", "data_limit": "ulimit -d", "stack_limit": "ulimit -s", "core_limit": "ulimit -c", "process_limit": "ulimit -u", "thread_limit": "cat /proc/sys/vm/max_map_count", "mem_limit": "ulimit -v", "swap_limit": "ulimit -l", } // getLimitValue get the value of the specified limit func getLimitValue(key string) (int, error) { cmd, ok := limitCommands[key] if !ok { return 0, nil } output, err := exec.Command("sh", "-c", cmd).Output() fmt.Println("getLimitValue", key, string(output)) logger.Debug("getLimitValue", zap.String("key", key), zap.String("output", string(output))) if err != nil { return 0, err } value := strings.TrimSpace(string(output)) if value == "unlimited" { return 0, nil } return strconv.Atoi(value) } // GetCPULimit get the CPU time limit func (sl *SystemLimits) GetCPULimit() (int, error) { if sl.CPULimit == 0 { val, err := getLimitValue("cpu_limit") if err != nil { return 0, err } sl.CPULimit = val } return sl.CPULimit, nil } // GetFileLimit get the file descriptor limit func (sl *SystemLimits) GetFileLimit() (int, error) { if sl.FileLimit == 0 { val, err := getLimitValue("file_limit") if err != nil { return 0, err } sl.FileLimit = val } return sl.FileLimit, nil } // GetDataLimit get the data segment limit func (sl *SystemLimits) GetDataLimit() (int, error) { if sl.DataLimit == 0 { val, err := getLimitValue("data_limit") if err != nil { return 0, err } sl.DataLimit = val } return sl.DataLimit, nil } // GetStackLimit get the stack size limit func (sl *SystemLimits) GetStackLimit() (int, error) { if sl.StackLimit == 0 { val, err := getLimitValue("stack_limit") if err != nil { return 0, err } sl.StackLimit = val } return sl.StackLimit, nil } // GetCoreLimit get the core file size limit func (sl *SystemLimits) GetCoreLimit() (int, error) { if sl.CoreLimit == 0 { val, err := getLimitValue("core_limit") if err != nil { return 0, err } sl.CoreLimit = val } return sl.CoreLimit, nil } // GetProcessLimit get the process limit func (sl *SystemLimits) GetProcessLimit() (int, error) { if sl.ProcessLimit == 0 { val, err := getLimitValue("process_limit") if err != nil { return 0, err } sl.ProcessLimit = val } return sl.ProcessLimit, nil } // GetThreadLimit get the thread limit func (sl *SystemLimits) GetThreadLimit() (int, error) { if sl.ThreadLimit == 0 { val, err := getLimitValue("thread_limit") if err != nil { return 0, err } sl.ThreadLimit = val } return sl.ThreadLimit, nil } // GetMemLimit get the virtual memory limit func (sl *SystemLimits) GetMemLimit() (int, error) { if sl.MemLimit == 0 { val, err := getLimitValue("mem_limit") if err != nil { return 0, err } sl.MemLimit = val } return sl.MemLimit, nil } // GetSwapLimit get the swap limit func (sl *SystemLimits) GetSwapLimit() (int, error) { if sl.SwapLimit == 0 { val, err := getLimitValue("swap_limit") if err != nil { return 0, err } sl.SwapLimit = val } return sl.SwapLimit, nil } // GetSystemEnv get the system environment variables // return format: ["VAR1=value1", "VAR2=value2", ...] func GetSystemEnv() []string { // get all environment variables envVars := os.Environ() // sort the environment variables to ensure the consistency of the output sort.Strings(envVars) return envVars }