Pārlūkot izejas kodu

移除冗余的 `prerun` 包并重构为 `lifecycle` 包

移除了 `cmd/prerun` 包,将其功能迁移到新的 `lifecycle` 包中,并使用 `sync.Once` 确保初始化逻辑只执行一次。同时重命名了 `lionv1`、`tigerv1` 和 `catv1` 为 `lion`、`tiger` 和 `cat`,并对相关代码进行了统一调整。
SongZihuan 12 stundas atpakaļ
vecāks
revīzija
49b70dad02

+ 13 - 13
.github/workflows/go-tag-release.yml

@@ -105,17 +105,17 @@ jobs:
         run: |
           mkdir -p ${{ github.workspace }}/output
 
-      - name: Build lionv1
+      - name: Build lion
         run: |
-          GOOS=linux GOARCH=amd64 go build -o "${{ github.workspace }}/output/linux_amd64_lionv1" -trimpath -ldflags='-s -w -extldflags "-static"' github.com/SongZihuan/BackendServerTemplate/src/cmd/lionv1
+          GOOS=linux GOARCH=amd64 go build -o "${{ github.workspace }}/output/linux_amd64_lion" -trimpath -ldflags='-s -w -extldflags "-static"' github.com/SongZihuan/BackendServerTemplate/src/cmd/lion
 
-      - name: Build tigerv1
+      - name: Build tiger
         run: |
-          GOOS=linux GOARCH=amd64 go build -o "${{ github.workspace }}/output/linux_amd64_tigerv1" -trimpath -ldflags='-s -w -extldflags "-static"' github.com/SongZihuan/BackendServerTemplate/src/cmd/tigerv1
+          GOOS=linux GOARCH=amd64 go build -o "${{ github.workspace }}/output/linux_amd64_tiger" -trimpath -ldflags='-s -w -extldflags "-static"' github.com/SongZihuan/BackendServerTemplate/src/cmd/tiger
 
-      - name: Build catv1
+      - name: Build cat
         run: |
-          GOOS=linux GOARCH=amd64 go build -o "${{ github.workspace }}/output/linux_amd64_catv1" -trimpath -ldflags='-s -w -extldflags "-static"' github.com/SongZihuan/BackendServerTemplate/src/cmd/catv1
+          GOOS=linux GOARCH=amd64 go build -o "${{ github.workspace }}/output/linux_amd64_cat" -trimpath -ldflags='-s -w -extldflags "-static"' github.com/SongZihuan/BackendServerTemplate/src/cmd/cat
 
       - name: Copy Release Info
         run: cp "${{ github.workspace }}/release_info.md.ignore" "${{ github.workspace }}/output/release_info.md"
@@ -170,23 +170,23 @@ jobs:
         run: |
           mkdir -p ${{ github.workspace }}\output
 
-      - name: Build lionv1
+      - name: Build lion
         run: |
           set GOOS=windows
           set GOARCH=amd64
-          go build -o "${{ github.workspace }}\output\windows_amd64_lionv1.exe" -trimpath -ldflags='-s -w -extldflags "-static"' github.com/SongZihuan/BackendServerTemplate/src/cmd/lionv1
+          go build -o "${{ github.workspace }}\output\windows_amd64_lion.exe" -trimpath -ldflags='-s -w -extldflags "-static"' github.com/SongZihuan/BackendServerTemplate/src/cmd/lion
 
-      - name: Build tigerv1
+      - name: Build tiger
         run:  |
           set GOOS=windows
           set GOARCH=amd64
-          go build -o "${{ github.workspace }}\output\windows_amd64_tigerv1.exe" -trimpath -ldflags='-s -w -extldflags "-static"' github.com/SongZihuan/BackendServerTemplate/src/cmd/tigerv1
+          go build -o "${{ github.workspace }}\output\windows_amd64_tiger.exe" -trimpath -ldflags='-s -w -extldflags "-static"' github.com/SongZihuan/BackendServerTemplate/src/cmd/tiger
 
-      - name: Build catv1
+      - name: Build cat
         run:  |
           set GOOS=windows
           set GOARCH=amd64
-          go build -o "${{ github.workspace }}\output\windows_amd64_catv1.exe" -trimpath -ldflags='-s -w -extldflags "-static"' github.com/SongZihuan/BackendServerTemplate/src/cmd/catv1
+          go build -o "${{ github.workspace }}\output\windows_amd64_cat.exe" -trimpath -ldflags='-s -w -extldflags "-static"' github.com/SongZihuan/BackendServerTemplate/src/cmd/cat
 
       - name: List build directory
         run: |
@@ -240,7 +240,7 @@ jobs:
         id: create_release
         uses: ncipollo/release-action@v1
         with:
-          artifacts: "${{ github.workspace }}/output/update.patch,${{ github.workspace }}/output/linux_amd64_lionv1,${{ github.workspace }}/output/linux_amd64_tigerv1,${{ github.workspace }}/output/linux_amd64_catv1,${{ github.workspace }}/output/windows_amd64_lionv1.exe,${{ github.workspace }}/output/windows_amd64_tigerv1.exe,${{ github.workspace }}/output/windows_amd64_catv1.exe"
+          artifacts: "${{ github.workspace }}/output/update.patch,${{ github.workspace }}/output/linux_amd64_lion,${{ github.workspace }}/output/linux_amd64_tiger,${{ github.workspace }}/output/linux_amd64_cat,${{ github.workspace }}/output/windows_amd64_lion.exe,${{ github.workspace }}/output/windows_amd64_tiger.exe,${{ github.workspace }}/output/windows_amd64_cat.exe"
           artifactErrorsFailBuild: true
           allowUpdates: false
           bodyFile: "${{ github.workspace }}/output/release_info.md"

+ 9 - 1
CHANGELOG.md

@@ -4,12 +4,20 @@
 
 其格式基于 [CHANGELOG 准则](./CHANGELOG_SPECIFICATION.md) 。
 
-## [未发布]
+## [0.14.0] - 2025/04/29 Asia/Shanghai
 
 ### 新增
 
 - 添加`utils`包的单元测试。
 
+### 修改
+
+- 原于 `cmd` 包下的 `prerun` 包移动到 `src` 下,重命名为 `lifecycle` 包,并使用 `sync.Once` 确保其只执行一次。
+
+### 重构
+
+- 重命名 `lionv1`、 `tigerv1` 和 `catv1` 为 `lion`、 `tiger` 和 `cat` 。
+
 ## [0.13.0] - 2025/04/28 Asia/Shanghai
 
 ### 新增

+ 42 - 42
README.md

@@ -35,11 +35,11 @@
 
 ## 入口
 
-入口文件在`src/cmd`下,目前分别有两个程序:`lionv1`和`tigerv1`。
+入口文件在`src/cmd`下,目前分别有三个程序:
 
-* `lionv1` 是使用控制单元的多服务演示程序。
-* `tigerv1` 是直接运行服务的单服务演示程序。
-* `catv1` 是服务安装演示程序。
+* `lion` 是使用控制单元的多服务演示程序。
+* `tiger` 是直接运行服务的单服务演示程序。
+* `cat` 是服务安装演示程序。
 
 入口程序不直接包含太多的实际代码,真正的`main`函数位于`src\mainfunc`下。
 程序的返回值代表程序的`Exit Code`。
@@ -68,22 +68,22 @@ $ go generate ./...
 
 ### 编译
 
-使用`go build`指令进行编译。如何包位于`github.com/SongZihuan/BackendServerTemplate/src/cmd/`下,例如`github.com/SongZihuan/BackendServerTemplate/src/cmd/lionv1`
+使用`go build`指令进行编译。如何包位于`github.com/SongZihuan/BackendServerTemplate/src/cmd/`下,例如`github.com/SongZihuan/BackendServerTemplate/src/cmd/lion`
 
-所以,编译命令如下(以`lionv1`为例):
+所以,编译命令如下(以`lion`为例):
 ```shell
-$ go build github.com/SongZihuan/BackendServerTemplate/src/cmd/lionv1
+$ go build github.com/SongZihuan/BackendServerTemplate/src/cmd/lion
 ```
 
 若用于开发环境,可以按如下方式编译:
 ```shell
-$ go build -o lionv1 -trimpath -ldflags='-s -w -extldflags "-static"' github.com/SongZihuan/BackendServerTemplate/src/cmd/lionv1
+$ go build -o lion -trimpath -ldflags='-s -w -extldflags "-static"' github.com/SongZihuan/BackendServerTemplate/src/cmd/lion
 ```
 
 其中:
- * `-o lionv1` 表示输出二进制文件的路径和名称
-   * Windows: `-o lionv1.exe`
-   * Linux/MacOS:`-o lionv1`
+ * `-o lion` 表示输出二进制文件的路径和名称
+   * Windows: `-o lion.exe`
+   * Linux/MacOS:`-o lion`
  * `-trimpath` 表示擦除二进制文件中关于源码目录的信息,可以压缩二进制文件体积和包含隐私。
  * `-ldflags='-s -w'` 是传递给链接器的参数。
    * `-s` 表示去掉符号和调试信息,可以减少二进制文件大小,同时增加反编译的难度。
@@ -97,41 +97,41 @@ $ go build -o lionv1 -trimpath -ldflags='-s -w -extldflags "-static"' github.com
 
 ### 运行参数
 
-接下来所列出来的指令,是`lionv1`、`tigerv1`和`catv1`所共有的子命令和标志。
+接下来所列出来的指令,是`lion`、`tiger`和`cat`所共有的子命令和标志。
 
-下列为公共子命令,以`lionv1`为例子:
+下列为公共子命令,以`lion`为例子:
 
-* `lionv1` 无子命令时,表示直接运行该程序。
-  * 注意:直接调用`catv1`运行代码是具有未知性的,应该使用`catv1 start`。
-* `lionv1 help` 查看`lionv1`的帮助文档。
-  * `lionv1 help <subcommand>` 查看子命令的帮助文档,例如:`lionv1 help version`。
-* `lionv1 version` 输出详细的版本号。
-* `lionv1 license` 输出授权协议(位于项目根目录的`LICENSE`)。
-* `lionv1 report` 输出程序反馈、报告方式文档。
-* `lionv1 check` 检查并输出配置文件的检查接管。
+* `lion` 无子命令时,表示直接运行该程序。
+  * 注意:直接调用`cat`运行代码是具有未知性的,应该使用`cat start`。
+* `lion help` 查看`lion`的帮助文档。
+  * `lion help <subcommand>` 查看子命令的帮助文档,例如:`lion help version`。
+* `lion version` 输出详细的版本号。
+* `lion license` 输出授权协议(位于项目根目录的`LICENSE`)。
+* `lion report` 输出程序反馈、报告方式文档。
+* `lion check` 检查并输出配置文件的检查接管。
 * `completion` 与`shell`和`powershell`实现自动补全有关。
 
-下列为公共标志,以`lionv1`为例子:
+下列为公共标志,以`lion`为例子:
 
-* `lionv1 -n xxx`,`lionv1 --name xxx` 设置程序运行的名称,需要一个参数 **(全局参数,任何子命令均具有此参数)**。
-* `lionv1 -h`,`lionv1 --help` 查看帮助文档 **(全局参数,任何子命令均具有此参数)**。
-* `lionv1 -c xxx`,`lionv1 --config xxx` 配置文件位置(可提供一个字符串参数作为路径指向配置文件,默认值为:`config.yaml`)。
-* `lionv1 -o xxx`、`lionv1 --output-config xxx` 反向输出配置文件(默认不输出,若提供一个路径则会输出到该路径所指处)。未知配置项不会输出,未设定配置项则以默认值(若有)输出。**前提:配置文件被正确导入和识别。**
+* `lion -n xxx`,`lion --name xxx` 设置程序运行的名称,需要一个参数 **(全局参数,任何子命令均具有此参数)**。
+* `lion -h`,`lion --help` 查看帮助文档 **(全局参数,任何子命令均具有此参数)**。
+* `lion -c xxx`,`lion --config xxx` 配置文件位置(可提供一个字符串参数作为路径指向配置文件,默认值为:`config.yaml`)。
+* `lion -o xxx`、`lion --output-config xxx` 反向输出配置文件(默认不输出,若提供一个路径则会输出到该路径所指处)。未知配置项不会输出,未设定配置项则以默认值(若有)输出。**前提:配置文件被正确导入和识别。**
 
-以下标志为`tigerv1`和`lionv1`共有,`catv1`没有的:
+以下标志为`tiger`和`lion`共有,`cat`没有的:
 
-* `lionv1 --auto-reload` 自动重载(监测配置文件,若其变化则重启服务系统)。该功能应该仅仅用在开发时。
+* `lion --auto-reload` 自动重载(监测配置文件,若其变化则重启服务系统)。该功能应该仅仅用在开发时。
 
 以下为`check`子命令的标志:
 
-* `lionv1 check -c xxx`,`lionv1 check --config xxx` 配置文件位置(可提供一个字符串参数作为路径指向配置文件,默认值为:`config.yaml`)。
-* `lionv1 check -o xxx`、`lionv1 check --output-config xxx` 反向输出配置文件(默认不输出,若提供一个路径则会输出到该路径所指处)。未知配置项不会输出,未设定配置项则以默认值(若有)输出。**前提:配置文件被正确导入和识别。**
+* `lion check -c xxx`,`lion check --config xxx` 配置文件位置(可提供一个字符串参数作为路径指向配置文件,默认值为:`config.yaml`)。
+* `lion check -o xxx`、`lion check --output-config xxx` 反向输出配置文件(默认不输出,若提供一个路径则会输出到该路径所指处)。未知配置项不会输出,未设定配置项则以默认值(若有)输出。**前提:配置文件被正确导入和识别。**
 
 以下为`version`子命令的标志:
 
-* `lionv1 version -s` `lionv1 version --short` 仅输出短的版本号。
+* `lion version -s` `lion version --short` 仅输出短的版本号。
 
-特定于`catv1`的子命令(如:`install`、`start`等)可参考:[后端服务](#后台服务)
+特定于`cat`的子命令(如:`install`、`start`等)可参考:[后端服务](#后台服务)
 
 ### 运行时配置文件
 
@@ -217,7 +217,7 @@ server:  # 系统执行服务所需要的参数
 
 ## 后台服务
 
-虽然`lionv1`和`tigerv1`也可以作为后台服务,但是我使用了`catv1`进行了更高层次的抽象,使得在`Windows`和`Linux`上可以安装服务程序。
+虽然`lion`和`tiger`也可以作为后台服务,但是我使用了`cat`进行了更高层次的抽象,使得在`Windows`和`Linux`上可以安装服务程序。
 
 后台服务采用Go的第三方库`github.com/kardianos/service`实现,主要目的是实现`Windows`上的服务注册。
 但是理论上来说,`MacOS`和`Linux`(`systemd`)也能使用。
@@ -234,7 +234,7 @@ describe: 一个简单的Go测试服务  # 服务的秒数
 
 # 参数来源
 #  no      无运行时参数(默认行为)
-#  install 在安装时指定参数,例如:catv1 install a b c,其中 a b c 作为参数
+#  install 在安装时指定参数,例如:cat install a b c,其中 a b c 作为参数
 #  config  在本配置文件中的 argument-list 列表指定运行时参数
 argument-from: install
 # argument-from 为 config 时启用
@@ -247,7 +247,7 @@ argument-list: []
 env-from: no
 # env-from 为 install 时启用
 env-get-list: 
-  - a  # 安装程序(catv1 install)运行时,获取环境变量 a,并作为服务运行时的环境变量(例如安装时 a 的值为 b ,服务运行时也将得到环境变量 a 的值为 b)
+  - a  # 安装程序(cat install)运行时,获取环境变量 a,并作为服务运行时的环境变量(例如安装时 a 的值为 b ,服务运行时也将得到环境变量 a 的值为 b)
   - c
 # env-from 为 config 时启用
 env-set-list: 
@@ -261,29 +261,29 @@ env-set-list:
 ### 安装
 
 ```shell
-$ catv1 install <命令行参数列表>
+$ cat install <命令行参数列表>
 ```
 
 使用此命令可以在`Windows`中或`Linux`中注册一个服务.
 
-注意:安装后可执行程序`catv1`仍需保留在原来位置,不可移动。
+注意:安装后可执行程序`cat`仍需保留在原来位置,不可移动。
 
 ### 卸载
 
 ```shell
-$ catv1 uninstall
+$ cat uninstall
 ```
 
 或者
 
 ```shell
-$ catv1 remove
+$ cat remove
 ```
 
 ### 启动
 
 ```shell
-$ catv1 start
+$ cat start
 ```
 
 启动不需要指定命令行参数,命令行参数在`install`时即确定。
@@ -291,13 +291,13 @@ $ catv1 start
 ### 停止
 
 ```shell
-$ catv1 stop
+$ cat stop
 ```
 
 ### 重启
 
 ```shell
-$ catv1 restart
+$ cat restart
 ```
 
 ## 日后升级计划

+ 15 - 15
src/cmd/catv1/main.go → src/cmd/cat/main.go

@@ -4,24 +4,24 @@
 
 package main
 
-// 必须明确导入 prerun 包 (虽然下面的import确实导入了 prerun 包,但此处重复写一次表示冗余,以免在某些情况下本包不适用 prerun 后,下方的导入被自动删除)
 import (
-	_ "github.com/SongZihuan/BackendServerTemplate/src/cmd/prerun"
-)
-
-import (
-	"github.com/SongZihuan/BackendServerTemplate/src/cmd/prerun"
 	"github.com/SongZihuan/BackendServerTemplate/src/cmdparser/check"
 	"github.com/SongZihuan/BackendServerTemplate/src/cmdparser/license"
 	"github.com/SongZihuan/BackendServerTemplate/src/cmdparser/report"
 	"github.com/SongZihuan/BackendServerTemplate/src/cmdparser/version"
 	"github.com/SongZihuan/BackendServerTemplate/src/global"
-	catv1 "github.com/SongZihuan/BackendServerTemplate/src/mainfunc/cat/v1"
+	"github.com/SongZihuan/BackendServerTemplate/src/lifecycle"
+	"github.com/SongZihuan/BackendServerTemplate/src/mainfunc/cat"
 	"github.com/SongZihuan/BackendServerTemplate/src/utils/cleanstringutils"
 	"github.com/SongZihuan/BackendServerTemplate/src/utils/exitutils"
 	"github.com/spf13/cobra"
 )
 
+// 必须明确导入 lifecycle 包 (虽然下面的import确实导入了 prerun 包,但此处重复写一次表示冗余,以免在某些情况下本包不适用 prerun 后,下方的导入被自动删除)
+import (
+	_ "github.com/SongZihuan/BackendServerTemplate/src/lifecycle"
+)
+
 const (
 	args1Install    = "install"
 	args1Uninstall1 = "uninstall"
@@ -39,8 +39,8 @@ func main() {
 }
 
 func command() exitutils.ExitCode {
-	err := prerun.PreRun()
-	defer prerun.PostRun() // 此处defer放在err之前(因为RPreRun包含启动东西太多,虽然返回err,但不代表全部操作没成功,因此defer设置在这个位置,确保清理函数被调用。清理函数可以判断当前是否需要清理)
+	err := lifecycle.PreRun()
+	defer lifecycle.PostRun() // 此处defer放在err之前(因为RPreRun包含启动东西太多,虽然返回err,但不代表全部操作没成功,因此defer设置在这个位置,确保清理函数被调用。清理函数可以判断当前是否需要清理)
 	if err != nil {
 		return exitutils.ErrorToExit(err)
 	}
@@ -67,7 +67,7 @@ func command() exitutils.ExitCode {
 		RunE: func(cmd *cobra.Command, args []string) error {
 			cmd.SilenceUsage = true
 			cmd.SilenceErrors = true
-			return catv1.MainV1(cmd, args, inputConfigFilePath)
+			return cat.Main(cmd, args, inputConfigFilePath)
 		},
 		PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
 			cmd.SilenceUsage = false
@@ -92,7 +92,7 @@ func command() exitutils.ExitCode {
 		RunE: func(cmd *cobra.Command, args []string) error {
 			cmd.SilenceUsage = true
 			cmd.SilenceErrors = true
-			return catv1.MainV1Install(cmd, args)
+			return cat.MainInstall(cmd, args)
 		},
 		PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
 			cmd.SilenceUsage = false
@@ -117,7 +117,7 @@ func command() exitutils.ExitCode {
 		RunE: func(cmd *cobra.Command, args []string) error {
 			cmd.SilenceUsage = true
 			cmd.SilenceErrors = true
-			return catv1.MainV1UnInstall(cmd, args)
+			return cat.MainUnInstall(cmd, args)
 		},
 		PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
 			cmd.SilenceUsage = false
@@ -140,7 +140,7 @@ func command() exitutils.ExitCode {
 		RunE: func(cmd *cobra.Command, args []string) error {
 			cmd.SilenceUsage = true
 			cmd.SilenceErrors = true
-			return catv1.MainV1Start(cmd, args)
+			return cat.MainStart(cmd, args)
 		},
 		PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
 			cmd.SilenceUsage = false
@@ -163,7 +163,7 @@ func command() exitutils.ExitCode {
 		RunE: func(cmd *cobra.Command, args []string) error {
 			cmd.SilenceUsage = true
 			cmd.SilenceErrors = true
-			return catv1.MainV1Stop(cmd, args)
+			return cat.MainStop(cmd, args)
 		},
 		PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
 			cmd.SilenceUsage = false
@@ -186,7 +186,7 @@ func command() exitutils.ExitCode {
 		RunE: func(cmd *cobra.Command, args []string) error {
 			cmd.SilenceUsage = true
 			cmd.SilenceErrors = true
-			return catv1.MainV1Restart(cmd, args)
+			return cat.MainRestart(cmd, args)
 		},
 		PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
 			cmd.SilenceUsage = false

+ 15 - 15
src/cmd/lionv1/main.go → src/cmd/lion/main.go

@@ -4,27 +4,27 @@
 
 package main
 
-// 必须明确导入 prerun 包 (虽然下面的import确实导入了 prerun 包,但此处重复写一次表示冗余,以免在某些情况下本包不适用 prerun 后,下方的导入被自动删除)
-import (
-	_ "github.com/SongZihuan/BackendServerTemplate/src/cmd/prerun"
-)
-
 import (
 	"fmt"
-	"github.com/SongZihuan/BackendServerTemplate/src/cmd/prerun"
 	"github.com/SongZihuan/BackendServerTemplate/src/cmdparser/check"
 	"github.com/SongZihuan/BackendServerTemplate/src/cmdparser/license"
 	"github.com/SongZihuan/BackendServerTemplate/src/cmdparser/report"
 	"github.com/SongZihuan/BackendServerTemplate/src/cmdparser/version"
 	"github.com/SongZihuan/BackendServerTemplate/src/global"
-	lionv1 "github.com/SongZihuan/BackendServerTemplate/src/mainfunc/lion/v1"
-	restartv1 "github.com/SongZihuan/BackendServerTemplate/src/mainfunc/restart/v1"
-	"github.com/SongZihuan/BackendServerTemplate/src/restart"
+	"github.com/SongZihuan/BackendServerTemplate/src/lifecycle"
+	"github.com/SongZihuan/BackendServerTemplate/src/mainfunc/lion"
+	"github.com/SongZihuan/BackendServerTemplate/src/mainfunc/restart"
+	restartinfo "github.com/SongZihuan/BackendServerTemplate/src/restart"
 	"github.com/SongZihuan/BackendServerTemplate/src/utils/cleanstringutils"
 	"github.com/SongZihuan/BackendServerTemplate/src/utils/exitutils"
 	"github.com/spf13/cobra"
 )
 
+// 必须明确导入 lifecycle 包 (虽然下面的import确实导入了 prerun 包,但此处重复写一次表示冗余,以免在某些情况下本包不适用 prerun 后,下方的导入被自动删除)
+import (
+	_ "github.com/SongZihuan/BackendServerTemplate/src/lifecycle"
+)
+
 var inputConfigFilePath string = "config.yaml"
 var name string = global.Name
 var reload bool = false
@@ -35,8 +35,8 @@ func main() {
 }
 
 func command() exitutils.ExitCode {
-	err := prerun.PreRun()
-	defer prerun.PostRun() // 此处defer放在err之前(因为RPreRun包含启动东西太多,虽然返回err,但不代表全部操作没成功,因此defer设置在这个位置,确保清理函数被调用。清理函数可以判断当前是否需要清理)
+	err := lifecycle.PreRun()
+	defer lifecycle.PostRun() // 此处defer放在err之前(因为RPreRun包含启动东西太多,虽然返回err,但不代表全部操作没成功,因此defer设置在这个位置,确保清理函数被调用。清理函数可以判断当前是否需要清理)
 	if err != nil {
 		return exitutils.ErrorToExit(err)
 	}
@@ -64,7 +64,7 @@ func command() exitutils.ExitCode {
 			cmd.SilenceUsage = false
 			cmd.SilenceErrors = false
 
-			if reload && cmd.Flags().Changed(restart.RestartFlag) {
+			if reload && cmd.Flags().Changed(restartinfo.RestartFlag) {
 				if ppid == 0 {
 					return fmt.Errorf("`restart` cannot be specified as 0")
 				}
@@ -78,10 +78,10 @@ func command() exitutils.ExitCode {
 			cmd.SilenceErrors = true
 
 			if reload {
-				return restartv1.MainV1(cmd, args, inputConfigFilePath)
+				return restart.Main(cmd, args, inputConfigFilePath)
 			}
 
-			return lionv1.MainV1(cmd, args, inputConfigFilePath, ppid)
+			return lion.Main(cmd, args, inputConfigFilePath, ppid)
 		},
 		PostRunE: func(cmd *cobra.Command, args []string) error {
 			cmd.SilenceUsage = false
@@ -100,7 +100,7 @@ func command() exitutils.ExitCode {
 	cmd.PersistentFlags().StringVarP(&name, "name", "n", global.Name, "the program display name")
 
 	cmd.Flags().BoolVar(&reload, "auto-reload", false, "auto reload config file when the file changed")
-	cmd.Flags().IntVar(&ppid, restart.RestartFlag, 0, "restart mode, note: DO NOT SET THIS FLAG unless you know your purpose clearly.")
+	cmd.Flags().IntVar(&ppid, restartinfo.RestartFlag, 0, "restart mode, note: DO NOT SET THIS FLAG unless you know your purpose clearly.")
 
 	cmd.Flags().StringVarP(&inputConfigFilePath, "config", "c", inputConfigFilePath, "the file path of the configuration file")
 

+ 15 - 15
src/cmd/tigerv1/main.go → src/cmd/tiger/main.go

@@ -4,27 +4,27 @@
 
 package main
 
-// 必须明确导入 prerun 包 (虽然下面的import确实导入了 prerun 包,但此处重复写一次表示冗余,以免在某些情况下本包不适用 prerun 后,下方的导入被自动删除)
-import (
-	_ "github.com/SongZihuan/BackendServerTemplate/src/cmd/prerun"
-)
-
 import (
 	"fmt"
-	"github.com/SongZihuan/BackendServerTemplate/src/cmd/prerun"
 	"github.com/SongZihuan/BackendServerTemplate/src/cmdparser/check"
 	"github.com/SongZihuan/BackendServerTemplate/src/cmdparser/license"
 	"github.com/SongZihuan/BackendServerTemplate/src/cmdparser/report"
 	"github.com/SongZihuan/BackendServerTemplate/src/cmdparser/version"
 	"github.com/SongZihuan/BackendServerTemplate/src/global"
-	restartv1 "github.com/SongZihuan/BackendServerTemplate/src/mainfunc/restart/v1"
-	tigerv1 "github.com/SongZihuan/BackendServerTemplate/src/mainfunc/tiger/v1"
-	"github.com/SongZihuan/BackendServerTemplate/src/restart"
+	"github.com/SongZihuan/BackendServerTemplate/src/lifecycle"
+	"github.com/SongZihuan/BackendServerTemplate/src/mainfunc/restart"
+	"github.com/SongZihuan/BackendServerTemplate/src/mainfunc/tiger"
+	restartinfo "github.com/SongZihuan/BackendServerTemplate/src/restart"
 	"github.com/SongZihuan/BackendServerTemplate/src/utils/cleanstringutils"
 	"github.com/SongZihuan/BackendServerTemplate/src/utils/exitutils"
 	"github.com/spf13/cobra"
 )
 
+// 必须明确导入 lifecycle 包 (虽然下面的import确实导入了 prerun 包,但此处重复写一次表示冗余,以免在某些情况下本包不适用 prerun 后,下方的导入被自动删除)
+import (
+	_ "github.com/SongZihuan/BackendServerTemplate/src/lifecycle"
+)
+
 var inputConfigFilePath string = "config.yaml"
 var name string = global.Name
 var reload bool = false
@@ -35,8 +35,8 @@ func main() {
 }
 
 func command() exitutils.ExitCode {
-	err := prerun.PreRun()
-	defer prerun.PostRun() // 此处defer放在err之前(因为RPreRun包含启动东西太多,虽然返回err,但不代表全部操作没成功,因此defer设置在这个位置,确保清理函数被调用。清理函数可以判断当前是否需要清理)
+	err := lifecycle.PreRun()
+	defer lifecycle.PostRun() // 此处defer放在err之前(因为RPreRun包含启动东西太多,虽然返回err,但不代表全部操作没成功,因此defer设置在这个位置,确保清理函数被调用。清理函数可以判断当前是否需要清理)
 	if err != nil {
 		return exitutils.ErrorToExit(err)
 	}
@@ -64,7 +64,7 @@ func command() exitutils.ExitCode {
 			cmd.SilenceUsage = false
 			cmd.SilenceErrors = false
 
-			if reload && cmd.Flags().Changed(restart.RestartFlag) {
+			if reload && cmd.Flags().Changed(restartinfo.RestartFlag) {
 				if ppid == 0 {
 					return fmt.Errorf("`restart` cannot be specified as 0")
 				}
@@ -78,10 +78,10 @@ func command() exitutils.ExitCode {
 			cmd.SilenceErrors = true
 
 			if reload {
-				return restartv1.MainV1(cmd, args, inputConfigFilePath)
+				return restart.Main(cmd, args, inputConfigFilePath)
 			}
 
-			return tigerv1.MainV1(cmd, args, inputConfigFilePath, ppid)
+			return tiger.Main(cmd, args, inputConfigFilePath, ppid)
 		},
 		PostRunE: func(cmd *cobra.Command, args []string) error {
 			cmd.SilenceUsage = false
@@ -100,7 +100,7 @@ func command() exitutils.ExitCode {
 	cmd.PersistentFlags().StringVarP(&name, "name", "n", global.Name, "the program display name")
 
 	cmd.Flags().BoolVar(&reload, "auto-reload", false, "auto reload config file when the file changed")
-	cmd.Flags().IntVar(&ppid, restart.RestartFlag, 0, "restart mode, note: DO NOT SET THIS FLAG unless you know your purpose clearly.")
+	cmd.Flags().IntVar(&ppid, restartinfo.RestartFlag, 0, "restart mode, note: DO NOT SET THIS FLAG unless you know your purpose clearly.")
 
 	cmd.Flags().StringVarP(&inputConfigFilePath, "config", "c", inputConfigFilePath, "the file path of the configuration file")
 

+ 2 - 9
src/cmdparser/check/cmd.go

@@ -5,8 +5,7 @@
 package check
 
 import (
-	"github.com/SongZihuan/BackendServerTemplate/src/cmd/prerun"
-	checkv1 "github.com/SongZihuan/BackendServerTemplate/src/mainfunc/check/v1"
+	"github.com/SongZihuan/BackendServerTemplate/src/mainfunc/check"
 	"github.com/spf13/cobra"
 )
 
@@ -20,13 +19,7 @@ var CMD = &cobra.Command{
 	RunE: func(cmd *cobra.Command, args []string) error {
 		cmd.SilenceUsage = true
 		cmd.SilenceErrors = true
-
-		err := prerun.PreRun()
-		if err != nil {
-			return err
-		}
-
-		return checkv1.MainV1(cmd, args, inputConfigFilePath, outputConfigFilePath)
+		return check.Main(cmd, args, inputConfigFilePath, outputConfigFilePath)
 	},
 }
 

+ 10 - 0
src/lifecycle/global.go

@@ -0,0 +1,10 @@
+// Copyright 2025 BackendServerTemplate Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package lifecycle
+
+// 必须明确导入 global 包 (虽然下面的import确实导入了 global 包,但此处重复写一次表示冗余,以免在某些情况下本包不适用 global 后,下方的导入被自动删除)
+import (
+	_ "github.com/SongZihuan/BackendServerTemplate/src/global"
+)

+ 25 - 0
src/lifecycle/postrun.go

@@ -0,0 +1,25 @@
+// Copyright 2025 BackendServerTemplate Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package lifecycle
+
+import (
+	"github.com/SongZihuan/BackendServerTemplate/src/logger"
+	"github.com/SongZihuan/BackendServerTemplate/src/utils/stdutils"
+	"sync"
+)
+
+var _postRunOnce sync.Once
+
+func PostRun() {
+	_postRunOnce.Do(func() {
+		postRun()
+	})
+}
+
+func postRun() {
+	logger.CloseLogger()
+	logger.Recover()
+	stdutils.CloseNullFile()
+}

+ 14 - 14
src/cmd/prerun/main.go → src/lifecycle/prerun.go

@@ -2,23 +2,29 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package prerun
-
-// 必须明确导入 global 包 (虽然下面的import确实导入了 global 包,但此处重复写一次表示冗余,以免在某些情况下本包不适用 global 后,下方的导入被自动删除)
-import (
-	_ "github.com/SongZihuan/BackendServerTemplate/src/global"
-	"github.com/SongZihuan/BackendServerTemplate/src/utils/envutils"
-	"github.com/SongZihuan/BackendServerTemplate/src/utils/stdutils"
-)
+package lifecycle
 
 import (
 	"github.com/SongZihuan/BackendServerTemplate/src/global"
 	"github.com/SongZihuan/BackendServerTemplate/src/logger"
 	"github.com/SongZihuan/BackendServerTemplate/src/utils/consoleutils"
+	"github.com/SongZihuan/BackendServerTemplate/src/utils/envutils"
 	"github.com/SongZihuan/BackendServerTemplate/src/utils/exitutils"
+	"github.com/SongZihuan/BackendServerTemplate/src/utils/stdutils"
+	"sync"
 )
 
+var _preRunOnce sync.Once
+var _preError error
+
 func PreRun() (exitCode error) {
+	_preRunOnce.Do(func() {
+		_preError = preRun()
+	})
+	return _preError
+}
+
+func preRun() (exitCode error) {
 	var err error
 
 	quiteMode := envutils.GetEnv(global.EnvPrefix, "QUITE")
@@ -55,9 +61,3 @@ func PreRun() (exitCode error) {
 
 	return nil
 }
-
-func PostRun() {
-	logger.CloseLogger()
-	logger.Recover()
-	stdutils.CloseNullFile()
-}

+ 1 - 1
src/mainfunc/cat/v1/config.go → src/mainfunc/cat/config.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package v1
+package cat
 
 import (
 	"fmt"

+ 1 - 1
src/mainfunc/cat/v1/config_test.go → src/mainfunc/cat/config_test.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package v1
+package cat
 
 import (
 	"fmt"

+ 7 - 16
src/mainfunc/cat/v1/main.go → src/mainfunc/cat/main.go

@@ -2,26 +2,17 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package v1
+package cat
 
 import (
 	"github.com/SongZihuan/BackendServerTemplate/src/utils/exitutils"
 	"github.com/kardianos/service"
 	"github.com/spf13/cobra"
-	"os"
 )
 
-func MainV1(cmd *cobra.Command, args []string, inputConfigFilePath string) (exitCode error) {
+func Main(cmd *cobra.Command, args []string, inputConfigFilePath string) (exitCode error) {
 	var err error
 
-	logfile, err := os.OpenFile("C:\\Users\\songz\\Code\\GoProject\\BackendServerTemplate\\test_self\\tmpcat.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
-	if err != nil {
-		panic(err)
-	}
-	defer func() {
-		_ = logfile.Close()
-	}()
-
 	err = initServiceConfig()
 	if err != nil {
 		return exitutils.InitFailed("service config", err.Error())
@@ -46,7 +37,7 @@ func MainV1(cmd *cobra.Command, args []string, inputConfigFilePath string) (exit
 	return prg.ExitCode()
 }
 
-func MainV1Install(cmd *cobra.Command, args []string) (exitCode error) {
+func MainInstall(cmd *cobra.Command, args []string) (exitCode error) {
 	var err error
 
 	err = initInstallServiceConfig(args)
@@ -78,7 +69,7 @@ func MainV1Install(cmd *cobra.Command, args []string) (exitCode error) {
 	return exitutils.SuccessExit("Service Install Success")
 }
 
-func MainV1UnInstall(cmd *cobra.Command, args []string) (exitCode error) {
+func MainUnInstall(cmd *cobra.Command, args []string) (exitCode error) {
 	var err error
 
 	err = initServiceConfig()
@@ -110,7 +101,7 @@ func MainV1UnInstall(cmd *cobra.Command, args []string) (exitCode error) {
 	return exitutils.SuccessExit("Service Remove Success")
 }
 
-func MainV1Start(cmd *cobra.Command, args []string) (exitCode error) {
+func MainStart(cmd *cobra.Command, args []string) (exitCode error) {
 	var err error
 
 	err = initServiceConfig()
@@ -142,7 +133,7 @@ func MainV1Start(cmd *cobra.Command, args []string) (exitCode error) {
 	return exitutils.SuccessExit("Service Start Success")
 }
 
-func MainV1Stop(cmd *cobra.Command, args []string) (exitCode error) {
+func MainStop(cmd *cobra.Command, args []string) (exitCode error) {
 	var err error
 
 	err = initServiceConfig()
@@ -174,7 +165,7 @@ func MainV1Stop(cmd *cobra.Command, args []string) (exitCode error) {
 	return exitutils.SuccessExit("Service Stop Success")
 }
 
-func MainV1Restart(cmd *cobra.Command, args []string) (exitCode error) {
+func MainRestart(cmd *cobra.Command, args []string) (exitCode error) {
 	var err error
 
 	err = initServiceConfig()

+ 1 - 1
src/mainfunc/cat/v1/service.go → src/mainfunc/cat/service.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package v1
+package cat
 
 import (
 	"errors"

+ 2 - 2
src/mainfunc/check/v1/main.go → src/mainfunc/check/main.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package v1
+package check
 
 import (
 	"fmt"
@@ -13,7 +13,7 @@ import (
 	"github.com/spf13/cobra"
 )
 
-func MainV1(cmd *cobra.Command, args []string, inputConfigFilePath string, outputConfigFilePath string) (exitCode error) {
+func Main(cmd *cobra.Command, args []string, inputConfigFilePath string, outputConfigFilePath string) (exitCode error) {
 	var err error
 
 	err = config.InitConfig(&config.ConfigOption{

+ 2 - 2
src/mainfunc/lion/v1/main.go → src/mainfunc/lion/main.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package v1
+package lion
 
 import (
 	"errors"
@@ -20,7 +20,7 @@ import (
 	"github.com/spf13/cobra"
 )
 
-func MainV1(cmd *cobra.Command, args []string, inputConfigFilePath string, ppid int) (exitCode error) {
+func Main(cmd *cobra.Command, args []string, inputConfigFilePath string, ppid int) (exitCode error) {
 	var err error
 
 	err = config.InitConfig(&config.ConfigOption{

+ 2 - 2
src/mainfunc/restart/v1/main.go → src/mainfunc/restart/main.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package v1
+package restart
 
 import (
 	"github.com/SongZihuan/BackendServerTemplate/src/config"
@@ -14,7 +14,7 @@ import (
 	"github.com/spf13/cobra"
 )
 
-func MainV1(cmd *cobra.Command, args []string, inputConfigFilePath string) (exitCode error) {
+func Main(cmd *cobra.Command, args []string, inputConfigFilePath string) (exitCode error) {
 	var err error
 
 	err = config.InitConfig(&config.ConfigOption{

+ 2 - 2
src/mainfunc/tiger/v1/main.go → src/mainfunc/tiger/main.go

@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package v1
+package tiger
 
 import (
 	"errors"
@@ -18,7 +18,7 @@ import (
 	"github.com/spf13/cobra"
 )
 
-func MainV1(cmd *cobra.Command, args []string, inputConfigFilePath string, ppid int) (exitCode error) {
+func Main(cmd *cobra.Command, args []string, inputConfigFilePath string, ppid int) (exitCode error) {
 	var err error
 
 	err = config.InitConfig(&config.ConfigOption{

+ 9 - 1
third-party/github.com.SongZihuan.BackendServerTemplate/CHANGELOG.md

@@ -4,12 +4,20 @@
 
 其格式基于 [CHANGELOG 准则](./CHANGELOG_SPECIFICATION.md) 。
 
-## [未发布]
+## [0.14.0] - 2025/04/29 Asia/Shanghai
 
 ### 新增
 
 - 添加`utils`包的单元测试。
 
+### 修改
+
+- 原于 `cmd` 包下的 `prerun` 包移动到 `src` 下,重命名为 `lifecycle` 包,并使用 `sync.Once` 确保其只执行一次。
+
+### 重构
+
+- 重命名 `lionv1`、 `tigerv1` 和 `catv1` 为 `lion`、 `tiger` 和 `cat` 。
+
 ## [0.13.0] - 2025/04/28 Asia/Shanghai
 
 ### 新增