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 · 193 天前 · 2643 次点击
    这是一个创建于 193 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我的需求是 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 条附言  ·  193 天前
    感谢大家,我先研究一下
    52 条回复    2023-11-01 16:38:00 +08:00
    exkernel
        1
    exkernel  
       193 天前   ❤️ 1
    xiao201261
        2
    xiao201261  
       193 天前   ❤️ 1
    你是打算跑 docker 还是?
    init.d(openrc) 或者什么的是很古老写法,在现代的 Linux 现在应该使用 systemd 来守护,来启动进程。
    bg7lgb
        3
    bg7lgb  
       193 天前
    直接加在 rc.local
    liarsa
        4
    liarsa  
       193 天前
    我同意二楼同学的说法
    julyclyde
        5
    julyclyde  
       193 天前
    建议参考一下/t/982696
    leegoo
        6
    leegoo  
    OP
       193 天前
    @julyclyde 这是正儿八经的需求。。跟这个没什么关系
    leegoo
        7
    leegoo  
    OP
       193 天前
    @xiao201261 不跑 docker ,如果用 systemd 也需要自己手动编写脚本把(我的意思是没办法在程序中自动加入开机自启)
    julyclyde
        8
    julyclyde  
       193 天前
    @leegoo 正儿八经的需求,找一个并不懂这方面知识的人来做?并没觉得这需求有多么正儿八经

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

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

    =====

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

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

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

    倒是检查下错误码啊
    stephenxiaxy
        20
    stephenxiaxy  
       193 天前
    systemd
    tairan2006
        21
    tairan2006  
       193 天前
    你这 windows 也要写个 bat 啊,并不是依靠自身,而且你这么写不能保活。

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

    如果是服务端程序,可以在/etc/systemd/system 下面创建一个.service 文件,需要 root
    julyclyde
        27
    julyclyde  
       193 天前
    @purrgil cron 是做短任务用的
    ysc3839
        28
    ysc3839  
       193 天前 via Android
    @liberize 没记错的话 systemd 是可以注册用户级别的服务的。
    expy
        29
    expy  
       193 天前
    参考服务器被入侵挖矿的,用 cron 。
    kingfalse
        30
    kingfalse  
       193 天前 via Android
    crontab ,每分钟执行一次 sh ,判断没有进程就启动,这不安全的多,兼容性极佳
    kingfalse
        31
    kingfalse  
       193 天前 via Android
    @julyclyde 加个&不就可以了吗?
    phpfpm
        32
    phpfpm  
       193 天前
    @julyclyde 是我在水木认识的那位大佬吗?
    ksc010
        33
    ksc010  
       193 天前
    可以 用 supervisor
    skywalkerfc
        34
    skywalkerfc  
       193 天前
    cron 定时任务
    systemd/init.d 后台常驻进程(更偏系统层,随 Linux 启动而启动)
    supervisor 后台常驻进程(更偏用户层,一般用来管理自己写的常驻脚本偏多)
    yanqiyu
        35
    yanqiyu  
       193 天前
    > 我的需求是 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  
       193 天前 via iPhone
    systemd.service
    voidmnwzp
        37
    voidmnwzp  
       193 天前
    注册服务然后自启动
    pyu77
        38
    pyu77  
       192 天前
    shell 脚本写个,然后放到 rc.local 启动就拉起来。
    想要中断后自动拉起,可以加到 crontab 定时任务。
    adoal
        39
    adoal  
       192 天前 via iPhone   ❤️ 1
    @julyclyde 放弃助人情结,尊重草台班子(们)
    tangtang369
        40
    tangtang369  
       192 天前
    一楼的答案就是正解 如果用 Go 的话都是用这个第三方模块来实现
    julyclyde
        41
    julyclyde  
       192 天前
    @adoal agLee with you

    @phpfpm 是吧
    julyclyde
        42
    julyclyde  
       192 天前
    @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  
       192 天前 via Android
    @julyclyde 不需要吧,至少通过 StartTransientUnit 创建临时 service 不需要特殊权限
    julyclyde
        44
    julyclyde  
       192 天前
    @ysc3839 StartTransientUnit 是指从 dbus 接口创建吗 user 级别的 unit 吧?
    那由哪个程序来发这个消息呢?发消息的这个程序是怎么运行起来呢?
    ysc3839
        45
    ysc3839  
       192 天前 via Android
    @julyclyde 只是举例子说明可以免额外权限创建用户级的 service ,不是说一定要用这种方案。具体能否 enable 一个用户级的 service ,我没调查过,但我猜测是可以的。
    julyclyde
        46
    julyclyde  
       192 天前
    @ysc3839 但是 TransientUnit 不能“下次开机”的时候自动启动吧?那东西的 unit file 根本就不存盘吧
    无法满足 OP 的需求
    ysc3839
        47
    ysc3839  
       192 天前 via Android
    @julyclyde 我已经说了“不是说一定要用这种方案”
    gejigeji
        48
    gejigeji  
       192 天前
    @julyclyde 进程退出后,login session 也不会退出?
    julyclyde
        49
    julyclyde  
       192 天前
    @gejigeji 旧版本 systemd 对于大量 session 累积的情况,会无法正常清理。“理论上”进程退出之后,session 应该退出,但实际上没做到
    gejigeji
        50
    gejigeji  
       191 天前
    @julyclyde ok, 直接/etc/crontab 应该没这个问题
    julyclyde
        51
    julyclyde  
       190 天前
    @gejigeji 应该也会。session 是由/etc/pam.d/crond 生成的。
    不过我没实际试过……

    抛开 session 的问题不说,服务进程的“上级”是 crond 就够奇怪了,和上级是个 login shell 差不多奇怪
    alsas
        52
    alsas  
       178 天前
    systemd
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1055 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 39ms · UTC 18:30 · PVG 02:30 · LAX 11:30 · JFK 14:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.