[AI生成] go 构造Z状态进程

zombie.go

//go:build linux

package main

import (
        "fmt"
        "os"
        "syscall"
        "time"
)

func main() {
        // 使用 syscall.ForkExec 直接创建子进程,这样我们可以更好地控制
        // 子进程会运行一个简单的命令并立即退出
        argv := []string{"/bin/sh", "-c", "echo '子进程启动,准备退出'; exit 0"}
        attr := &syscall.ProcAttr{
                Files: []uintptr{0, 1, 2}, // 继承 stdin, stdout, stderr
        }

        childPid, err := syscall.ForkExec("/bin/sh", argv, attr)
        if err != nil {
                fmt.Printf("创建子进程失败: %v\n", err)
                os.Exit(1)
        }

        fmt.Printf("父进程 PID: %d\n", os.Getpid())
        fmt.Printf("子进程 PID: %d → 已启动,将立即退出,父进程不回收 → 成为僵尸进程\n", childPid)

        // 给子进程一点时间来启动和退出
        time.Sleep(1 * time.Second)
        fmt.Println("子进程应该已经退出,但父进程不回收,现在是僵尸进程!")

        // 验证:查看进程状态
        fmt.Println("\n尝试用 ps 命令查看进程状态...")
        psCmd, err := os.StartProcess("ps", []string{"ps", "-efl"}, &os.ProcAttr{
                Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
        })
        if err == nil {
                // 我们不等待它,让它自己运行
                psCmd.Release()
        }

        // 无限休眠,保持父进程运行,这样子进程不会变成孤儿进程
        fmt.Println("\n父进程无限休眠中...")
        for {
                time.Sleep(1 * time.Hour)
        }
}

Dockerfile

# 第一阶段:构建 Go 程序
FROM golang:alpine AS builder

# 设置工作目录
WORKDIR /build

# 复制源码
COPY zombie.go .

# 静态编译,确保可以在 alpine 上运行
RUN go build -o zombie zombie.go

# 第二阶段:运行环境
FROM alpine:latest

# 安装 ps 命令,方便查看进程
RUN apk add --no-cache procps

# 从 builder 阶段复制编译好的程序
COPY --from=builder /build/zombie /usr/local/bin/zombie

# 容器启动命令:运行僵尸程序
CMD ["/usr/local/bin/zombie"]
docker build -t zombie-container .
docker run -itd zombie-container

image

为什么kill -9无法杀死僵尸进程?
僵尸进程早就已经「死了」,kill -9 只能杀「活着」的进程。

posted on 2026-05-04 15:55  王景迁  阅读(11)  评论(0)    收藏  举报

导航