diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dba6b64 --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +# 本地环境 +**/.DS_Store +**/.local/* +**/.venv/* +**/.conda/* +**/.taskfile/.env + +# 临时目录 +**/tmp/** +**/log/** +**/logs/** +**/temp/** +**/cache/** + +# 构建产物 +**/dist/** +**/build/** diff --git a/.taskfile/.env.template b/.taskfile/.env.template new file mode 100644 index 0000000..e69de29 diff --git a/.taskfile/cmd.yml b/.taskfile/cmd.yml new file mode 100644 index 0000000..53e05a4 --- /dev/null +++ b/.taskfile/cmd.yml @@ -0,0 +1,12 @@ +# https://taskfile.dev + +version: "3" + +vars: + GREETING: 用于本项目的常用命令编写 + +tasks: + default: + desc: 默认任务 + cmds: + - echo "${GREETING}" diff --git a/.taskfile/env.yml b/.taskfile/env.yml new file mode 100644 index 0000000..2cd63a9 --- /dev/null +++ b/.taskfile/env.yml @@ -0,0 +1,50 @@ +version: "3" + +vars: + NAMESPACE: "wangsendi" + DEVELOPER: "https://yuque.com/wangsendi" + TIME_NOW: + sh: TZ='Asia/Shanghai' date '+%Y-%m-%d %H:%M:%S %Z' + + PATH_REALPATH: + sh: pwd + PATH_DIRNAME: + sh: dirname "{{.PATH_REALPATH}}" + PATH_BASENAME: + sh: basename "{{.PATH_REALPATH}}" + PATH_PROJECT: + sh: echo "{{.PATH_BASENAME}}" | cut -d'-' -f2- + + GIT_TAG_LATEST: + sh: | + _latest_tag=$(git tag --sort=-v:refname | head -n 1 2>/dev/null) || true + if [[ "${_latest_tag}" == "" ]]; then + git tag v0.0.0 -m "init" 2>/dev/null || true + _latest_tag="v0.0.0"; + fi + echo ${_latest_tag} + GIT_COMMIT: + sh: git log -n 1 --format=%h 2>/dev/null || echo "0000" + GIT_SOURCE: + sh: grep -A1 '^\[remote' .git/config | grep 'url' | head -n 1 | sed 's|.git$||; s|:|/|; s|git@|https://|' | awk '{print $NF}' + GIT_PROJECT: + sh: echo "{{.GIT_SOURCE}}" | awk -F/ '{print $NF}' + +tasks: + env: + desc: "显示环境变量" + silent: true + cmds: + - | + echo "NAMESPACE: {{.NAMESPACE}}" + echo "DEVELOPER: {{.DEVELOPER}}" + echo "TIME_NOW: {{.TIME_NOW}}" + echo + echo "PATH_REALPATH: {{.PATH_REALPATH}}" + echo "PATH_DIRNAME: {{.PATH_DIRNAME}}" + echo "PATH_BASENAME: {{.PATH_BASENAME}}" + echo "PATH_PROJECT: {{.PATH_PROJECT}}" + echo + echo "GIT_TAG_LATEST: {{.GIT_TAG_LATEST}}" + echo "GIT_COMMIT: {{.GIT_COMMIT}}" + echo "GIT_SOURCE: {{.GIT_SOURCE}}" diff --git a/.taskfile/git.yml b/.taskfile/git.yml new file mode 100644 index 0000000..97b907e --- /dev/null +++ b/.taskfile/git.yml @@ -0,0 +1,76 @@ +version: "3" + +tasks: + clear: + desc: "清除历史提交记录" + silent: true + cmds: + - | + _branch_name_current=$(git branch --show-current 2>/dev/null || echo "") + _branch_name_backups="local/bak/${_branch_name_current}/$(date +'%Y/%m/%d/%H%M%S')" + if [[ "${_branch_name_current}" == "" ]]; then + echo "当前分支为空,跳过清除 git 缓存" + exit 0 + fi + git add -A && git commit -am "clear commit" || true + git rm -r --cached . + git branch -m ${_branch_name_backups} + git checkout --orphan ${_branch_name_current} + git add -A && git commit -am "clear commit" || true + git push -f origin ${_branch_name_current} + + reinit: + desc: "重新初始化 git" + cmds: + - | + _remote_url=$(git remote get-url origin | head -n1) + rm -rf .git + git init --initial-branch=main + touch README.md + git add . + git commit -m "first commit" + git tag -a {{.GIT_TAG_LATEST}} -m "init" + git remote add origin ${_remote_url} + git config push.autoSetupRemote true + - task: clear + + push: + desc: "推送代码" + cmds: + - | + git add . + git commit -m "- {{.CLI_ARGS}}" || true + git push origin main || true + + tag:next: + desc: "创建 tag" + vars: + GIT_TAG_NEXT: + sh: | + echo {{.GIT_TAG_LATEST}} | awk -F. '{print $1"."$2"."$3+1}' + cmds: + - echo '__version__ = "{{.GIT_TAG_NEXT}}"' > $(find . -maxdepth 3 -name version.py) || true + - task: push + - | + git tag -a {{.GIT_TAG_NEXT}} -m "- {{.CLI_ARGS}}" + git push origin {{.GIT_TAG_NEXT}} + + keys:gen: + desc: "设置并使用部署秘钥" + cmds: + - | + _path_keys=".taskfile/git/keys" + mkdir -p ${_path_keys} + if [[ ! -f "${_path_keys}/id_ed25519" ]]; then + ssh-keygen -t ed25519 -N '' -f ${_path_keys}/id_ed25519 -C "{{.GIT_PROJECT}}" + fi + chmod 600 ${_path_keys}/id_ed25519 + chmod 644 ${_path_keys}/id_ed25519.pub + + keys:set: + desc: "设置部署秘钥" + cmds: + - | + _path_keys=".taskfile/git/keys" + git config push.autoSetupRemote true + git config core.sshCommand "ssh -i ${_path_keys}/id_ed25519 -o StrictHostKeyChecking=no -F /dev/null" diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 0000000..32e168e --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,18 @@ +# https://taskfile.dev + +version: "3" +dotenv: [".env", ".taskfile/.env", "{{.HOME}}/.env", ".taskfile/.env.template"] + +includes: + env: + taskfile: .taskfile/env.yml + optional: true + flatten: true + + cmd: + taskfile: .taskfile/cmd.yml + optional: true + + git: + taskfile: .taskfile/git.yml + optional: true diff --git a/boot/auto.sh b/boot/auto.sh new file mode 100644 index 0000000..da0821d --- /dev/null +++ b/boot/auto.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +__main() { + : + +} +__main + +__help() { + cat >/dev/null <<-'AEOF' + + + +AEOF +} diff --git a/boot/conflict.sh b/boot/conflict.sh new file mode 100644 index 0000000..359c13b --- /dev/null +++ b/boot/conflict.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# shellcheck disable=SC1091 +# shellcheck disable=SC2046 + +if [[ -d "/host/proc/1/" ]]; then source /apps/gitrce/hook/singleton.sh "$0"; fi + +__main() { + : + +} + +# __main + +nsenter --mount=/host/proc/1/ns/mnt bash <<<"$(declare -f __main | sed "\$a __main")" + +__help() { + cat >/dev/null <<-'EOF' + +bash -c 'cd /apps/gitrce/ && git pull -f; bash /apps/gitrce/boot/conflict.sh' + +EOF +} diff --git a/boot/cron.sh b/boot/cron.sh new file mode 100644 index 0000000..1633bcb --- /dev/null +++ b/boot/cron.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +# shellcheck disable=SC1091 +# shellcheck disable=SC2009 +# Admin https://www.yuque.com/wangsendi + +__main() { + : # TODO + +} + +__main + +__help() { + cat >/dev/null <<-'AEOF' + +AEOF +} diff --git a/boot/env.sh b/boot/env.sh new file mode 100644 index 0000000..c2c9513 --- /dev/null +++ b/boot/env.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2034 +# 在每一次间隔时间后读取的变量, 作用容易入口文件 +# 用于在容器运行的状态下, 远程修改 git 拉取间隔时间 +# 注意,最小值不能大于最大值, 否则客户端 Git 死循环 + +INTERVAL_MIN=200 # 间隔最小值 +INTERVAL_MAX=300 # 间隔最大值 diff --git a/boot/install.sh b/boot/install.sh new file mode 100644 index 0000000..ac1cd5b --- /dev/null +++ b/boot/install.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2317,SC2086 +# Admin https://www.yuque.com/wangsendi + +__main() { + + { + # 判断是否有 docker 和 docker-compose + if ! command -v docker >/dev/null 2>&1; then + echo "docker not installed" + return 1 + fi + + if [[ "$(docker compose version 2>/dev/null | grep version -c)" != "1" ]]; then + echo "docker compose not installed" + return 1 + fi + } + + { + # 镜像准备 + _image1="1181.s.kuaicdn.cn:11818/ghcr.io/wangsendi/gitrce:bbiz-t2507281" + _image2="$(echo "$_image1" | awk -F '/' '{print $NF}')" + if [[ "$(docker images "$_image2" | wc -l)" != "2" ]]; then + docker pull $_image1 && docker tag "$_image1" "$_image2" + fi + } + + { + _gre_remote_repo="https://codeberg.org/umi-edge/250924-s-speedtest.git" + _container_name="250924-s-speedtest" + _apps_data="/data/umi/gitrce/$_container_name/master" + _compose_file="$_apps_data/boot/docker-compose.yaml" + mkdir -p ${_compose_file%/*} + cat >$_compose_file </dev/null <<-'AEOF' + +bash <(curl -fsSL https://codeberg.org/umi-edge/250924-s-speedtest/raw/branch/main/boot/install.sh) + +AEOF +} diff --git a/boot/start.sh b/boot/start.sh new file mode 100755 index 0000000..17864c5 --- /dev/null +++ b/boot/start.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +__main() { + : + ln -sf /host/run/docker.sock /var/run/docker.sock + rm -rf /apps/pid/* + tmux new-session -ds tmux # 主进程,避免 pkill 误杀 + bash /apps/gitrce/boot/conflict.sh >/dev/null 2>&1 + + bash /apps/gitrce/deploy/release/default/start.sh >/dev/null 2>&1 + +} + +__main + +_help() { + cat >/dev/null </dev/null <<-'AEOF' + +AEOF +} diff --git a/boot/update.sh b/boot/update.sh new file mode 100755 index 0000000..adbd9f6 --- /dev/null +++ b/boot/update.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# 每次 git 更行后的操作 + +__main() { + # service rsyslog restart + # service cron restart + service cron reload + pkill -f '/default/update.sh sleep' + +} + +__main diff --git a/boot/upgrade.sh b/boot/upgrade.sh new file mode 100644 index 0000000..af6bd37 --- /dev/null +++ b/boot/upgrade.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +__main() { + : + +} + +__help() { + cat >/dev/null <<-'AEOF' + + + AEOF +} + +__main diff --git a/cron.d/default b/cron.d/default new file mode 100644 index 0000000..c45a5cc --- /dev/null +++ b/cron.d/default @@ -0,0 +1,7 @@ +# shellcheck disable=SC2148 +# shellcheck disable=SC2035 +# shellcheck disable=SC2211 + +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +# * * * * * root date diff --git a/cron.d/deploy b/cron.d/deploy new file mode 100644 index 0000000..aafe4d8 --- /dev/null +++ b/cron.d/deploy @@ -0,0 +1,6 @@ +# shellcheck disable=SC2148 +# shellcheck disable=SC2035 +# shellcheck disable=SC2211 +# shellcheck disable=SC1091 + +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin diff --git a/deploy/release/default/start.sh b/deploy/release/default/start.sh new file mode 100644 index 0000000..852c11c --- /dev/null +++ b/deploy/release/default/start.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# shellcheck disable=SC1091 +# 设置版本启动安装路径并执行, 避免多版本存在时的一些特殊需求 + +if [[ "$1" == "sleep" ]]; then source /apps/script/hook/sleep.sh "$0" 3 15; fi + +__main() { + bash /apps/gitrce/deploy/release/default/init_cache_dir.sh + + _version="t20251123" + _workspace="/apps/gitrce/deploy/release/$_version" + _path="/apps/data/deploy/release/default/version.txt" + mkdir -p ${_path%/*} + echo "$_version" >$_path + bash "$_workspace/start.sh" +} + +__main + +__help() { + cat >/dev/null <<-'EOF' + + + EOF +} diff --git a/deploy/release/t20251123/start.sh b/deploy/release/t20251123/start.sh new file mode 100644 index 0000000..920918b --- /dev/null +++ b/deploy/release/t20251123/start.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# shellcheck source=/dev/null +# shellcheck disable=SC2046 +# shellcheck disable=SC2034 +# shellcheck disable=SC1091 +# shellcheck disable=SC2086 +# shellcheck disable=SC2206 +# shellcheck disable=SC2116 +# shellcheck disable=SC2154 +# shellcheck disable=SC2317 + +if [[ -d "/host/proc/1/" ]]; then source /apps/gitrce/hook/singleton.sh "$0"; fi +if [[ "$1" == "sleep" ]]; then source /apps/gitrce/hook/sleep.sh "$0" 1 30; fi + +__main() { + : + echo 'start.sh' >/apps/data/test.txt +} + +__main + +__help() { + cat >/dev/null <<-'EOF' + + + EOF +} diff --git a/hook/nsenter.sh b/hook/nsenter.sh new file mode 100644 index 0000000..0e2d3e2 --- /dev/null +++ b/hook/nsenter.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# 在要使用宿主机执行命令时引入该脚本 +# 示例 +# # shellcheck disable=SC1091 +# if [[ -d "/host/proc/1/" ]]; then source /apps/gitrce/hook/nsenter.sh "$0"; fi + +_script_path_this=$(realpath "$(ps -p $$ -o args= 2>/dev/null | awk '{print $2}')") +_latter="${_script_path_this#/apps/data}" +if [[ "$CONTAINER_NAME" == "" ]]; then CONTAINER_NAME=$(grep devices /dev/null | awk '{print $2}')") + + # 生成 PID 文件的路径 + _pid_name="$(echo "$_script_path_this" | sed 's:^/::; s/\//#/g; s/\.sh$/.pid/')" # 还原 echo "$result" | sed 's:^:/:' | sed 's/#/\//g; s/\.pid$/.sh/' + _pid_file="/apps/pid/$_pid_name" + + # 创建 PID 文件所在的目录 + mkdir -p "${_pid_file%/*}" + + # 从 PID 文件中读取存储的 PID + _pid_data=$(cat "$_pid_file" 2>/dev/null) + + # 根据存储的 PID 获取对应脚本的绝对路径 + _script_path_pid=$(realpath "$(ps -p "$_pid_data" -o args= 2>/dev/null | awk '{print $2}')" 2>/dev/null) + if [[ "$_script_path_this" != "$_script_path_pid" ]]; then + # 如果当前脚本路径与存储的脚本路径不同,则更新 PID 文件并继续执行 + echo "$$" >"$_pid_file" + else + # 如果相同,则说明已有实例在运行,输出相关信息并退出 + echo "脚本单例模式运行, 已存在运行实例,当前脚本已退出" + echo "_pid_file: $_pid_file" + echo "_pid_data: $_pid_data" + echo "_script_path_this: $_script_path_this" + echo "_script_path_pid : $_script_path_pid" + exit 0 + fi +} + +__singleton_pattern diff --git a/hook/sleep.sh b/hook/sleep.sh new file mode 100755 index 0000000..ff5622c --- /dev/null +++ b/hook/sleep.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# 需要在执行脚本延时一段时间, 可以调用该脚本... + +_t_sleep=$(shuf -i "$2"-"$3" -n 1) +echo "延时:$_t_sleep" +sleep "$_t_sleep" + +# 示例 +# if [[ "$1" == "sleep" ]]; then source /apps/gitrce/hook/sleep.sh "$0" 1 300; fi