Files
ccg-workflow/codeagent-wrapper/process_check_unix.go
T
li 6d5628977b feat: CCG 多模型协作系统 v1.0
Claude Code + Codex + Gemini 多模型协作工作流系统

## 核心功能
- 6阶段开发工作流 (/ccg:dev)
- 智能路由:前端→Gemini,后端→Codex
- Prompt 增强 (Auggie MCP prompt-enhancer)
- 双模型代码审查和技术分析

## 命令列表
- /ccg:dev - 完整开发工作流
- /ccg:frontend - 前端任务
- /ccg:backend - 后端任务
- /ccg:review - 代码审查
- /ccg:analyze - 技术分析
- /ccg:enhance - Prompt 增强
- /ccg:commit - 智能提交
- /ccg:rollback - 交互式回滚
- /ccg:clean-branches - 清理分支
- /ccg:worktree - Worktree 管理
- /ccg:init - 项目初始化

## 特性
- 预编译二进制(无需 Go 环境)
- 专家系统提示词(Codex/Gemini)
- 一键安装脚本
2026-01-05 01:28:10 +08:00

105 lines
2.3 KiB
Go

//go:build unix || darwin || linux
// +build unix darwin linux
package main
import (
"errors"
"fmt"
"os"
"strconv"
"strings"
"syscall"
"time"
)
var findProcess = os.FindProcess
var readFileFn = os.ReadFile
// isProcessRunning returns true if a process with the given pid is running on Unix-like systems.
func isProcessRunning(pid int) bool {
if pid <= 0 {
return false
}
proc, err := findProcess(pid)
if err != nil || proc == nil {
return false
}
err = proc.Signal(syscall.Signal(0))
if err != nil && (errors.Is(err, syscall.ESRCH) || errors.Is(err, os.ErrProcessDone)) {
return false
}
return true
}
// getProcessStartTime returns the start time of a process on Unix-like systems.
// Returns zero time if the start time cannot be determined.
func getProcessStartTime(pid int) time.Time {
if pid <= 0 {
return time.Time{}
}
// Read /proc/<pid>/stat to get process start time
statPath := fmt.Sprintf("/proc/%d/stat", pid)
data, err := readFileFn(statPath)
if err != nil {
return time.Time{}
}
// Parse stat file: fields are space-separated, but comm (field 2) can contain spaces
// Find the last ')' to skip comm field safely
content := string(data)
lastParen := strings.LastIndex(content, ")")
if lastParen == -1 {
return time.Time{}
}
fields := strings.Fields(content[lastParen+1:])
if len(fields) < 20 {
return time.Time{}
}
// Field 22 (index 19 after comm) is starttime in clock ticks since boot
startTicks, err := strconv.ParseUint(fields[19], 10, 64)
if err != nil {
return time.Time{}
}
// Get system boot time
bootTime := getBootTime()
if bootTime.IsZero() {
return time.Time{}
}
// Convert ticks to duration (typically 100 ticks/sec on most systems)
ticksPerSec := uint64(100) // sysconf(_SC_CLK_TCK), typically 100
startTime := bootTime.Add(time.Duration(startTicks/ticksPerSec) * time.Second)
return startTime
}
// getBootTime returns the system boot time by reading /proc/stat.
func getBootTime() time.Time {
data, err := readFileFn("/proc/stat")
if err != nil {
return time.Time{}
}
lines := strings.Split(string(data), "\n")
for _, line := range lines {
if strings.HasPrefix(line, "btime ") {
fields := strings.Fields(line)
if len(fields) >= 2 {
bootSec, err := strconv.ParseInt(fields[1], 10, 64)
if err == nil {
return time.Unix(bootSec, 0)
}
}
}
}
return time.Time{}
}