V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
dzdh
V2EX  ›  Go 编程语言

fork 的进程怎么自动 attach 到当前的 os.Std{in/out/err}而不是自动退出

  •  
  •   dzdh · 2022-12-25 11:17:25 +08:00 · 1322 次点击
    这是一个创建于 729 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在折腾 go 的 0 停机重启升级。

    前几天看到了 systemd 方案,尝试后还可以。

    然后看到了另外一个方案: https://goteleport.com/blog/golang-ssh-bastion-graceful-restarts/

    有个疑问:

    测试后发现,当收到 HUP 信号后 fork 出子进程没问题,但是 http.Shutdown 结束后原来的进程直接退出了。当然是不影响服务的,就是有个问题,能不能不让老进程退出或者是老进程可以退出但是把 stdin/stdout/stderr 自动挂到新起的进程上呢。

    第 1 条附言  ·  2022-12-25 11:53:30 +08:00

    当本地测试和使用systemd启动时,type=simple一旦fork子进程会systemd认为原先进程正常死掉了,然后就退出了子进程也跟着退了。当type=forking时,systemctl start 会卡住,直到fork一次(那只能进程一启动就自动先fork一遍?).

    试过 process.Wait() 但是进程会套娃

    7 条回复    2022-12-26 11:49:14 +08:00
    wheeler
        1
    wheeler  
       2022-12-25 12:34:49 +08:00 via iPhone
    能不能换个思路。起两个进程。监控进程和业务进程。监控进程作为 main process ,持久运行不退出。业务进程执行 fork exec 。
    wheeler
        2
    wheeler  
       2022-12-25 12:37:28 +08:00 via iPhone
    https://github.com/cloudflare/tableflip#integration-with-systemd

    或者你可以看看 fliptable 怎么玩的。
    dzdh
        3
    dzdh  
    OP
       2022-12-25 12:46:21 +08:00
    @wheeler

    这样的话就要这么做:

    1. 启动 main process
    2. fork 业务 进程 传递个环境变量或者是指定参数 main process 记录个 pid 或者 process 对象
    3. main process 收到信号 再 fork 个进程,用 reuseport 监听(不用传递 fd 了),然后调用 process.signal 给老进程,覆盖全局的 process 对象为新启动的对象
    这样对于 systemd 来说只能是 type=simple

    是吧?类似 laravel 的 queue:listen ,自己不停的调 queue:work (本质上是两个命令)

    写成服务按传递不同参数的方案就是 xxx daemon 和 xxx work 用 xxx daemon 就是个 foreground manager 。它去管理 xxx work 的启停。也可以直接调用 xxx work ,收到信号就直接退

    按环境变量的做法就完全由 main process 管(ENV=ENV xxx 也太中二了)

    总的来说也是个办法。但是纯学习向来说还是想知道有没有什么方法可以做到让子进程在父进程退出后能直接接管父进程的 stdin/stdout/stderr...
    wheeler
        4
    wheeler  
       2022-12-25 12:50:07 +08:00 via iPhone
    @dzdh #3 golang exec 不是可以继承文件吗,然后子进程 serve fileListener 就好了。

    没记错的话,go http 默认自己会设置 reuseaddr 。
    lolizeppelin
        5
    lolizeppelin  
       2022-12-25 12:58:50 +08:00
    linux 基础问题, 查查文件描述符的复制继承就知道怎么做了,和 systemd 没有关系
    dzdh
        6
    dzdh  
    OP
       2022-12-25 14:07:50 +08:00
    @wheeler

    exec 可以继承文件但是解决不了本地开发的时候子进程脱离 console 的问题

    unix.SO_REUSEPORT 搜了一下源码目录没有地方调用。必须通过 net.ListenConfig.Control 手动指定。
    julyclyde
        7
    julyclyde  
       2022-12-26 11:49:14 +08:00
    可以由 systemd 持有 socket 然后你的软件只做服务

    不过其实我觉得你首先应该考虑,选 stdin/stdout 做服务,是不是真的合适
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2708 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 00:28 · PVG 08:28 · LAX 16:28 · JFK 19:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.