Skip to content

Commit b4d00b8

Browse files
committed
Fix GARSS startup on Windows
1 parent dba3f68 commit b4d00b8

9 files changed

Lines changed: 264 additions & 26 deletions

File tree

.gitattributes

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
*.sh text eol=lf
2+
*.command text eol=lf
3+
*.bat text eol=crlf

GARSS-LINUX.sh

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,42 @@
11
#!/bin/sh
22

33
ROOT_DIR=$(CDPATH= cd "$(dirname "$0")" && pwd)
4-
cd "$ROOT_DIR/garss-studio" || exit 1
4+
PROJECT_DIR="$ROOT_DIR/garss-studio"
5+
COMPOSE_FILE="docker-compose.dev.yml"
6+
7+
cd "$PROJECT_DIR" || exit 1
8+
9+
ensure_docker() {
10+
if ! docker --version >/dev/null 2>&1; then
11+
echo "请先安装并启动 Docker。"
12+
return 1
13+
fi
14+
}
15+
16+
ensure_env() {
17+
if [ ! -f ".env" ]; then
18+
cp ".env.example" ".env"
19+
echo "已从 .env.example 创建 .env"
20+
fi
21+
}
22+
23+
entry_url() {
24+
access_code=$(grep -E '^ACCESS_CODE=' .env 2>/dev/null | head -n 1 | cut -d= -f2-)
25+
access_code=${access_code%\"}
26+
access_code=${access_code#\"}
27+
access_code=${access_code:-banana}
28+
echo "http://127.0.0.1:25173/reader?pw=$access_code"
29+
}
30+
31+
open_entry() {
32+
url="$1"
33+
echo "入口: $url"
34+
if command -v xdg-open >/dev/null 2>&1; then
35+
xdg-open "$url" >/dev/null 2>&1 &
36+
else
37+
echo "无法自动打开浏览器,请手动访问: $url"
38+
fi
39+
}
540

641
run_action() {
742
action="$1"
@@ -10,25 +45,42 @@ run_action() {
1045
1|start|启动)
1146
echo "正在启动 GARSS..."
1247
echo ""
13-
npm run quick:start -- --open
14-
return $?
48+
ensure_docker || return $?
49+
ensure_env
50+
docker compose -f "$COMPOSE_FILE" up --build -d || return $?
51+
open_entry "$(entry_url)"
52+
return 0
1553
;;
1654
2|stop|关闭)
1755
echo "正在关闭 GARSS..."
1856
echo ""
19-
npm run quick:stop
57+
ensure_docker || return $?
58+
docker compose -f "$COMPOSE_FILE" down
2059
return $?
2160
;;
2261
3|upgrade|升级)
2362
echo "正在升级 GARSS..."
2463
echo ""
25-
npm run quick:upgrade -- --open
26-
return $?
64+
ensure_docker || return $?
65+
ensure_env
66+
if [ -d "$ROOT_DIR/.git" ]; then
67+
docker run --rm -v "$ROOT_DIR:/repo" -w /repo alpine/git pull --ff-only || return $?
68+
else
69+
echo "未检测到 .git,跳过代码拉取。"
70+
fi
71+
docker compose -f "$COMPOSE_FILE" pull rsshub || return $?
72+
docker compose -f "$COMPOSE_FILE" up --build -d || return $?
73+
open_entry "$(entry_url)"
74+
return 0
2775
;;
2876
4|status|状态|查看状态)
2977
echo "正在查看 GARSS 状态..."
3078
echo ""
31-
npm run quick:status
79+
ensure_docker || return $?
80+
ensure_env
81+
echo "入口: $(entry_url)"
82+
echo ""
83+
docker compose -f "$COMPOSE_FILE" ps
3284
return $?
3385
;;
3486
5|exit|quit|退出|退出控制台)

GARSS-MACOS.command

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,86 @@
11
#!/bin/zsh
22

33
ROOT_DIR="${0:A:h}"
4-
cd "$ROOT_DIR/garss-studio" || exit 1
4+
PROJECT_DIR="$ROOT_DIR/garss-studio"
5+
COMPOSE_FILE="docker-compose.dev.yml"
6+
7+
cd "$PROJECT_DIR" || exit 1
8+
9+
ensure_docker() {
10+
if ! docker --version >/dev/null 2>&1; then
11+
echo "请先安装并启动 Docker Desktop。"
12+
return 1
13+
fi
14+
}
15+
16+
ensure_env() {
17+
if [ ! -f ".env" ]; then
18+
cp ".env.example" ".env"
19+
echo "已从 .env.example 创建 .env"
20+
fi
21+
}
22+
23+
entry_url() {
24+
local access_code
25+
access_code="$(grep -E '^ACCESS_CODE=' .env 2>/dev/null | head -n 1 | cut -d= -f2-)"
26+
access_code="${access_code%\"}"
27+
access_code="${access_code#\"}"
28+
access_code="${access_code:-banana}"
29+
echo "http://127.0.0.1:25173/reader?pw=$access_code"
30+
}
31+
32+
open_entry() {
33+
local url="$1"
34+
echo "入口: $url"
35+
open "$url" >/dev/null 2>&1 || echo "无法自动打开浏览器,请手动访问: $url"
36+
}
537

638
run_action() {
739
local action="$1"
40+
local url
841

942
case "$action" in
1043
1|start|启动)
1144
echo "正在启动 GARSS..."
1245
echo ""
13-
npm run quick:start -- --open
14-
return $?
46+
ensure_docker || return $?
47+
ensure_env
48+
docker compose -f "$COMPOSE_FILE" up --build -d || return $?
49+
url="$(entry_url)"
50+
open_entry "$url"
51+
return 0
1552
;;
1653
2|stop|关闭)
1754
echo "正在关闭 GARSS..."
1855
echo ""
19-
npm run quick:stop
56+
ensure_docker || return $?
57+
docker compose -f "$COMPOSE_FILE" down
2058
return $?
2159
;;
2260
3|upgrade|升级)
2361
echo "正在升级 GARSS..."
2462
echo ""
25-
npm run quick:upgrade -- --open
26-
return $?
63+
ensure_docker || return $?
64+
ensure_env
65+
if [ -d "$ROOT_DIR/.git" ]; then
66+
docker run --rm -v "$ROOT_DIR:/repo" -w /repo alpine/git pull --ff-only || return $?
67+
else
68+
echo "未检测到 .git,跳过代码拉取。"
69+
fi
70+
docker compose -f "$COMPOSE_FILE" pull rsshub || return $?
71+
docker compose -f "$COMPOSE_FILE" up --build -d || return $?
72+
url="$(entry_url)"
73+
open_entry "$url"
74+
return 0
2775
;;
2876
4|status|状态|查看状态)
2977
echo "正在查看 GARSS 状态..."
3078
echo ""
31-
npm run quick:status
79+
ensure_docker || return $?
80+
ensure_env
81+
echo "入口: $(entry_url)"
82+
echo ""
83+
docker compose -f "$COMPOSE_FILE" ps
3284
return $?
3385
;;
3486
5|exit|quit|退出|退出控制台)

GARSS-WINDOWS.bat

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
@echo off
22
chcp 65001 >nul
3-
setlocal
3+
setlocal EnableExtensions
44

55
set "ROOT_DIR=%~dp0"
6-
cd /d "%ROOT_DIR%garss-studio" || exit /b 1
6+
if "%ROOT_DIR:~-1%"=="\" set "ROOT_DIR=%ROOT_DIR:~0,-1%"
7+
set "PROJECT_DIR=%ROOT_DIR%\garss-studio"
8+
set "COMPOSE_FILE=docker-compose.dev.yml"
9+
10+
cd /d "%PROJECT_DIR%" || exit /b 1
711

812
if not "%~1"=="" (
913
call :run_action "%~1"
@@ -69,28 +73,82 @@ echo 未知操作: %selected%
6973
echo 可用操作: start / stop / upgrade / status / exit
7074
exit /b 1
7175

76+
:ensure_docker
77+
docker --version >nul 2>nul
78+
if errorlevel 1 (
79+
echo 请先安装并启动 Docker Desktop。
80+
exit /b 1
81+
)
82+
exit /b 0
83+
84+
:ensure_env
85+
if not exist ".env" (
86+
copy ".env.example" ".env" >nul
87+
echo 已从 .env.example 创建 .env
88+
)
89+
exit /b 0
90+
91+
:set_entry_url
92+
set "ACCESS_CODE=banana"
93+
if exist ".env" (
94+
for /f "usebackq tokens=1,* delims==" %%A in (".env") do (
95+
if "%%A"=="ACCESS_CODE" set "ACCESS_CODE=%%B"
96+
)
97+
)
98+
set "ACCESS_CODE=%ACCESS_CODE:"=%"
99+
set "GARSS_URL=http://127.0.0.1:25173/reader?pw=%ACCESS_CODE%"
100+
exit /b 0
101+
102+
:open_entry
103+
call :set_entry_url
104+
echo 入口: %GARSS_URL%
105+
start "" "%GARSS_URL%"
106+
exit /b 0
107+
72108
:do_start
73109
echo 正在启动 GARSS...
74110
echo.
75-
call npm run quick:start -- --open
76-
exit /b %ERRORLEVEL%
111+
call :ensure_docker || exit /b 1
112+
call :ensure_env || exit /b 1
113+
docker compose -f "%COMPOSE_FILE%" up --build -d
114+
if errorlevel 1 exit /b %ERRORLEVEL%
115+
call :open_entry
116+
exit /b 0
77117

78118
:do_stop
79119
echo 正在关闭 GARSS...
80120
echo.
81-
call npm run quick:stop
121+
call :ensure_docker || exit /b 1
122+
docker compose -f "%COMPOSE_FILE%" down
82123
exit /b %ERRORLEVEL%
83124

84125
:do_upgrade
85126
echo 正在升级 GARSS...
86127
echo.
87-
call npm run quick:upgrade -- --open
88-
exit /b %ERRORLEVEL%
128+
call :ensure_docker || exit /b 1
129+
call :ensure_env || exit /b 1
130+
if exist "%ROOT_DIR%\.git" (
131+
docker run --rm -v "%ROOT_DIR%:/repo" -w /repo alpine/git pull --ff-only
132+
if errorlevel 1 exit /b %ERRORLEVEL%
133+
) else (
134+
echo 未检测到 .git,跳过代码拉取。
135+
)
136+
docker compose -f "%COMPOSE_FILE%" pull rsshub
137+
if errorlevel 1 exit /b %ERRORLEVEL%
138+
docker compose -f "%COMPOSE_FILE%" up --build -d
139+
if errorlevel 1 exit /b %ERRORLEVEL%
140+
call :open_entry
141+
exit /b 0
89142

90143
:do_status
91144
echo 正在查看 GARSS 状态...
92145
echo.
93-
call npm run quick:status
146+
call :ensure_docker || exit /b 1
147+
call :ensure_env || exit /b 1
148+
call :set_entry_url
149+
echo 入口: %GARSS_URL%
150+
echo.
151+
docker compose -f "%COMPOSE_FILE%" ps
94152
exit /b %ERRORLEVEL%
95153

96154
:do_exit

garss-studio/AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
## 推荐启停命令
2424

25-
仓库根目录有各平台统一入口,双击后选择启动、关闭、升级、查看状态或退出控制台;执行完一次操作后会返回菜单。退出控制台或关闭窗口不应停止服务,只有“关闭”动作会执行 `npm run quick:stop`
25+
仓库根目录有各平台统一入口,双击后选择启动、关闭、升级、查看状态或退出控制台;执行完一次操作后会返回菜单。控制台入口直接调用 Docker,不依赖宿主机 Node.js。退出控制台或关闭窗口不应停止服务,只有“关闭”动作会停止容器
2626

2727
```text
2828
GARSS-MACOS.command

garss-studio/Dockerfile.backend.dev

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ ENV RSSHUB_BASE_URL=http://rsshub:1200
1414

1515
EXPOSE 3001
1616

17-
CMD ["sh", "scripts/dev-entrypoint.sh", "node", "./node_modules/.bin/tsx", "server/index.ts"]
17+
CMD ["node", "scripts/dev-entrypoint.mjs", "node", "./node_modules/.bin/tsx", "server/index.ts"]

garss-studio/Dockerfile.frontend.dev

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ COPY scripts ./scripts
99

1010
EXPOSE 25173
1111

12-
CMD ["sh", "scripts/dev-entrypoint.sh", "npm", "run", "dev:docker"]
12+
CMD ["node", "scripts/dev-entrypoint.mjs", "npm", "run", "dev:docker"]

garss-studio/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ http://127.0.0.1:25173/?pw=banana
6161
| Linux | `GARSS-LINUX.sh` |
6262
| Windows | `GARSS-WINDOWS.bat` |
6363

64-
双击后可选择启动、关闭、升级、查看状态或退出控制台。启动和升级会自动打开浏览器;关闭控制台窗口不会停止服务,只有选择“关闭”才会停止容器。
64+
双击后可选择启动、关闭、升级、查看状态或退出控制台。控制台入口只需要 Docker,不需要宿主机 Node.js;关闭控制台窗口不会停止服务,只有选择“关闭”才会停止容器。
6565

6666
## 开发
6767

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#!/usr/bin/env node
2+
3+
import { readdir, stat } from "node:fs/promises";
4+
import { spawn } from "node:child_process";
5+
6+
async function hasInstalledNodeModules() {
7+
try {
8+
const stats = await stat("node_modules");
9+
if (!stats.isDirectory()) {
10+
return false;
11+
}
12+
const entries = await readdir("node_modules");
13+
return entries.length > 0;
14+
} catch {
15+
return false;
16+
}
17+
}
18+
19+
function run(command, args) {
20+
return new Promise((resolvePromise, rejectPromise) => {
21+
const child = spawn(command, args, {
22+
stdio: "inherit",
23+
});
24+
const signalHandlers = ["SIGINT", "SIGTERM", "SIGHUP"].map((signal) => {
25+
const handler = () => {
26+
if (!child.killed) {
27+
child.kill(signal);
28+
}
29+
};
30+
process.once(signal, handler);
31+
return { signal, handler };
32+
});
33+
34+
child.on("error", (error) => {
35+
for (const item of signalHandlers) {
36+
process.removeListener(item.signal, item.handler);
37+
}
38+
rejectPromise(error);
39+
});
40+
child.on("close", (code, signal) => {
41+
for (const item of signalHandlers) {
42+
process.removeListener(item.signal, item.handler);
43+
}
44+
if (signal) {
45+
resolvePromise(128 + (signal === "SIGINT" ? 2 : signal === "SIGTERM" ? 15 : 1));
46+
return;
47+
}
48+
resolvePromise(code ?? 0);
49+
});
50+
});
51+
}
52+
53+
async function main() {
54+
const [command, ...args] = process.argv.slice(2);
55+
if (!command) {
56+
throw new Error("Missing command for dev entrypoint.");
57+
}
58+
59+
if (!(await hasInstalledNodeModules())) {
60+
const installCode = await run("npm", ["ci"]);
61+
if (installCode !== 0) {
62+
process.exitCode = installCode;
63+
return;
64+
}
65+
}
66+
67+
process.exitCode = await run(command, args);
68+
}
69+
70+
main().catch((error) => {
71+
console.error(error.message);
72+
process.exitCode = 1;
73+
});

0 commit comments

Comments
 (0)