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

golang 常规应该如何向已经运行的程序发送带参数的指令?

  •  
  •   raw0xff · 2023-07-04 20:26:22 +08:00 · 2107 次点击
    这是一个创建于 494 天前的主题,其中的信息可能已经有所发展或是发生改变。

    想让程序在运行时通过外部命令(带参数)执行不同的函数方法。比如可执行程序是"imabin",imabin 已经运行中,在命令行“imabin add='xxx' host='xxx' port='xxx'”可以让已经运行的进程执行相应的函数,是不是应该这样操作?这样做是不是还要考虑重复启动和查找已经运行的进程的问题,有没有别的方式?

    用信号的话,不可以带参数而且只有两个自定义信号。 用端口通信的话,是不是没必要?

    大佬的常规做法是怎样?

    27 条回复    2023-08-14 16:41:28 +08:00
    lhbc
        1
    lhbc  
       2023-07-04 20:31:02 +08:00 via Android
    搞个配置文件,配置监听端口或者 socket 或者 pid
    再次运行的时候读取配置,检查相应的端口或者 socket ,然后向进程发送你的参数
    raw0xff
        2
    raw0xff  
    OP
       2023-07-04 20:51:38 +08:00
    @lhbc 感谢大佬,监听端口是为了做已运行的标记还是为了接收参数?“然后向进程发送你的参数”是用 tcp 或者 udp 向端口发参数吗?这是常规做法吗?
    thinkershare
        3
    thinkershare  
       2023-07-04 20:59:24 +08:00
    不同操作系统有自己的互斥体试下,程序启动时候检查这个互斥体,然后做去重处理。然后检查到已被持有后,转发命令行参数到已运行进程,已运行进程可用使用 TCP/进程管道/文件监听等多种方式来获取刚刚启动程序传递的参数。没有什么常规不常规。要看你的实际需求。有很多方法可用做到你需要的这种操作。
    thinkershare
        4
    thinkershare  
       2023-07-04 21:00:14 +08:00
    互斥体实现
    0o0O0o0O0o
        5
    0o0O0o0O0o  
       2023-07-04 21:01:15 +08:00 via iPhone
    viper
    aloxaf
        6
    aloxaf  
       2023-07-04 21:04:09 +08:00
    哪种方法最常规不知道,但最简单的肯定是直接用官方的 rpc 包: https://pkg.go.dev/net/rpc
    不同实例就监听不同端口
    rrfeng
        7
    rrfeng  
       2023-07-04 21:04:26 +08:00 via Android   ❤️ 1
    明显是个 X-Y problem ,请说出你的原始需求。
    yianing
        8
    yianing  
       2023-07-04 22:02:20 +08:00
    docker 和 caddy 都是监听一个 unix socket 通信
    Vegetable
        9
    Vegetable  
       2023-07-04 22:23:19 +08:00
    常见的 daemon+cli 模式呗,比如 docker
    lhbc
        10
    lhbc  
       2023-07-04 22:26:47 +08:00 via Android
    @raw0xff 这要涉及到进程间通讯
    无非就是 tcp 或者 socket 这几种

    端口和 socket, pid 都可以用于标识进程已运行
    dobelee
        11
    dobelee  
       2023-07-04 22:31:34 +08:00
    都用 go 了,起个服务,可扩展性更高。
    flyqie
        12
    flyqie  
       2023-07-04 22:56:11 +08:00 via Android
    搞个 unix domain socket 完事。

    要是只用一个 mgr 管理的话,甚至可以直接 stdin stdout stderr 结合实现。。

    避免重复启动和查找已运行进程用 pid file 实现(即使 pid file 存在最好也要做几次检查,看看 pid file 里面的 pid 到底是否存在,避免意外结束导致 pid file 没有正确释放),非常追求唯一性的话可以考虑搞一下其他类型的锁来辅助。

    如果直接带参跑新进程来做数据交换的话,不灵活,也不好改。
    raw0xff
        13
    raw0xff  
    OP
       2023-07-04 23:38:17 +08:00
    @yianing
    @Vegetable 对,就是想实现像 docker 那样“docker+命令+参数”这种操作。请问大概实现方式是啥我去搜搜。


    @thinkershare 感谢老哥,我去查查。
    ETiV
        14
    ETiV  
       2023-07-04 23:56:38 +08:00
    docker 是 C/S 架构

    你用的 docker + 命令 + 参数,docker 其实是客户端,用它来生成参数向 dockerd 这个进程发请求。dockerd 监听在本地 socks 文件上,可以为它配置权限属性,避免非授权访问…

    所有功能上的事儿都是 dockerd 去完成的,比如 docker pull ,是 dockerd 在 pull…

    ====
    当然你也可以像 hashicorp vault 那样,一个可执行程序,根据参数不同,既当 server 又当 client
    wweir
        15
    wweir  
       2023-07-05 05:50:58 +08:00 via iPhone
    前面说了那么多基于 rpc 通讯的方案,再说两个基于信号、文件监听的方案
    1 、用 notify 监听配置文件的变动,执行对应动作
    2 、监听指定 signal ,执行对应动作,动作里面可以包括读指定文件
    Nazz
        16
    Nazz  
       2023-07-05 10:21:22 +08:00
    试试 unix socket ?
    我这个库封装了 websocket 服务端和客户端, 支持 unix socket 作为传输层
    https://github.com/lxzan/gws
    MoYi123
        17
    MoYi123  
       2023-07-05 11:16:32 +08:00
    经典八股文之《进程间的通信方式》 , 里面随便挑一种就行.
    julyclyde
        18
    julyclyde  
       2023-07-05 12:58:22 +08:00
    @wweir inotify 的话有竞争情况
    下发多个指令的时候,发指令和收指令方的节奏不容易协调

    signal 的信息量太简略了
    ttvast
        19
    ttvast  
       2023-07-05 13:46:48 +08:00
    shm+signal
    proxytoworld
        20
    proxytoworld  
       2023-07-05 14:06:35 +08:00
    go 可以动态解析配置文件啊,监测到配置文件修改则重新读取,解析参数
    harrozze
        21
    harrozze  
       2023-07-05 14:09:17 +08:00
    @julyclyde #18 他的意思是把要执行的动作放到文件里,通过 signal 让正在运行的进程去读一下,然后执行。这种在频率不高的情况下可行,包括通过 signal 重读配置文件都可以,kill -HUP 经常用来干这事儿。但其实整套实现方案还是得根据具体情况进行选择,signal 重新初始化+旧子进程优雅退出,还是 socket/fifo 的方式发命令。另:notify 监听文件改变的方式在生产线上不可取,监听到事件到执行命令之间需要有个相对严格的验证文件正确性的过程,文件改变即执行的方式不容易做到。
    raw0xff
        22
    raw0xff  
    OP
       2023-07-05 16:50:43 +08:00
    @proxytoworld 正在看这个
    wweir
        23
    wweir  
       2023-07-05 20:35:45 +08:00
    @harrozze 哈哈哈,一看就是琢磨过干过这事的人
    julyclyde
        24
    julyclyde  
       2023-07-06 11:58:34 +08:00
    @harrozze inotify 其实也可以校验正确性再加载,这倒不是问题

    问题在于:发指令方如用“覆盖命令文件”的方式发了多次指令,但被指令方也许只读了一次配置文件,从而丢失了中间的其他指令;如果选用往命令文件内 append 内容的方式,又涉及到:被指令方应该从上次记忆的位置开始读文件、旧文件是否应该删除以节省空间、rotate 之后需要从头开始读之类的破事。虽然最终也可能达到正确,但是开发者的时间都浪费掉了


    fifo ,多个指令一起发过来,存在打开文件冲突的问题

    listen socket+多个 accept 的方式是相对靠谱的
    harrozze
        25
    harrozze  
       2023-07-06 12:19:41 +08:00
    @julyclyde #24 对,监控文件改动就去执行的方式,缺点就是缺乏一个明确的信号,容易漏,容易出错误(比如,如果不知道需要把所有指令一次性写入的话,有可能会一行甚至半行式的增加文件内容)导致非预期的结果。
    raw0xff
        26
    raw0xff  
    OP
       2023-07-06 15:09:00 +08:00
    @julyclyde
    @harrozze
    看大佬对话受益匪浅,分析了一下自己的需求场景,多用户同时访问的机率为 0 ,用户只有我自己,所以我选修改配置文件后-HUP 。
    ducks
        27
    ducks  
       2023-08-14 16:41:28 +08:00
    mq:没错正是在下!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2684 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 06:46 · PVG 14:46 · LAX 22:46 · JFK 01:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.