老哥们,问一个 go 在 Linux 把自生加入开机自启的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
leegoo
V2EX    Go 编程语言

老哥们,问一个 go 在 Linux 把自生加入开机自启的问题

  •  
  •   leegoo 2023-10-17 16:11:13 +08:00 3577 次点击
    这是一个创建于 795 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我的需求是 go 在启动的时候把自生加入开机自启,并且不依赖其他软件。

    我在 windows 环境,go 可以新建一个文件(AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\start.bat),在脚本内可以调用 exe 程序 重启就会自动启动

    但是在 linux 上,我把编译后的 go 文件进行执行,里面的代码有一句是 os.Create("/etc/init.d/start.sh") 在创建时 会创建失败,我以为是权限的问题 ,但是我是使用的是root用户,并且使用chmod 777了。 实际上 执行 os.Create("/tmp/start.sh")是成功的

    查到的方案基本上都是通过用shell, 但是这样需要手动的添加

    有没有办法解决linux执行 os.Create("/tmp/start.sh")失败的问题

    linux 权限如下:

    [root@localhost etc]# pwd /etc [root@localhost etc]# ll | grep init drwxr-xr-x. 2 root root 24 Sep 27 23:42 gdbinit.d lrwxrwxrwx. 1 root root 11 Sep 27 23:30 init.d -> rc.d/init.d -rw-r--r--. 1 root root 511 Nov 16 2020 inittab 
     [root@localhost application]# ll total 2076 -rwxr-xr-x. 1 root root 2111964 Oct 17 11:05 start 
    第 1 条附言    2023-10-17 20:18:05 +08:00
    感谢大家,我先研究一下
    52 条回复    2023-11-01 16:38:00 +08:00
    exkernel
        1
    exkernel  
       2023-10-17 16:24:21 +08:00   1
    xiao201261
        2
    xiao201261  
       2023-10-17 16:24:53 +08:00   1
    你是打算跑 docker 还是?
    init.d(openrc) 或者什么的是很古老写法,在现代的 Linux 现在应该使用 systemd 来守护,来启动进程。
    bg7lgb
        3
    bg7lgb  
       2023-10-17 16:27:25 +08:00
    直接加在 rc.local
    liarsa
        4
    liarsa  
       2023-10-17 16:28:13 +08:00
    我同意二楼同学的说法
    julyclyde
        5
    julyclyde  
       2023-10-17 16:36:40 +08:00
    建议参考一下/t/982696
    leegoo
        6
    leegoo  
    OP
       2023-10-17 16:42:03 +08:00
    @julyclyde 这是正儿八经的需求。。跟这个没什么关系
    leegoo
        7
    leegoo  
    OP
       2023-10-17 16:43:36 +08:00
    @xiao201261 不跑 docker ,如果用 systemd 也需要自己手动编写脚本把(我的意思是没办法在程序中自动加入开机自启)
    julyclyde
        8
    julyclyde  
       2023-10-17 16:45:05 +08:00
    @leegoo 正儿八经的需求,找一个并不懂这方面知识的人来做?并没觉得这需求有多么正儿八经

    你在 windows 环境设置的那个是用户级自动启动吧,是登录之后才有的
    服务器哪儿有机会让你登录啊

    设置系统级自动启动需要系统级的权限,不是你想写就能随便往里写的
    xiao201261
        9
    xiao201261  
       2023-10-17 16:51:05 +08:00
    @leegoo 如果你还是想直接加 init.d 的话,你可以检查一下 selinux 是否阻止了你的程序往 /etc/init.d 加文件 用 dmesg 看最近几条日志就知道了。

    =====

    让进程守护是个复杂的操作,什么不需要写脚本呢?
    让什么用户运行你的程序?
    是不是要等待网络或者数据库启动后再运行?(优先级)
    要不要限制什么权限?
    原始的 /etc/init.d 里面也是有不少的配置选项呢,脚本量和 systemd 相比差不了多少(何况你系统基本也是 systemd 运行的,保留 /etc/init.d 只是为了兼容)

    难道你的启动脚本就一行,用来启动 go 的程序就撒手不管了?
    真的,跑服务有很多需要考虑的东西,不要只启动就行了,守护在哪里,日志放哪里.....
    leegoo
        10
    leegoo  
    OP
       2023-10-17 16:54:36 +08:00
    @julyclyde 大哥,我觉得你真是有点没事找事。公司有这个需求,我只是来实现而已。你为什么非要觉得我要搞一个最大权限?
    意思是公司派了一个需求,又只有你适合去做这个事情,你不做吗?
    不是每个公司都有专职的 DBA 和运维
    julyclyde
        11
    julyclyde  
       2023-10-17 17:07:13 +08:00
    @leegoo 你这个需求,客观上就是需要最大权限
    但是你对这个不熟悉,掌握这个权限会有风险和错误
    这才是问题
    14v45mJPBYJW8dT7
        12
    14v45mJPBYJW8dT7  
       2023-10-17 17:08:51 +08:00
    为什么不写在 shell 脚本去启动呢
    KagurazakaNyaa
        13
    KagurazakaNyaa  
       2023-10-17 17:11:40 +08:00   1
    写个 systemd 的 unit 不就好了,然后程序里把 unit 链接到/etc/systemd/system/multi-user.target.wants/
    purrgil
        14
    purrgil  
       2023-10-17 17:15:30 +08:00
    windows 下我用任务计划自启。
    还能同时做到间隔几分钟自启,防止程序被杀掉。

    linux 下对应的当然是 crontab 了。
    purrgil
        15
    purrgil  
       2023-10-17 17:20:17 +08:00
    你把程序放 Startup 里启动,那服务器每次重启是不是要进桌面才会启动?
    julyclyde
        16
    julyclyde  
       2023-10-17 17:21:26 +08:00
    @purrgil 你这个做法很腾讯
    在 linux 里用 crontab 启动后台任务(尤其是用户级 crontab )是一个极其错误的行为
    会导致后台服务使用的资源被计入用户的统计数据里去
    purrgil
        17
    purrgil  
       2023-10-17 17:31:13 +08:00
    @julyclyde 那我可理解不了。
    cron 不就是干这个用的?
    huangzhiyia
        18
    huangzhiyia  
       2023-10-17 17:36:15 +08:00 via Android
    你都有 root 了,可以写 /etc/systemd/system/ 里面,用 systemd 来管理。
    hsfzxjy
        19
    hsfzxjy  
       2023-10-17 17:47:08 +08:00 via Android
    > os.Create("/etc/init.d/start.sh") 失败

    倒是检查下错误码啊
    stephenxiaxy
        20
    stephenxiaxy  
       2023-10-17 17:51:32 +08:00
    systemd
    tairan2006
        21
    tairan2006  
       2023-10-17 18:35:13 +08:00
    你这 windows 也要写个 bat 啊,并不是依靠自身,而且你这么写不能保活。

    对比你的 bat 方案,linux 下直接创建 CronJob 最简单,用 @reboot.
    aisk
        22
    aisk  
       2023-10-17 18:40:58 +08:00
    @purrgil 不是。
    kkocdko
        23
    kkocdko  
       2023-10-17 19:04:00 +08:00
    如果是实体机,请你通过 systemd 的 service 做。由 systemd 完成自启动,自动拉起,日志管理等等。
    kkocdko
        24
    kkocdko  
       2023-10-17 19:05:55 +08:00
    emmm ,看到楼上的回复了,楼主你想怎么做就怎么做吧
    X4hB5a
        25
    X4hB5a  
       2023-10-17 19:35:00 +08:00
    liberize
        26
    liberize  
       2023-10-17 19:38:41 +08:00 via Android
    如果是桌面程序,可以在~/.config/autostart 下创建一个.desktop 文件,基本对标 windows

    如果是服务端程序,可以在/etc/systemd/system 下面创建一个.service 文件,需要 root
    julyclyde
        27
    julyclyde  
       2023-10-17 19:39:22 +08:00
    @purrgil cron 是做短任务用的
    ysc3839
        28
    ysc3839  
       2023-10-17 19:42:27 +08:00 via Android
    @liberize 没记错的话 systemd 是可以注册用户级别的服务的。
    expy
        29
    expy  
       2023-10-17 19:48:49 +08:00
    参考服务器被入侵挖矿的,用 cron 。
    kingfalse
        30
    kingfalse  
       2023-10-17 20:03:06 +08:00 via Android
    crontab ,每分钟执行一次 sh ,判断没有进程就启动,这不安全的多,兼容性极佳
    kingfalse
        31
    kingfalse  
       2023-10-17 20:04:07 +08:00 via Android
    @julyclyde 加个&不就可以了吗?
    phpfpm
        32
    phpfpm  
       2023-10-17 20:21:15 +08:00
    @julyclyde 是我在水木认识的那位大佬吗?
    ksc010
        33
    ksc010  
       2023-10-17 20:22:21 +08:00
    可以 用 supervisor
    skywalkerfc
        34
    skywalkerfc  
       2023-10-17 20:50:43 +08:00
    cron 定时任务
    systemd/init.d 后台常驻进程(更偏系统层,随 Linux 启动而启动)
    supervisor 后台常驻进程(更偏用户层,一般用来管理自己写的常驻脚本偏多)
    yanqiyu
        35
    yanqiyu  
       2023-10-17 21:15:58 +08:00
    > 我的需求是 go 在启动的时候把自生加入开机自启,并且不依赖其他软件。

    "并且不依赖其他软件"? 要是 init 都不想依赖那就麻烦了,建议添加 init=你的程序 替代掉 init ,启动自身之后创建容器启动原来的 init 作为给用户的系统

    开个玩笑

    你得依赖点什么东西,要是 systemd 就创建 systemd unit: https://www.freedesktop.org/software/systemd/man/systemd.unit.html
    要是 sysV init 就是/etc/rc.d/xxx.sh, /etc/init.d/,/etc/rc.d/init.d


    写好一个可用的 systemd unit 没那么难。

    以及就算创建文件失败至少给点失败的信息,不然大家水晶球也水晶不出来
    SenLief
        36
    SenLief  
       2023-10-17 23:07:34 +08:00 via iPhone
    systemd.service
    voidmnwzp
        37
    voidmnwzp  
       2023-10-18 00:03:49 +08:00
    注册服务然后自启动
    pyu77
        38
    pyu77  
       2023-10-18 09:57:40 +08:00
    shell 脚本写个,然后放到 rc.local 启动就拉起来。
    想要中断后自动拉起,可以加到 crontab 定时任务。
    adoal
        39
    adoal  
       2023-10-18 10:06:04 +08:00 via iPhone   1
    @julyclyde 放弃助人情结,尊重草台班子(们)
    tangtang369
        40
    tangtang369  
       2023-10-18 11:27:38 +08:00
    一楼的答案就是正解 如果用 Go 的话都是用这个第三方模块来实现
    julyclyde
        41
    julyclyde  
       2023-10-18 12:18:06 +08:00
    @adoal agLee with you

    @phpfpm 是吧
    julyclyde
        42
    julyclyde  
       2023-10-18 12:22:17 +08:00
    @ysc3839 systemd 用户级别服务需要再另外运行一个 systemd 吧,还是需要用户先登录的吧

    @pyu77
    @kingfalse
    你这做法(每分钟 cron )很腾讯
    在旧版本 systemd 里,大量使用 cron 、在 cron 里运行后台服务,会导致大量的 login session 累积,压垮 systemd-logind ,随随便便占十几 G 内存

    @kingfalse &符号是由 shell 处理的。也就是首先你要有个 shell ,也就是会产生一个 login session

    @ksc010
    @skywalkerfc
    supervisorD 自己的启动和存活怎么保证呢?
    ysc3839
        43
    ysc3839  
       2023-10-18 13:01:29 +08:00 via Android
    @julyclyde 不需要吧,至少通过 StartTransientUnit 创建临时 service 不需要特殊权限
    julyclyde
        44
    julyclyde  
       2023-10-18 13:07:29 +08:00
    @ysc3839 StartTransientUnit 是指从 dbus 接口创建吗 user 级别的 unit 吧?
    那由哪个程序来发这个消息呢?发消息的这个程序是怎么运行起来呢?
    ysc3839
        45
    ysc3839  
       2023-10-18 13:22:39 +08:00 via Android
    @julyclyde 只是举例子说明可以免额外权限创建用户级的 service ,不是说一定要用这种方案。具体能否 enable 一个用户级的 service ,我没调查过,但我猜测是可以的。
    julyclyde
        46
    julyclyde  
       2023-10-18 13:38:29 +08:00
    @ysc3839 但是 TransientUnit 不能“下次开机”的时候自动启动吧?那东西的 unit file 根本就不存盘吧
    无法满足 OP 的需求
    ysc3839
        47
    ysc3839  
       2023-10-18 13:42:42 +08:00 via Android
    @julyclyde 我已经说了“不是说一定要用这种方案”
    gejigeji
        48
    gejigeji  
       2023-10-18 15:30:00 +08:00
    @julyclyde 进程退出后,login session 也不会退出?
    julyclyde
        49
    julyclyde  
       2023-10-18 20:06:03 +08:00
    @gejigeji 旧版本 systemd 对于大量 session 累积的情况,会无法正常清理。“理论上”进程退出之后,session 应该退出,但实际上没做到
    gejigeji
        50
    gejigeji  
       2023-10-19 22:45:07 +08:00
    @julyclyde ok, 直接/etc/crontab 应该没这个问题
    julyclyde
        51
    julyclyde  
       2023-10-20 21:55:13 +08:00
    @gejigeji 应该也会。session 是由/etc/pam.d/crond 生成的。
    不过我没实际试过……

    抛开 session 的问题不说,服务进程的“上级”是 crond 就够奇怪了,和上级是个 login shell 差不多奇怪
    alsas
        52
    alsas  
       2023-11-01 16:38:00 +08:00
    systemd
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2586 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 07:15 PVG 15:15 LAX 23:15 JFK 02:15
    Do have faith in what you're doing.
    ubao msn 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