fix(openlist): 修复 openlist 闪退问题

问题原因:
openlist 使用相对路径(如 data/data.db)访问数据库文件,这些路径
相对于工作目录解析。之前工作目录设置为 ~/.netmount,但 openlist
数据在 ~/.netmount/openlist,导致找不到数据库文件而闪退。

解决方案:
1. spawn_sidecar 和 run_sidecar_once 函数添加 cwd 参数
2. 前端启动 openlist 时传入数据目录作为工作目录
3. setOpenlistPass CLI 命令也使用正确的数据目录

修改文件:
- src-tauri/src/lib.rs: 添加 cwd 参数支持
- src/utils/sidecar.ts: 更新函数签名
- src/utils/sidecarService.ts: 传递 cwd 参数
- src/utils/openlist/process.ts: 传入数据目录
- src/utils/openlist/openlist.ts: 传入数据目录
This commit is contained in:
VirtualHotBar
2026-03-26 14:03:28 +08:00
parent 896a110bba
commit bab06c82d1
5 changed files with 31 additions and 14 deletions

View File

@@ -419,6 +419,7 @@ async fn spawn_sidecar(
app: tauri::AppHandle<Runtime>,
name: String,
args: Vec<String>,
cwd: Option<String>,
) -> Result<u32, String> {
use std::process::Stdio;
use std::io::Write as _;
@@ -452,10 +453,14 @@ async fn spawn_sidecar(
), tauri::path::BaseDirectory::Resource)
.map_err(|e| format!("Failed to resolve sidecar path: {}", e))?;
// 获取工作目录(用户主目录下的 .netmount
let work_dir = app.path().home_dir()
.map_err(|e| format!("Failed to get home dir: {}", e))?
.join(".netmount");
// 获取工作目录:优先使用传入的 cwd否则使用默认目录
let work_dir = if let Some(cwd_path) = cwd {
std::path::PathBuf::from(cwd_path)
} else {
app.path().home_dir()
.map_err(|e| format!("Failed to get home dir: {}", e))?
.join(".netmount")
};
// 确保工作目录存在
if !work_dir.exists() {
@@ -658,6 +663,7 @@ async fn run_sidecar_once(
name: String,
args: Vec<String>,
timeout_ms: Option<u64>,
cwd: Option<String>,
) -> Result<RunSidecarOnceResult, String> {
use std::io::Write as _;
use std::process::Stdio;
@@ -695,11 +701,15 @@ async fn run_sidecar_once(
)
.map_err(|e| format!("Failed to resolve sidecar path: {}", e))?;
let work_dir = app
.path()
.home_dir()
.map_err(|e| format!("Failed to get home dir: {}", e))?
.join(".netmount");
// 获取工作目录:优先使用传入的 cwd否则使用默认目录
let work_dir = if let Some(cwd_path) = cwd {
std::path::PathBuf::from(cwd_path)
} else {
app.path().home_dir()
.map_err(|e| format!("Failed to get home dir: {}", e))?
.join(".netmount")
};
if !work_dir.exists() {
let _ = std::fs::create_dir_all(&work_dir);
}

View File

@@ -115,9 +115,11 @@ async function setOpenlistPass(pass: string) {
// v1.1.2 行为:每次启动都无条件写入 admin 密码,避免升级/迁移导致的"密码不一致"卡死。
// OpenList 提供 CLIopenlist --data <dir> admin set <pass>
// 预启动阶段可能失败(数据库不存在),服务启动后再调用此函数会成功
const dataDir = openlistDataDir()
try {
await runSidecarOnce('binaries/openlist', ['--data', openlistDataDir(), 'admin', 'set', pass], {
await runSidecarOnce('binaries/openlist', ['--data', dataDir, 'admin', 'set', pass], {
timeoutMs: 15_000,
cwd: dataDir,
})
return
} catch (e) {

View File

@@ -48,6 +48,8 @@ async function startOpenlist() {
console.log('OpenList start args:', args)
// 使用 Rust 端启动 sidecar确保由主进程创建
// 传入数据目录作为工作目录,确保 openlist 能正确找到数据库文件
const dataDir = openlistDataDir()
let pid: number
try {
pid = await startSidecarAndWait({
@@ -56,6 +58,7 @@ async function startOpenlist() {
args,
readyCheck: openlist_api_ping,
timeoutMs: 30_000,
cwd: dataDir,
})
} catch (e) {
console.error('Failed to spawn OpenList:', e)

View File

@@ -18,19 +18,20 @@ function shortSidecarName(nameOrBinary: string): string {
return nameOrBinary.includes('/') ? nameOrBinary.split('/').pop() || nameOrBinary : nameOrBinary
}
async function spawnSidecar(binary: string, args: string[]): Promise<number> {
return await invoke<number>('spawn_sidecar', { name: binary, args })
async function spawnSidecar(binary: string, args: string[], cwd?: string): Promise<number> {
return await invoke<number>('spawn_sidecar', { name: binary, args, cwd })
}
async function runSidecarOnce(
binary: string,
args: string[],
opts?: { timeoutMs?: number }
opts?: { timeoutMs?: number; cwd?: string }
): Promise<RunSidecarOnceResult> {
return await invoke<RunSidecarOnceResult>('run_sidecar_once', {
name: binary,
args,
timeout_ms: opts?.timeoutMs,
cwd: opts?.cwd,
})
}

View File

@@ -11,6 +11,7 @@ type StartAndWaitOptions = {
timeoutMs?: number
initialDelayMs?: number
includeLogTailOnError?: boolean
cwd?: string
}
async function startSidecarAndWait(opts: StartAndWaitOptions): Promise<number> {
@@ -19,7 +20,7 @@ async function startSidecarAndWait(opts: StartAndWaitOptions): Promise<number> {
let pid = 0
try {
pid = await spawnSidecar(opts.binary, opts.args)
pid = await spawnSidecar(opts.binary, opts.args, opts.cwd)
if (opts.initialDelayMs && opts.initialDelayMs > 0) {
await sleep(opts.initialDelayMs)
}