V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
liuguangxuan
V2EX  ›  C++

请教各位 C++的老哥,发布程序的时候,需要打成 rpm、deb 包吗?

  •  
  •   liuguangxuan · 65 天前 · 2537 次点击
    这是一个创建于 65 天前的主题,其中的信息可能已经有所发展或是发生改变。

    自己平时在工作中,发布或者更新 C++程序时,直接发布一个文件夹,里面包含了可执行程序和相关的依赖库。用户下载下来,替换更新。

    请问各位老哥:

    1. 你们发布程序的时候会打包成 rpm 、deb 格式的包吗?如果打包的话用的是什么工具?如何检测 CentOS 、Ubuntu 等不同平台的?
    2. 打包发布程序的时候,如何和 systemd 配合,使用 systemctl 来管理?
    3. 行业里面,比较规范的做法是什么?
    28 条回复    2022-05-10 11:21:17 +08:00
    iClass
        1
    iClass  
       65 天前 via Android
    比较规范的做法是 发布到 Github 开源
    XiLingHost
        2
    XiLingHost  
       65 天前   ❤️ 1
    用 ci/cd 做自动化构建,生成的制品可以发布到内网的 nexus 里
    ZhiyuanLin
        3
    ZhiyuanLin  
       65 天前   ❤️ 1
    内部用的程序,建议全静态链接,用户自行下载个 binary 直接拷贝到 /usr/local/bin 或其他自己喜欢的路径,基本没有跨发行版兼容问题。内部使用的 binary 我个人倾向于不用系统包管理器安装,避免在打包者失误的情况下对系统造成什么影响。

    systemd 按格式写个 service file 复制到相关路径即可。https://wiki.archlinux.org/title/systemd
    BrettD
        4
    BrettD  
       65 天前 via iPhone
    在目标机器上从源码编译
    hetal
        5
    hetal  
       65 天前
    业务系统的话,最简单是用 docker 。
    littlewing
        6
    littlewing  
       65 天前   ❤️ 1
    全静态链接所有依赖,拿来啥都不用装就能跑的那种
    adoal
        7
    adoal  
       65 天前
    真的想打包 rpm/deb ?那就是学 rpm 和 deb 的官方 guide 呗,学了之后第一个问题的后面两个问号和第二第三个问题都不值得问了。

    不过内网环境里还要打成发行版包的团队不多。毕竟这种事不产生业务绩效,管理者一般是不在乎的,属于低性价比的行事方式。
    workman2021
        9
    workman2021  
       65 天前   ❤️ 1
    nfpm: https://github.com/goreleaser/nfpm 编译好的二进制文件 直接用这个打包成 deb,rpm 方便
    jim9606
        10
    jim9606  
       65 天前   ❤️ 1
    可以打包,因为有些自动部署会要求发布为 rpm/deb 。
    尽量用静态链接,少用共享库,或者改 rpath 优先用本地共享库,不要像发行版那样搞七八个直接依赖,最好是只依赖 libc6 ,也尽量不要在安装 /卸载脚本里做任何编辑全局配置的事(例如 sed 修改 sysctl.conf 和 ld.so.conf )。
    目录的话一般不要混在 /usr 下面,在 /opt 下面按 app 名建目录比较好,或者看 SA 的建议。
    Chipmunker
        11
    Chipmunker  
       65 天前
    既然是 c++项目,可以直接用 cmake 来打包啊。多平台支持。
    timpaik
        12
    timpaik  
       65 天前 via Android   ❤️ 1
    当然是打 docker 镜像?
    mingl0280
        13
    mingl0280  
       64 天前   ❤️ 1
    Windows:InstallShield 或者 NSIS ,
    Linux:不打包,.tar.gz+安装脚本。
    懒得搞那些打包啥的……
    systemctl 并不管程序包,那是 dpkg 之类的包管理器管。
    行业内并没有“比较规范的做法”,都是各家自己看着办,不然哪来的那么多软件包安装套件啥的……
    liuguangxuan
        14
    liuguangxuan  
    OP
       64 天前
    @Chipmunker #11 感谢老哥回复,我第一反应也是用 cmake 的 cpack 打包,但是没有找到检测 Linux 发行版的方法,最后用的是读取`/etc/os-release`文件,根据关键字来判断。

    打成 rpm 包,并配合 systemd 参考的是 https://github.com/andrew-hardin/cpack-systemd-demo 这篇教程,但是没有找到同时兼顾 Linux 多种发行版的打包教程,老哥能否指点一下,给个用 cmake 打包,配合 systemd ,同时兼顾不同发行版的优雅点儿的方式或者教程?
    nightwitch
        15
    nightwitch  
       64 天前
    打包并不是很方便。。尤其是对于企业工作场景,即使是开发者都可能没有 root 权限,不能随便安装包。
    打成 tar.gz 就差不多了,用户可以放到自己的$HOME 目录。
    deb 文件本质上就是 tar.xz 。只是里面的路径不同
    adoal
        16
    adoal  
       64 天前
    对了,OP 你为啥执着于检测发行版?而且你所谓的检测发行版是在打包时检测,还是装包时检测,还是运行时检测?

    打单个包兼容多种发行版还是不太现实的,不是社区的常规做法。一般是针对不同发行版、不同版本单独打包。可以在独立的目标版本机上打,也可以临时拉一个 docker 进去打。虽然版本不行,但 rpm spec 或者 debian rules 未必不同(当然,而已有可能不同),不同的是打出来的包的依赖而已。

    另外还想问一下 OP ,你打包的目的到底是啥,你在公司里是什么角色,公司的 IT 基建环境怎么样……如果是纯开发的话,自己去想打包问题可能会有点累又自作多情,还是跟基建组的同事商量一下吧。
    adoal
        17
    adoal  
       64 天前
    虽然版本不行 => 虽然版本不同
    Chipmunker
        18
    Chipmunker  
       64 天前
    @liuguangxuan OP 你好。我感觉你要实现的效果和各大厂商的在 Linux 端的闭源程序做法有点像啊!例如 Wolfram Mathematica 程序及 NVIDA 的驱动等。他们就是发布一个单个的二进制文件,在不同发行版下都是通用的。

    我不太清楚他们的具体实践如何,我推测了一个类似的操作,或许可以实现相近的效果:
    1. 首先按照预设运行平台,使用 cmake 中的 cpack 来生成对应平台的包( rpm, deb );
    2. 编写安装脚本,其中包含判断平台,安装对应平台的包到系统,执行 systemd 操作之类的;
    3. 将包和脚本组合在一起,生成单个可执行文件。这里有一个简单示例: https://blog.zhenglin.work/linux/how_to_made_bin.html

    以上只是我的设想,没有具体操作过,不知是否能够完美实现 OP 需求。
    liuguangxuan
        19
    liuguangxuan  
    OP
       64 天前
    @adoal #16 检测发行版的目的:有的用户是 CentOS ,有的是 Ubuntu ,所以有了想检测发行版的想法。最初的想法打包时检测,分别打成不同的包,CentOS 的用户就给 rpm 包,Ubuntu 用户就给 deb 包。

    rpm 的 spec 我研究了一下,好像最终是使用 rpmbuild 来打包,debian 的 rules 还没来得及研究。

    关于打包目的和在公司的角色:我在公司是开发,因为人手不够,所以兼顾运维、写文档等等。至于公司的 IT 基建环境,可以说为 0 ,没有任何规范,一切都靠自己,所以只能摸索前进。我看到很多开源的工具都提供 rpm 包,就想着这个可能就是发布程序的最佳实践,就想学习一下,然后应用到公司以后发布程序中。

    另外没有进过大厂,也不知道大厂的分工,这是我第一次听基建这个词,老哥能否介绍一下大厂的各个部门,以及各个部门的职责。
    liuguangxuan
        20
    liuguangxuan  
    OP
       64 天前
    @Chipmunker #18 感谢老哥,发的这个链接,感觉里面思路有点儿清奇,是个办法。

    但是我想做的其实就是你说的第一步,“首先按照预设运行平台,使用 cmake 中的 cpack 来生成对应平台的包( rpm, deb )”,我想实现的是 cmake 自动能识别平台,比如为 CentOS 或者 Ubuntu ,然后分别达成 rpm 包,或者 deb 包。老哥有没有推荐的教程啊?
    adoal
        21
    adoal  
       64 天前   ❤️ 2
    @liuguangxuan Linux 的软件安装是个很复杂的生态。可以不管发行版,自己从上游软件的源代码开始编译安装,也可以不用管 File System Hierachy 规定的什么文件放在什么目录……实际上大部分上游软件编译之前的 configure 或类似阶段的默认值就是不遵循 FSH 的。但有发行版在,对于普通用户节省了挑选上游软件具体版本测试其搭配的兼容性的精力。

    同时,发行版会在自己编译开源软件时做一些风格上的适配,比如约定不同类别的文件放在什么路径、后台服务程序用什么机制启动、配置文件如何细分到各种**.d 里以便把插件的配置和主配置分开方便自动修改、日志文件如何定时切分,等等。

    rpm 和 deb 是两大主流发行版 RH 系和 Debian 系的“御用”格式,发行版本身包含的组件(比如 Debian 当前版本里有 8 万多个软件)是用这两种格式来打包的。通常比起上游来经过了一系列统一风格的改造。理论上是可以跨越发行版混装的,但实际上有很多问题,有些能装成功有些则不行。所以正常的做法是,写好 spec/rules 然后针对用到的特定目标发行版和目标版本来做自动打包,当然 spec/rules 是有兼容性问题的,也要好好适配同一发行版的不同版本。你厂 IT 基建环境基本为 0 的话而你又要兼作基建的话,那强烈建议现阶段尽量减少发行版 /版本的数量。比如都统一到 Debian 或者 CentOS 的一两个版本上。暂时统一不上去的,以后逐步改版替换。操作系统版本迭代导致的屎山,等以后再去想办法治理,现阶段既然是 0 ,还是尽量简化。

    还有很多开源软件(有的闭源软件也是),是发行版不会包含或者还没收录的,上游作者有时候也会打包成 rpm 或者 deb ,让用户能以使用发行版的相同操作风格来管理。甚至有些体积很大的,比如 GitLab ,比如 Elastic Search 。

    但是打包 rpm 或 deb 往往是个吃力不讨好的事,因为很多人(尤其是纯开发角色的)其实不太在乎运维方面的讲究,他们更喜欢一个 tar.gz 原地解压后的 everything-under-prefix 方式,认为这样更方便和自由,而 rpm 或 deb 里遵循 FHS 等规范的生产环境打包方式对开发来说太麻烦了,比如要考虑各种路径的权限、执行时的用户身份等,而且“散落”在不同的地方,开发过程中查找起来麻烦,等等。在企业里,基建团队打包 rpm/deb 是不产生直接的业务绩效的,开发团队对这些玩意的认可度也不高。所以往往会有企业根据自己踩过的各种坑自己搞得各种“最佳实践”。其实长线下来 rpm/deb 的学习成本未必高,但是起点高,要学一大堆不能马上产生绩效的“乱七八糟”的东西,而且很可能不讨大部分开发人员喜欢。所以大部分厂的业务型软件都不太用发行版包的方式来发布。

    所以,虽然我自己(一个甲方的综合信息化人员)比较喜欢按发行版打包、按 FHS 布局的行为,但在这贴里还是建议你慎重考虑。因为精力投入会比较大,不产生业务绩效,而且不太容易被其他人接受。看看这贴里的很多回复就知道了。当然,如果你觉得值得,自己能 hold 住,说不定会成为业界尤其是国内业界与众不同的一股清流( or 泥石流)。


    另外,还有值得一提的是,发行版的打包方式,其实是很传统的了。在云原生时代,很多软件对于外部依赖组件所采取的 vendoring 策略跟发行版打包是矛盾的。Debian packaging team 曾经尝试把 K8S 给 deb 化,但 K8S 特定版本和 Debian 特定版本的第三方依赖锁定版本冲突,始终没办法很好解决,最后终于放弃。LWN 上还曾经专门有一篇讨论。最后的结论是,三观不同没法强融。
    adoal
        22
    adoal  
       64 天前   ❤️ 1
    @liuguangxuan 不清楚用 cmake 如何自动识别发行版再打包……但正常的做法是,当软件出新版之后,用批处理流程为支持的每个发行版+版本组合自动起相应的 docker ,在 docker 里面打包。可以参考有个开源 API 网关叫 APISIX 的 build 系统 apisix-build-tools ,使用时可以通过参数指定包格式、发行版、版本号,只要自己写一个脚本来批量多次调用打包工具就行了。
    adoal
        23
    adoal  
       64 天前   ❤️ 1
    就是说,你改好软件功能,测试通过了,要打包了,假设你公司的生产和开发环境使用以下发行版+版本,那……
    拉起一个 centos 8 (或者 alma 8 、rocky 8 、龙蜥 8 )的 docker ,在里面打出 -el8 的 rpm 包;
    拉起一个 centos 7 的 docker ,在里面打出 -el7 的 rpm 包;
    拉起一个 debian 11 的 docker ,在里面打出 -bullseys 的 deb 包;
    拉起一个 ubuntu 20.04 的 docker ,在里面打出 -focal 的 deb 包。
    把这 4 次拉起 docker 写成一个批处理脚本自动跑完就好。
    adoal
        24
    adoal  
       64 天前   ❤️ 1
    建议你说服领导,把公司的操作系统环境统一,至少生产环境要统一,开发环境谁不愿意跟着走的要自己负责由此导致的兼容性问题。
    liuguangxuan
        25
    liuguangxuan  
    OP
       63 天前
    @adoal #24 感谢老哥回复,有理有据。现在已逐步放弃了打包的想法了。😂
    Chipmunker
        26
    Chipmunker  
       63 天前
    @liuguangxuan 如果你是做为软件发布者发布包,那么你需要对不同平台进行打包,这个你可以在不同的 docker 镜像里做,写一个脚本判断系统平台,然后给 cmake 传入不同参数即可。判断的方式应该就是你说的那个办法吧。我在 stackoverflow 找的一个类似的: https://stackoverflow.com/a/62960931/8097964

    如果你是指分发给用户之后再打包,那么完全没必要啊,cmake 不是有 install 操作麽?没必要打包啊!
    byaiu
        27
    byaiu  
       62 天前
    xmake+xrepo 可能是一个可选项

    如果我自己有 c++的项目,可能会考虑用这个来做构建工具+发布。
    chilledheart
        28
    chilledheart  
       58 天前
    不复杂,如果考虑一般用户(比如老版本的 debian 或者 archlinux 之类的)可以考虑用定制的 alphine linux 编译打包成通用的 tar.gz 。可以参考 chromium 打包。
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1809 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 67ms · UTC 16:56 · PVG 00:56 · LAX 09:56 · JFK 12:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.