# shcanpool **Repository Path**: wangjunqun/shcanpool ## Basic Information - **Project Name**: shcanpool - **Description**: A simple shell command-line framework - **Primary Language**: Shell - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: https://gitee.com/icanpool/shcanpool - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 11 - **Created**: 2025-04-21 - **Last Updated**: 2025-04-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README - [1. 简介](#1-简介) - [2. 仓库](#2-仓库) - [3. 目录](#3-目录) - [4. 使用](#4-使用) - [4.1. 开发](#41-开发) - [4.2. 执行](#42-执行) - [4.3. 环境](#43-环境) - [4.4. 配置](#44-配置) - [4.5. 参数](#45-参数) - [4.6. 调试](#46-调试) - [4.7. 插件](#47-插件) - [4.8. 组件](#48-组件) - [5. 测试](#5-测试) - [6. 案例](#6-案例) - [7. 结语](#7-结语) # 1. 简介 shcanpool是一个精选的shell脚本框架,采用面向过程的编程思想,可用于开发命令行管理工具。 # 2. 仓库 - gitee:[https://gitee.com/icanpool/shcanpool](https://gitee.com/icanpool/shcanpool) # 3. 目录 |一级目录|二级目录|说明| |:---|:---|:---| |misc||杂项脚本,小工具| |projects||工程| ||demo|样例工程| ||……|| |src|apps|应用(命令)脚本| ||base|基础脚本| ||libs|基础库脚本,基于标准命令实现| ||misc|杂项脚本,按需使用| ||plugins|特定的库脚本| ||utils|通用脚本,框架的核心| |template||模板文件| |test||测试脚本| |tools||工具脚本| 备注:utils和libs中的脚本都是通用的,可以广泛的用在别的项目中。 # 4. 使用 以projects/demo工程为例进行讲解,用户可以参考demo工程开发个人命令工具。 |一级目录|说明| |:---|:---| |demo.sh|命令入口| |apps|应用(命令)脚本| ## 4.1. 开发 如何开发一个功能?以helloworld.sh为例,如下: ```shell method_def helloworld usage_helloworld() { printf "helloworld (hello): Hello to the world usage: ${PROG} hello " } alias_def helloworld hello do_helloworld() { echo "hello world" } ``` 1. 一个功能必须定义两个函数:do_helloworld,usage_helloworld 备注: * do_xxx和usage_xxx后面的名字必须一致 * usage_xxx第一行是功能的简述,通过':'分割 2. 一个功能通过method定义后才生效:method_def helloworld 备注: * method定义的方法,最终以子命令的形式存在 3. 一个功能别名通过alias定义:alias_def helloworld hello 备注: * alias定义的别名,最终也以子命令的形式存在 * ailas可以定义多个别名,比如:alias_def helloworld hello hw ## 4.2. 执行 通过执行 ```demo.sh``` 脚本来执行不同的功能。 1. 查看所有帮助信息 ``` bash demo.sh [-h|--help] ``` 2. 查看命令帮助信息 ``` bash demo.sh h helloworld bash demo.sh h hello ``` 3. 执行命令 ``` bash demo.sh helloworld bash demo.sh hello ``` ## 4.3. 环境 功能中会使用一些非系统内嵌的命令,这些命令可能需要单独进行安装,通过下面命令可以检测当前系统中是否存在用到的相关命令: ``` bash demo.sh checkenv bash demo.sh ce ``` ## 4.4. 配置 有些命令需要先配置信息,配置模板文件在config/template.conf中,通过变量CONFIG_FILE指定配置文件。 提供了两个命令用来管理配置文件:init,set ``` bash demo.sh init bash demo.sh set ``` init:初始化配置文件 set:设置/编辑配置文件 ## 4.5. 参数 1. 复数 有的命令可能需要支持批量操作,一种是循环调用命令,另一种是支持复数参数(命令内部根据复数循环),参数一般使用空格进行分割,某个参数如果是复数也使用空格进行分割的话,将会和命令参数冲突,下面有两种方法解决冲突问题: 1)将复数参数用双引号括起来当成一个命令参数,然后双引号内用空格分割,如:"a b c d"。 2)将文件名当成一个命令参数,然后文件中保存批量数据,数据可以一行一个,也可以用空格分割每个数据,如:file1,内容如下: ``` a b c d ``` 方法1)可以用来临时性的批量操作,比较快速和方便;方法2)可以固化命令格式,只需要根据实际修改文件内容。 处理复数的函数是:get_list 提示:目前批量数据必须是连续有效字符,不能中间出现空白字符,否则会被解析为多个数据。 ## 4.6. 调试 1. BASH 选项调试法 ``` bash -x demo.sh ... ``` 2. SH_OPTION 变量调试法 有一种更好的使用demo的方法是,在用户bin或系统bin目录下创建指向demo.sh的软连接demo,然后就可以在任意目录下像执行系统命令一样执行demo,如下所示: ``` ln -s /path/to/shcanpool/projects/demo/demo.sh demo ... demo -h ``` 如果执行demo命令,那么就无法通过bash来执行demo,为了方便调试增加了变量SH_OPTION。 1)在入口脚本中需要先加载base/env.sh才可以使用变量SH_OPTION,如: ``` load $SHCANPOOL_DIR/src/base/env.sh ``` 2)demo.sh脚本中默认已经加载了base/env.sh,所以像如下方式执行,也可以进行调试: ``` SH_OPTION=x demo ... ``` 备注:SH_OPTION可以组合设置为bash常用的选项,如:SH_OPTION=xe 等效为 set -xe 3. 调试命令 有时希望单独调试某个命令,可以通过debug命令,如下所示: ``` demo d help demo debug help ``` 4. 调试函数 有时想验证一个函数实现的功能,一般是将其封装成一个子命令,这样比较麻烦,可以通过call命令来快速测试,如: ``` demo c usage_help demo call usage_help ``` ## 4.7. 插件 插件化开发可以动态扩展软件的功能,即插即用。 shcanpool 提供的插件化思想是:用任何语言开发功能,接着用 x.sh 脚本封装调用,然后一起放到 plugins 目录中。 备注:x 为具体的功能名,插件一般约定俗成的放到 plugins 目录,放到其它目录中也可以。 ## 4.8. 组件 有时一个功能模块只使用一个命令可能无法更好的满足使用,但如果为一个功能开发相应的多个命令,又可能会出现命名问题,比如: - 通过名称可能无法有效的知道哪些是针对一个功能的 - 随着功能的丰富,不同功能可能需要同名的命令,比如:ls,help 基于上述场景,就需要支持组件化(模块)开发,即一个命令支持子命令。 假设组件为 xyz,提供 help 和 list 子命令,开发流程如下: ``` method_def xyz usage_xyz() { module_usage "xyz (x)" "module brief description" } alias_def xyz x do_xyz() { module_do "xyz" "$@" } __xyz_get_subcmd() { local cmd="" case "${1}" in "h"|"help") cmd="help" ;; "ls"|"list") cmd="list" ;; esac echo "$cmd" } xyz_usage_help() { module_usage_help xyz } xyz_do_help() { module_do_help xyz "$1" } xyz_usage_list() { printf "list (ls): List all items usage: ${PROG} xyz ls \n" } xyz_do_list() { echo "module demo" } ``` 1. 一个组件必须定义三个函数:do_xyz,usage_xyz,__xyz_get_subcmd 备注: * do_xxx 和 usage_xxx 同基本的功能定义 2. 子命令必须定义两个函数:xyz_do_xxx,xyz_usage_xxx 备注: * 函数必须以组件名作为前缀,一方面用于标识属于同一个组件,另一方面防止命名冲突 # 5. 测试 shcanpool 提供了一个简易的测试框架 test/libs/ut.sh,每个测试用例是以 test_ 开头的函数,通过执行 test/test.sh 可以查看和执行测试用例: ``` bash test/test.sh [-h|--help] ``` # 6. 案例 - [ola](projects/ola):一款为openEuler写的shell命令行工具 # 7. 结语 更多功能请自行解锁! 赞助方式: ![sponsor](./doc/sponsor/sponsor.png) 赞助名单:[名单](./doc/sponsor/sponsor.md)