各位大佬,帮忙看一下这段代码是什么原理让 go 保持后台运行的 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
PeterYang1996
V2EX    程序员

各位大佬,帮忙看一下这段代码是什么原理让 go 保持后台运行的

  •  
  •   PeterYang1996 2021-09-01 14:11:09 +08:00 4823 次点击
    这是一个创建于 1501 天前的主题,其中的信息可能已经有所发展或是发生改变。

    需要做一个服务在后台运行,又不想使用第三方进程管理工具,在网上找到一段代码,试了一下可以后台运行,不明白原理

    package main import ( "log" "os" "os/exec" "strconv" "time" ) func main() { args := os.Args daemon := false for k, v := range args { if v == "-d" { daemon = true args[k] = "" } } if daemon { Daemonize(args...) return } file, err := os.OpenFile("test.txt", os.O_CREATE|os.O_RDWR, 0664) if err != nil { log.Println(err) return } defer file.Close() for { file.Write([]byte(strconv.Itoa((int)(time.Now().Unix())) + "\n")) time.Sleep(time.Second * 1) } } func Daemonize(args ...string) { var arg []string if len(args) > 1 { arg = args[1:] } cmd := exec.Command(args[0], arg...) cmd.Env = os.Environ() cmd.Start() } 

    后台运行 ./mian -d

    第 1 条附言    2021-09-01 17:09:38 +08:00
    感谢各位,已解决
    38 条回复    2021-09-17 16:20:21 +08:00
    6IbA2bj5ip3tK49j
        1
    6IbA2bj5ip3tK49j  
       2021-09-01 14:14:19 +08:00
    里面有个 for 循环啊。
    Dockerfile
        2
    Dockerfile  
       2021-09-01 14:16:25 +08:00   11
    你是我见过现实中第一个把 main 打成 mian 的(
    pkoukk
        3
    pkoukk  
       2021-09-01 14:16:55 +08:00
    for{}死循环啊
    hingbong
        4
    hingbong  
       2021-09-01 14:20:33 +08:00
    他相当于用命令行重新启动了一次自己,然后就 return 了
    zjyl1994
        5
    zjyl1994  
       2021-09-01 14:22:30 +08:00
    for 循环啊朋友
    for {

    file.Write([]byte(strconv.Itoa((int)(time.Now().Unix())) + "\n"))

    time.Sleep(time.Second * 1)
    }
    indexphp
        6
    indexphp  
       2021-09-01 14:22:34 +08:00
    上面说 for 循环的,仔细看看在传入 `-d` 的时候真的有走到 for 循环?
    indexphp
        7
    indexphp  
       2021-09-01 14:24:12 +08:00
    @hingbong 我理解有误,这个是正解,自己启动了一下自己。
    PeterYang1996
        8
    PeterYang1996  
    OP
       2021-09-01 14:24:39 +08:00
    @hingbong 应该是这样
    PeterYang1996
        9
    PeterYang1996  
    OP
       2021-09-01 14:26:38 +08:00
    @indexphp 你别理他们了
    opsll
        10
    opsll  
       2021-09-01 14:45:00 +08:00   7
    我的理解是这样的: cmd := exec.Command(args[0], arg...)这行代码,是将当前可执行文件,通过子进程的再启动一遍,后续执行 return 的时候主进程就退出了,而子进程就变成了孤儿进程,在后台执行。由于你这里有个 for 循环,那么就会在后台一直执行不退出。
    shakaraka
        11
    shakaraka  
    PRO
       2021-09-01 14:51:07 +08:00
    @opsll #10 孤儿进程哈哈哈哈哈哈哈哈哈哈
    Akiya
        12
    Akiya  
       2021-09-01 16:43:07 +08:00
    这个就是 Daemonize 的标准做法啊,起一个子进程去跑,然后自己无了,那么就是在后台运行了。很多软件比如 nginx 实现就是这样的
    ysc3839
        13
    ysc3839  
       2021-09-01 16:55:38 +08:00
    cmd := exec.Command(args[0], arg...)
    cmd.Env = os.Environ()
    cmd.Start()

    ysc3839
        14
    ysc3839  
       2021-09-01 17:13:11 +08:00
    @ysc3839 这么做有用的根本原因大概是 shell 只会等待子进程,不会等待子进程启动的孙进程,所以子进程启动一个新进程后自己退出,shell 就不会等待了。如果遇到了会等孙进程的 shell 或终端,这种做法就无效了。
    ihipop
        15
    ihipop  
       2021-09-01 21:00:38 +08:00 via Android
    @ysc3839 而且这样会导致如果这个孙进程没人回收变僵尸。
    Senorsen
        16
    Senorsen  
       2021-09-01 21:13:41 +08:00
    @wunonglin orphan process 就是叫孤儿进程(虽然一翻译成中文确实有点违和感)
    darknoll
        17
    darknoll  
       2021-09-01 21:41:11 +08:00
    居然有好几个说 for 循环的。。。
    lululau
        18
    lululau  
       2021-09-01 22:33:18 +08:00
    这个代码怎么说呢。。。知道 daemonize 这个词,竟然不知道 Google 一下 “How to make a daemon process in golang”,了解一下怎么正确编写 daemonize 代码
    wangsongyan
        19
    wangsongyan  
       2021-09-01 22:45:04 +08:00 via iPhone
    @darknoll #17 没 for 循环能后台运行?
    JustLookBy
        20
    JustLookBy  
       2021-09-01 23:08:43 +08:00
    @wangsongyan 后台运行和 for 循环 有一毛钱关系,for 循环和 time.Sleep(一万年) 在这作用一样,都只是模拟长时间运行而已。。。
    wangsongyan
        21
    wangsongyan  
       2021-09-02 06:54:14 +08:00 via iPhone
    @JustLookBy #20 你要这么说,我的回复少了两个字,没 for 循环能(一直)后台运行?
    ihipop
        22
    ihipop  
       2021-09-02 08:01:05 +08:00 via Android
    @wangsongyan 能,包括但不限于 sleep channel,等方法
    itfanr
        23
    itfanr  
       2021-09-02 08:45:47 +08:00
    @opsll 其实就是 linux fork 那一套
    darknoll
        24
    darknoll  
       2021-09-02 09:05:38 +08:00
    @wangsongyan 你到现在还没明白这段代码的要点?
    bing0
        25
    bing0  
       2021-09-02 09:39:14 +08:00
    那么问题来了,僵尸进程会内存溢出吗?
    lolizeppelin
        26
    lolizeppelin  
       2021-09-02 11:34:15 +08:00
    找资料学把 fork setsid setuid setgid 和信号 搞清楚,别走 cmd 这种邪门歪道

    实在不想学你还可以直接用 systemd 来管 但是无论怎么搞 标准做法还是要处理信号来方便退出
    cenbiq
        27
    cenbiq  
       2021-09-02 12:31:34 +08:00
    不太理解前面说的孤儿进程,我直接启动进程就执行 for 不能做到吗?一定要启动子进程再让自身 return 才行?
    koolob
        28
    koolob  
       2021-09-02 12:52:16 +08:00
    @cenbiq #27 直接启动然后 for 的话,此时控制台退出,程序就中断了。后台运行的目的是实现在控制台启动程序后,控制台退出,程序依然运行。
    koolob
        29
    koolob  
       2021-09-02 12:54:51 +08:00
    用这种做法还需要配套方案才行,比如保存进程号,处理各种信号,这样才能算是稳定的程序。只是本地练习的话倒是无所谓。
    mxT52CRuqR6o5
        30
    mxT52CRuqR6o5  
       2021-09-02 15:22:43 +08:00
    问:水为什么会往低处流?
    答:因为低处的位置比高处低。
    mxT52CRuqR6o5
        31
    mxT52CRuqR6o5  
       2021-09-02 15:29:40 +08:00
    @cenbiq “后台”运行
    barathrum
        32
    barathrum  
       2021-09-02 16:07:35 +08:00
    就是 double fork
    ragnaroks
        33
    ragnaroks  
       2021-09-02 22:42:10 +08:00
    看到上面几个 for 循环我一下以为我从小学开始学的 C 路走歪了,一般都是起个线程,主线程等待子线程结束,最简单的实现
    lasuar
        34
    lasuar  
       2021-09-03 11:08:36 +08:00
    套娃,多此一举。 ./main &
    jianjian714
        35
    jianjian714  
       2021-09-03 14:50:31 +08:00
    go 热重启算后台运行的一个完善的应用了吧
    necodba
        36
    necodba  
       2021-09-16 19:04:34 +08:00
    article-spider 里面能不能加一个并发。或者限定每一条获取数据的时间频率,另外如果首页的地址是 /article/1 , 第二页地址是 /pages?=2&type=commic&article=11,这种翻页完全改了参数的咋整
    PeterYang1996
        37
    PeterYang1996  
    OP
       2021-09-17 16:18:53 +08:00
    @necodba 你的 issue 这么提到这里了。。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     888 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 20:22 PVG 04:22 LAX 13:22 JFK 16:22
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86