V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
adoyle
V2EX  ›  Linux

分享一个 Bash 脚本编程类库 Lobash

  •  3
     
  •   adoyle ·
    adoyle-h · 2019-07-02 09:35:00 +08:00 · 7889 次点击
    这是一个创建于 2002 天前的主题,其中的信息可能已经有所发展或是发生改变。

    https://github.com/adoyle-h/lobash

    看名字你或许猜到了,这是一个受到 JS 的 Lodash 启发的,专用于 Bash 编程的类库。

    Bash 脚本的坑很多,我期望能写一个类库,把复杂的东西封装到简单的函数(模块)里,一个函数只做一件事情。以此来增强开发体验。

    我已经写了 90 个模块,近 500 个单测,大致 API 和开发模式已经稳定。

    我曾尝试想将 Lobash 支持 Zsh 的,搭完测试框架和环境,跑了一下测试发现,Zsh 和 Bash 还有很多不一样的地方。所以决定放弃支持 Zsh,可能哪天我会再写个 Lozsh 库。

    我在自己的 Dotfiles 里试吃了自己的狗粮,没有遇到什么问题。所以来试用一下吧,有什么感想提 Issue 或在这个帖子里留言即可。提 Issue 请尽量用英文,用中文也可以。

    如果觉得有意思,欢迎与我一起共建。
    如果觉得不错,请点一下 Star,让我有动力继续开发,谢谢。

    第 1 条附言  ·  2019-07-07 16:02:49 +08:00

    发布了 v0.2.0 版本,主要改动是

    1. Bash 兼容性,从 4.4+ 改为 4.0+
    2. 修正了一些模块的 bug
    3. 更完善的文档,更友好的交互命令

    具体见 ChangeLog

    第 2 条附言  ·  2019-07-08 01:36:56 +08:00

    发布了 v0.3.0 版本,主要改动是条件判断都支持了 return 0/1 的方式。但有不兼容之前版本的修改。

    • 大部分条件判断的模块都提供两种实现,像是 l.is_file 和 l.is_file.s。
      • l.is_file 是 return 0/1 的形式
      • l.is_file.s 是 echo true/false 且 return 0 的形式,.s 代表着 strict
    • 重命名了一些模块
      • l.true => l.truthy.s
      • l.false => l.falsy.s
      • l.strict_has => l.has.s
      • l.is_writeable => l.is_writable.s
    • l.has not 不支持了,改成了 l.has_not

    为了保持可读性,考虑到项目初期用的人不多,于是产生了不兼容的修改,各位见谅。以后应该不会有这种不兼容修改了。

    具体见 changelog

    这个帖子里提到的问题应该都修改好了。后续有问题请到 issue 里提问。

    第 3 条附言  ·  2019-07-12 21:48:34 +08:00

    最后一条 APPEND 发布了 0.4.0 版本,主要做了以下改动

    1. nameref 的功能用 eval 代替了,所以目前只有 3 个模块不支持 4.0,其余 110 个模块都已支持 4.0+。具体见 module usages
    2. 支持自定义导出,之前是默认导出所有模块的,现在你可以选择只导出想要的模块。
    3. 新增 l.parse_params 模块,解析命令行参数用的,个人感觉比 getopt/getopts 方便。具体用法看单元测试或者例子。
    4. 新增 l.match_list 模块,正则匹配同时提取多个数值用。
    5. 修正了 union_array 的 bug
    6. 导出模块时去掉了一些不必要的代码和注释,减少了生成的 lobash 的代码行数。

    其他具体见 changelog

    最后,欢迎大家提意见,或者把这个库分享给其他人。

    60 条回复    2019-07-03 13:45:18 +08:00
    dandycheung
        1
    dandycheung  
       2019-07-02 09:51:55 +08:00 via iPhone
    手动点赞,挺好。
    Meltdown
        2
    Meltdown  
       2019-07-02 09:58:21 +08:00 via Android
    不错,收藏
    wutiantong
        3
    wutiantong  
       2019-07-02 10:00:43 +08:00
    看起来不错
    pony279
        4
    pony279  
       2019-07-02 10:08:49 +08:00   ❤️ 10
    无意冒犯,还是忍不住泼点凉水,bash 虽然可以当编成语言用,但这怕不是 shell 脚本的初衷

    100 行内还搞不定的事情,还坚持用 bash 就是糟糕的选择

    写 bash 的人就应该熟悉语法,就是追求极简,用

    l.is_file() {
    [[ -f ${1:-} ]] && echo true || echo false
    }

    if [ $(l.is_file $filename) == "true" ] ; ... fi

    这样罗嗦的方式来替代

    if [ -f "$filename" ] ; then ... fi

    是不明智的选择

    如果有用各种基础库的需求,还不如重新设计一个语言,bash 干这个真的特别别扭
    adoyle
        5
    adoyle  
    OP
       2019-07-02 10:27:20 +08:00   ❤️ 4
    @pony279

    > 100 行内还搞不定的事情,还坚持用 bash 就是糟糕的选择

    坚持还是不坚持,是用户的理想判断和选择自由,Lobash 只是为选择 Bash 提供一些帮助而已。100 行内搞不定的事情,确实可以考虑其他语言。但为什么要选择 bash 呢?我觉得在于依赖,比如你用 nodejs 写,运行你程序的用户需要在运行平台装 node,依赖的版本管理升级怎么办,这会引入更多问题。bash 和 linux 命令行大多数是通用的,虽然我这个库需要用 bash 4.4,而现实上 linux 装的大多数是 bash 4.3,但是升级一下 bash 还是很简单的事。


    > 写 bash 的人就应该熟悉语法,就是追求极简
    这是对于熟练工而言的,当你只是想用 bash 用管道去写个小程序,当你去翻 bash 手册熟悉语法越陷越深,就我的经验而看 bash 有是很多坑的,学习的过程是比较痛苦的。

    is_ 系列为什么要这么啰嗦的返回 true 或者 false ?请看这个链接
    https://github.com/adoyle-h/lobash/blob/develop/doc/how-to-write-functions.md#how-to-return-a-boolean-value
    0x11901
        6
    0x11901  
       2019-07-02 10:28:02 +08:00
    没有 API 文档吗?不可能 90 个模块需要我自己看哪个能用上吧……

    还有实名反对楼上的观点。
    adoyle
        7
    adoyle  
    OP
       2019-07-02 10:28:14 +08:00
    刚刚打错字了,理想判断 => 理性判断
    adoyle
        8
    adoyle  
    OP
       2019-07-02 10:29:34 +08:00
    @0x11901 请仔细看 README,https://github.com/adoyle-h/lobash#module-usages
    这里有用法,描述,例子,单测的链接,晚上有空我再加个跳到源代码的链接。
    hgjian
        9
    hgjian  
       2019-07-02 10:33:39 +08:00 via Android
    没有中文文档,看不懂哦,我英语差。
    adoyle
        10
    adoyle  
    OP
       2019-07-02 10:35:59 +08:00
    @hgjian 不好意思,以后也不会加中文文档的,英语差可以翻字典一个个词来看,我也是从英语渣渐渐成长的,相信你也可以做到。
    jorneyr
        11
    jorneyr  
       2019-07-02 10:38:04 +08:00
    挺好的
    YK46PTT
        12
    YK46PTT  
       2019-07-02 10:40:01 +08:00
    挺好的, 之前也想找这样的 repo
    zhanglp888
        13
    zhanglp888  
       2019-07-02 10:52:09 +08:00
    赞,感动!
    repo 现有的模块,已经能完成我基本所有的需求了
    等我仔细看一下单测,再谈感想~
    pony279
        14
    pony279  
       2019-07-02 10:54:31 +08:00   ❤️ 1
    > 我觉得在于依赖,比如你用 nodejs 写,运行你程序的用户需要在运行平台装 node,依赖的版本管理升级怎么办,这会引入更多问题。bash 和 linux 命令行大多数是通用的,虽然我这个库需要用 bash 4.4,而现实上 linux 装的大多数是 bash 4.3,但是升级一下 bash 还是很简单的事。

    1. 这取决于你的业务。如果本身没有什么依赖,能用 bash 写的,同样可以用兼容性好的 node 脚本完成。就是因为逻辑复杂了,才会不得不选择 node, java, go, python, php,才会有各种依赖和版本管理。

    2. 升级 bash 4.4 就是修改你的系统工具了,至少需要 root 权限吧,有 root 权限安装个 node/php/python 也是一条命令的事情。

    > is_ 系列为什么要这么啰嗦的返回 true 或者 false ?请看这个链接

    > The way 2 cannot distinguish the false and the exception occurs in function (it will return other codes if your shell has set -o errexit and set -o pipefail). So the choice 1 is better.

    return 0/1 / echo true/false 确实有这样的优缺点

    长期做开发的人确实有严谨的逻辑

    但是,从我多年写过的 bash 脚本来看,我根本不需要这些啊,如果按照你的考虑,每条都严谨处理,你的 l.is_file 会变成这样:

    isFile=$(l.is_file $filename) # when exception with set -e, the script will abort immediately
    if [ "$isFile" == "true" ]
    then
    ...
    fi

    为了极度的严谨罗嗦正这样,何必呢。有这样的需求,正统的编成语言才是最优解。

    再退一步想想,is_file 这种底层只依赖简单系统调用的东西都能异常,怕是整个操作系统即将崩溃了,就好比天塌下来了,为啥要关心桌子上的水杯还在晃。
    dandycheung
        15
    dandycheung  
       2019-07-02 11:02:50 +08:00 via iPhone
    @pony279 总会有一些我们每个人都想象不到的场景的,作者的努力让人有了更多的选择,世界也没有因此而更糟。我为什么需要呢,因为我有一块用一块淘汰了的 1GB 或者 2GB 的 TF 卡做系统盘的 Pi 板子,装个 Python 就有点嫌大,bash 刚刚好,就这样。
    Karpov
        16
    Karpov  
       2019-07-02 11:04:28 +08:00 via iPhone
    对于 bash 场景有了很好的选择,谢谢分享
    pony279
        17
    pony279  
       2019-07-02 11:10:03 +08:00
    @dandycheung 我并没有打算否定作者的努力,我只是从我个人经验和实用性的角度解释这类工具的必要性。作者有他坚持的理由,我有不需要的理由,就是这么简单啊
    adoyle
        18
    adoyle  
    OP
       2019-07-02 11:12:29 +08:00
    @pony279

    > 2. 升级 bash 4.4 就是修改你的系统工具了,至少需要 root 权限吧,有 root 权限安装个 node/php/python 也是一条命令的事情。

    全局安装了这些,多个不同的项目有相同依赖就会有版本冲突和不兼容的风险,所以我通常不推荐全局安装,用 nvm,rvm,gvm 来装各种语言环境。

    在 Lobash 这个库我也考虑如果有多个类库来使用 Lobash,其他项目间接依赖多版本的 Lobash 怎么办。因此我使用 ./build + PREFIX + 时间戳 的方式来生成项目自己唯一的 lobash.bash。

    用户选择什么方案,就要考虑这个方案的成本,具体细节具体分析吧。我只是为 Bash 增加使用的可能性,并不影响用户的判断,用户需要自己来判断自己需要什么。


    > 为了极度的严谨罗嗦正这样,何必呢。有这样的需求,正统的编成语言才是最优解。

    恩,你说的有道理。因为我急于开发出这套框架来应用,return 0 1 在我看来不理想,为了 API 格式统一我先选择了严谨的写法,严谨虽然麻烦但总不会出错。你的意见我需要一点时间再考虑,如果确实没问题,可以新增一批模块,提供更多方便的选择。
    yidinghe
        19
    yidinghe  
       2019-07-02 11:14:30 +08:00
    我是支持楼主的,我自己也写过简单的运维脚本 https://gitee.com/yidinghe/codes/394evuspjc1qfrwyzd2no37,只是用来启动和停止进程。另外我开启了 issue #2。
    rrfeng
        20
    rrfeng  
       2019-07-02 11:23:22 +08:00 via Android
    支持楼主的想法做法
    但是实用性确实有限…
    adoyle
        21
    adoyle  
    OP
       2019-07-02 11:26:25 +08:00
    @rrfeng 恩,程序员嘛,就喜欢瞎折腾
    hljjhb
        22
    hljjhb  
       2019-07-02 11:31:24 +08:00 via Android
    bash 4.4+ 基本与服务器无缘了
    iwtbauh
        23
    iwtbauh  
       2019-07-02 11:35:36 +08:00 via Android   ❤️ 3
    @pony279 #4

    Linux 内核源码里面也有很多几百行的 shell 脚本。而且是 POSIX shell 脚本,连 bash 都不是。

    如果你看一个发行版的源码树,你会发现很大的 shell 脚本多的是。

    为什么他们要写这么长的 shell 脚本呢。原因在于需求决定了使用 shell 比其他语言更合适。源码树里还有大量的 perl 脚本和 c 代码,为什么这时候不用 shell,自然是因为解决相应的需求用另外的语言合适。而不是代码行数决定的。

    “ 100 行以上不选 bash ”就像超过 100 米长的路不能骑单车一样可笑。
    ps1aniuge
        24
    ps1aniuge  
       2019-07-02 11:45:11 +08:00   ❤️ 4
    1 你用 bash 写 bash 库,我真的很佩服你。
    2 我的观点:把 bash 扔到角落里,基本不用。99%用 powershell。
    3 powershell win,linux 通用。
    4 你的库对强类型支持如何?用你的库能实现布尔么?
    powershell 有强类型。比如布尔,py 也有。还有 fish。
    py 的主要问题是没有命令行管道。fish 的主要问题是它没有强类型库做底层支撑。

    5 依赖。
    5.1 啥也不装就啥功能都有。---无法实现。
    5.2go 次好。但是 go 并没有提供命令行框架。也没有提供命令行。
    5.3powershell 提供一揽子框架。安装简单。依赖比 py 好。没有绝对路径。
    5.4py 没提供命令行,管道。安装有时需要编译。

    结论:powershell 是最好的。

    6tab 补全。
    bash 一手好牌打烂了,还坑了 go。
    用 go 开发的命令行程序,依赖 bash,依赖 bash 补全,那就要写补全脚本,
    https://www.v2ex.com/t/563986#reply0

    7 调试 shell 不行。
    用 vscode+powershell,帮 shell 脚本实现单步,断点的例子
    https://www.v2ex.com/t/575848#reply1

    最终结论:
    1bash 还有救么?
    2 所有给 bash 续命的,都是幺蛾子,在 powershell 面前不值一提。命真续不了了。

    3powershell 的主要优势
    3.1win,linux 通用
    3.2 后台硬(.net 库强)
    3.3 常用库基本齐全。
    3.4 有像 pypi 那样的官方,第三方存储库。一件安装任何扩展。有 n 大企业支持,给它发布模块。
    3.5 有
    命令行。
    管道。
    对象。管道前后传强类型对象。从 win 到 linux,用 ssh 远程传对象。
    远程调试。
    自动上传脚本到远程。

    powershell 才是爱脚本人的未来,楼主既然这么强。何不编写 powershell 的脚本,放在 [powershell 画廊] 。帮助完善 powershell ?

    powershell [强] [简] 死你!
    adoyle
        25
    adoyle  
    OP
       2019-07-02 11:53:47 +08:00
    @hljjhb 诶,我也很纠结。`inherit_errexit` 选项 bash 4.4 才有,`Nameref` 4.3 才有,这两个我很难割舍。

    `inherit_errexit` 保证程序按我理想的来,如果没有这个保证,就会有各种坑,具体看[这个链接]( https://mywiki.wooledge.org/BashFAQ/105),这对 bash 脚本开发者是个负担。

    `Nameref` 主要是传递数组很方便。

    bash 4.4+ 是基本与服务器无缘了,最多只能在 docker 里跑,但都能跑 docker 了,环境依赖问题就没有了,想用什么语言都行何必用 bash。
    ps1aniuge
        26
    ps1aniuge  
       2019-07-02 12:06:23 +08:00
    一个老烂番茄,你去顶,将会顶出一头臭汁。你应该去踩 2 脚。

    powershell 不是开源的? 不是免费的?

    问:powershell 啥时候开源(+免费)的?
    答:
    2015 年小范围内部开源,2016 年开发者大会上,正式法律开源。



    问:开源后的 powershell,属于谁的财产?
    答:
    在遵守其开源协议的前提下。powershell 开源后。属于 [社区财产] 或 [任何人财产] 。



    问:谁是 powershell 开源免费的最大受益者?
    答:
    powershell 可以运行在,win,mac,ubuntu1404+,centos7,debian8+,suse12+,arch,alpine linux,树莓派 Raspbian,win10-iot,docker,snap-app,open-wrt 路由器等。
    这些系统使用者,是 powershell 开源免费的最大受益者。



    问:powershell 完全开源了么?
    答:
    不完全是。
    1 powershell 之所以简单、强大、好用。靠的是 powershell5.1+win 自带的 powershell 库。我们应该主要使用这些库。
    这些库,并没有开源。开源之前,是否免费我也不清楚。
    2 powershell6,powershell7,和相关的库,开源了。
    这里面的区别主要是 [win 自带软件,相关的 powershell 库] 。
    库数量很多,如 iis 的 ps 库。但这些 win 独有软件的 ps 库,跨不了平台。即便开源给 linux 也并没啥用。
    另外一些 win,linux 通用的 ps 库,比如 sqlserver 的 powershell 库,已经开源免费放在了 github 和 powershell 画廊。

    结论:
    1 开源时间太短,社区力量不强。ps 开源库还没成气候。
    2win 中的老旧不开源 ps 库挺好用。这些库中有价值的正在逐渐开源+跨平台。
    3 不开源的 ps 库,如 iis 的 ps 库,hyperv 的 ps 库,还将继续存在,并作为 win 功能的一部分。


    问:powershell 命令为啥那么长?我很不爽啊。
    问:powershell 命令会重名吗?
    答:
    powershell 命令太多,超过好几万。微软为了 powershell 命令不重名,所以把 powershell 命令搞的很长。
    正因为命令长,命令唯一,才让 ps 基本不需要像 python 那样,在脚本中 import 这个库、那个包。也没有 py 那种 [库或依赖] 路径问题。
    鱼与熊掌而已。唯一的长命令名,不需要学习记忆包名。
    实际上 linux 命令也很长。有很多子命令。比如:
    kubectl expose deployment nginx --type=NodePort --name=example-service
    git reflog expire --expire=now --all
    也有人说:“像 java 和 php 这种包名或者 namespace 又臭又长的”
    实际上库多了,包名字都会长。

    bash 不需要安装么?
    bash 是自带不需要装,但啥也干不了啊。你照样要东装一个包,西装一个包依赖软件。如:
    linux 上的 expect 这个工具,也需要装 tcl !
    impl
        27
    impl  
       2019-07-02 12:21:24 +08:00 via Android
    shell 不够,python 来凑
    q397064399
        28
    q397064399  
       2019-07-02 12:24:25 +08:00
    @impl #26 为啥不直接用 Python 可能我觉得脚本语法太古怪了 而且没找到好的调试工具
    Imr
        29
    Imr  
       2019-07-02 12:27:45 +08:00 via iPhone
    想法不错,支持一下。

    虽然就像前面那位说的熟悉 bash 的人肯定不会用到这些,但是把脚本语言正正经经写出来,挺有趣的不是吗
    Meltdown
        30
    Meltdown  
       2019-07-02 12:40:05 +08:00 via Android
    有了这种库的帮助,100 行 bash 就可以做更多的事情了。当然如果为了性能着想,我会考虑换成其他语言。
    xuboying
        31
    xuboying  
       2019-07-02 12:56:33 +08:00
    楼主的想法不错,不过当今 bash 确实不适合做复杂的事情了。
    1. 现在流行的容器化封装 init 程序直接启动 app,绕过 shell 了包括 bash
    2. 运维也可以用 ansible,复杂的任务可以交给 python
    3. bash 的可靠性也不太行,set -eu -o pipefail 异常捕获在自己的 term 下执行 OK,上了 ci 系统就失效了。一直搞不清哪里出问题。有空还得换成别的更可靠的语言
    sinopec
        32
    sinopec  
       2019-07-02 13:00:53 +08:00
    @pony279 确实 复杂点的 我为什么不用 python
    pony279
        33
    pony279  
       2019-07-02 13:03:52 +08:00
    @iwtbauh 100 行只是我随便提的数字,旨在说明复杂的逻辑不适合用 shell 完成,你杠这个数字的意义是什么?
    ps1aniuge
        34
    ps1aniuge  
       2019-07-02 13:10:18 +08:00
    大渣豪,我系渣渣辉,
    我会写一篇为什么不用 shell 脚本人,为啥要用 powershell,而不用 python。敬请期待。
    adoyle
        35
    adoyle  
    OP
       2019-07-02 13:20:20 +08:00
    @xuboying 你说的很对。果然这个库可能就是个玩具了
    playnoa
        36
    playnoa  
       2019-07-02 13:27:53 +08:00 via Android
    @ps1aniuge 这种名词+动词的方式其实很方便的,另外,教主,带我走~~
    leopku
        37
    leopku  
       2019-07-02 14:11:17 +08:00 via iPhone
    @adoyle 先点个赞

    不过在升级 bash 和安装 nodejs / java / golang 之间,我宁愿选择后者

    再说如果依赖成为问题,我会选择用 c / golang/rust 写
    Geeker
        38
    Geeker  
       2019-07-02 15:48:37 +08:00
    这个很强啊,平时写点小脚本还挺实用
    BruceAuyeung
        39
    BruceAuyeung  
       2019-07-02 15:56:32 +08:00 via Android
    很久之前我就有想搞一个这样的工具库,可是实在懒没干成,所以特地 star 支持下
    james122333
        40
    james122333  
       2019-07-02 16:02:43 +08:00
    这库才刚开始开发...
    不过我写的不会公开就是了
    参照我之前回复的
    https://www.v2ex.com/t/570005
    还可以这样搞

    readonly true=1
    readonly false=0

    return() {
    case $1 in 0|true) echo true ; builtin return 0 ;; 1|false) echo false ; builtin return 1 ;; *) echo $1 ; builtin return $1 ;; esac
    }

    shell 可以处理复杂逻辑吗? 当然可以 至于好不好维护是看个人怎么写
    jziwenchen
        41
    jziwenchen  
       2019-07-02 16:08:59 +08:00
    问下楼主 有没有 bash 学习的好资源推荐下?
    james122333
        42
    james122333  
       2019-07-02 16:11:17 +08:00
    把 builtin return $1 再加上判断是否数字会更好些 不是数字就不是状态了
    adoyle
        43
    adoyle  
    OP
       2019-07-02 19:26:33 +08:00
    @james122333 没看懂这个 return 函数有什么用。这是为了解决什么问题?

    我是为了让 return 0/1 只用来区分命令是否有异常,用 true/false 来区分命令返回值的真与否,并且配合 `set -o errexit` 和 `shopt -s inherit_errexit` 这样的先决条件,才这样写的 is_ 函数的。
    james122333
        46
    james122333  
       2019-07-02 19:58:01 +08:00
    @adoyle
    就是一起做阿 让 return 也拥有返回值的功能 并同时区分命令是否异常
    builtin return $1 改判断会更好就是了 两种都可以写
    adoyle
        47
    adoyle  
    OP
       2019-07-02 20:41:50 +08:00
    @james122333 大致了解了,想法很有创意,但是不符合我的需求。你看这段代码
    https://gist.github.com/c52d778b9b01c183d0eb41aa16892177#file-t-bash

    期望的是 is_success 返回 false,foo 收到后把结果打印出来,但执行会发现在 33 行就跳出程序了。
    因为 `set -o errexit` 和 `shopt -s inherit_errexit` 起了作用。

    `shopt -s inherit_errexit` 的目的是为了快速失败 (fast-fail),当 sub-shell 里抛异常了,那么当前 shell 也应该停下来而不是继续执行下去。所以 inherit_errexit 这个选项是必须的。
    我为了区分异常控制流和普通的数据流,才因此用 return 0 表示命令正常,return 1 表示类似 throw error。用 echo true 表示数值为真,用 echo false 表示数值为假。
    因此你说的 return 方式不符合我的需求。
    james122333
        48
    james122333  
       2019-07-02 22:38:33 +08:00   ❤️ 1
    @adoyle

    你需要的是改变写法 hahaha
    如以下

    #!/bin/bash

    shopt -s extglob

    readonly true=1
    readonly false=0

    set -E
    trap 'case $err in false) ;; *) exit ;; esac' ERR

    return() {
    case $* in
    0|true)
    err=true
    echo $err
    builtin return 0
    ;;
    1|false)
    err=false
    echo $err
    builtin return 1
    ;;
    +([0-9]))
    err=$*
    echo $err
    builtin return $err
    ;;
    *)
    echo $*
    ;;
    esac
    }

    test() {
    return false
    }
    huiyifyj
        49
    huiyifyj  
       2019-07-02 22:46:53 +08:00
    bash 这玩意写不动大一点的功能,这样折腾会写着就很累,除非支持模块化(像 powershell 那样)。
    james122333
        50
    james122333  
       2019-07-02 22:52:25 +08:00
    @huiyifyj

    可以自己写模块阿 只是没什么现成的而已
    我写了一堆 包括自动化的
    Cyshall
        51
    Cyshall  
       2019-07-02 23:08:59 +08:00 via iPhone
    @ps1aniuge 期待,能否麻烦到时候 @我一下。
    iMusic
        52
    iMusic  
       2019-07-02 23:21:30 +08:00
    star
    xiaolanger
        53
    xiaolanger  
       2019-07-02 23:42:59 +08:00
    写 bash 太累了,大佬厉害!还有,在服务器上升级 bash,基本与线上服务无缘了吧
    adoyle
        54
    adoyle  
    OP
       2019-07-03 09:04:21 +08:00
    @james122333 酷!利用 trap 真是巧妙的点子,感觉很有启发,可以改进 Lobash。感谢分享
    adoyle
        55
    adoyle  
    OP
       2019-07-03 09:09:48 +08:00
    @huiyifyj

    > bash 这玩意写不动大一点的功能

    你见过用 bash 写的 docker 吗? https://github.com/p8952/bocker
    虽然是依赖了很多 linux 程序,15 年就停止更新了,但功能不算简单吧。
    还有 Lobash 中使用的测试框架 [bats-core]( https://github.com/bats-core/bats-core) 也是纯 bash 编写,功能挺复杂的。
    还有很多有意思的 shell 命令: https://github.com/alebcay/awesome-shell

    能写出什么东西,一部分取决于语言的表达力,一部分取决于你的想象力。

    > 这样折腾会写着就很累,除非支持模块化(像 powershell 那样)

    通过唯一的命名空间来做模块化,Lobash 就是这么做的,Bash 脚本一般依赖不多的,可以人为控制避免命名冲突,虽然糙了点但能用啊。
    然后,难道支持了模块化用了 powershell 就会不折腾么?每种方案都会伴随自身的局限,是否折腾要结合你的具体上下文来看。怎么避免就要靠你的聪明才智了。
    adoyle
        56
    adoyle  
    OP
       2019-07-03 09:20:19 +08:00   ❤️ 1
    @xiaolanger @hljjhb

    想了一下,线上服务其实也能跑。Lobash 可以支持 4.2+。但数组相关的模块还有 sub/inc 模块一共 9 个模块无法使用,起码剩下 80+ 个模块是可以用的。

    具体分析如下:

    Lobash 依赖 4.4 的 inherit_errexit 特性和 4.3 的 nameref 特性。

    但在 4.4 出来之前,还是有很多用 Bash 写的脚本在线上跑也没出问题嘛。
    所以 inherit_errexit 这个开关可以是个可选项(原本就是开发者自己选择去开的),
    开启 inherit_errexit 是为了保证 fast-fail,
    如果没开它,那就由开发者自己负责保证不触发异常情况(这本就是开发者应做的),多测试各种边界,那还是能在 4.3 上跑的。于是 Lobash 就可以兼容到 Bash 4.3+。

    4.3 的 nameref 特性也不是所有模块都有用到,目前就数组相关的模块还有 sub/inc 模块一共 9 个模块有用到。
    判断模块是否有用 nameref 特性的方法很简单,只要调用方式是传递变量名的,都是用到了 nameref 特性。
    于是你只要使用剩下的模块,阉割了部分功能的 Lobash 就可以兼容 Bash 4.2+ 啦。
    不过还需要你改下生成的 lobash.bash 里的 check_supported_bash_version 函数,把版本号检查改到 4.2,默认是 4.4。

    我这线上 centos 都是 Bash 4.2,我想应该不会有更低的线上版本了。
    ChristopherWu
        57
    ChristopherWu  
       2019-07-03 10:50:16 +08:00
    题外话,我的经验: 凡是不能 3 分钟内写完的 bash 脚本,都特么用 python 写绝对没错。
    你根本想象不了 bash 语法多难记,有多坑。
    adoyle
        58
    adoyle  
    OP
       2019-07-03 11:04:48 +08:00   ❤️ 1
    @ChristopherWu 题外话,可能你需要这个工具 https://github.com/koalaman/shellcheck
    iyaozhen
        59
    iyaozhen  
       2019-07-03 12:46:24 +08:00
    @adoyle 我看了下我公司的服务器很多是 3.00.22(2)-release,最高是 version 4.1.17(2)-release
    而且生产服务 bash 等组件是不能升级的。
    我感觉楼主还是尽量向下兼容吧
    adoyle
        60
    adoyle  
    OP
       2019-07-03 13:45:18 +08:00
    @iyaozhen 好的,根据上面的说法,我觉得应该可以在少部分模块不可用的情况下支持到 4.0+,Bash 3 就饶了我吧,不想蹚这浑水。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3011 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 13:22 · PVG 21:22 · LAX 05:22 · JFK 08:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.