Skip to content

Commit ca066da

Browse files
committed
feat: 添加 Termux 支持的简化命令和打包命令
fix: 优化 kill-by-port 脚本,直接调用 sudo 以简化权限管理
1 parent 3f0944b commit ca066da

File tree

5 files changed

+45
-62
lines changed

5 files changed

+45
-62
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,18 @@ cd $HOME/dev-sidecar/packages/gui
443443
NODE_OPTIONS="--require ${HOME:-/data/data/com.termux/files/home}/dev-sidecar/packages/gui/src/utils/os-network-fallback.cjs" \
444444
ELECTRON_FORCE_NO_SANDBOX=1 ELECTRON_NO_SANDBOX=1 ELECTRON_DISABLE_SANDBOX=1 \
445445
npm run electron
446+
447+
或使用简化命令(在 packages/gui 目录下):
448+
449+
```bash
450+
pnpm run electron:termux
451+
```
452+
453+
若需在 Termux 尝试打包(不保证成功,缺少桌面依赖时可能失败):
454+
455+
```bash
456+
pnpm run electron:build:termux
457+
```
446458
```
447459

448460
- 说明:

packages/core/src/shell/scripts/kill-by-port.js

Lines changed: 9 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,48 +4,20 @@ const sudo = require('../sudo')
44
const execute = Shell.execute
55

66
const executor = {
7-
async windows (exec, { port }) {
7+
async windows(exec, { port }) {
88
const killCmd = `for /f "tokens=5" %a in ('netstat -aon ^| find ":${port}" ^| find "LISTENING"') do (taskkill /f /pid %a & exit /B)`
9-
try {
10-
await exec([killCmd], { type: 'cmd' })
11-
return true
12-
} catch (e) {
13-
const msg = String(e || '')
14-
if (/Access is denied|not permitted|permission denied/i.test(msg)) {
15-
// Re-run via sudo to trigger UAC elevation on Windows
16-
await sudo(killCmd, { name: `KillByPort ${port}` })
17-
return true
18-
}
19-
throw e
20-
}
9+
await sudo(killCmd, { name: `KillByPort ${port}` })
10+
return true
2111
},
22-
async linux (exec, { port }) {
12+
async linux(exec, { port }) {
2313
const pidCmd = `lsof -i:${port} |grep 'dev-sidecar\\|electron\\|@docmirro' |awk '{print $2}'`
24-
try {
25-
await exec(`kill \`${pidCmd}\``)
26-
return true
27-
} catch (e) {
28-
const msg = String(e || '')
29-
if (/not permitted|Operation not permitted|permission denied/i.test(msg)) {
30-
await sudo(`kill \`${pidCmd}\``, { name: `KillByPort ${port}` })
31-
return true
32-
}
33-
throw e
34-
}
14+
await sudo(`kill \`${pidCmd}\``, { name: `KillByPort ${port}` })
15+
return true
3516
},
36-
async mac (exec, { port }) {
17+
async mac(exec, { port }) {
3718
const pidCmd = `lsof -i:${port} |grep 'dev-side\\|Elect' |awk '{print $2}'`
38-
try {
39-
await exec(`kill \`${pidCmd}\``)
40-
return true
41-
} catch (e) {
42-
const msg = String(e || '')
43-
if (/not permitted|Operation not permitted|permission denied/i.test(msg)) {
44-
await sudo(`kill \`${pidCmd}\``, { name: `KillByPort ${port}` })
45-
return true
46-
}
47-
throw e
48-
}
19+
await sudo(`kill \`${pidCmd}\``, { name: `KillByPort ${port}` })
20+
return true
4921
},
5022
}
5123

packages/core/src/shell/sudo.js

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,27 @@ const os = require('node:os')
44
const sudoPrompt = require('@vscode/sudo-prompt')
55
const log = require('../utils/util.log.core')
66

7-
function sudo (command, options = {}) {
8-
const { name = 'DevSidecar', onStdout, onStderr } = options
7+
function sudo(command, options = {}) {
8+
const { name = 'DevSidecar', onStdout, onStderr } = options
99

10-
if (!['darwin', 'linux', 'win32'].includes(os.platform())) {
11-
return Promise.reject(new Error('Unsupported platform for privileged operations'))
12-
}
10+
if (!['darwin', 'linux', 'win32'].includes(os.platform())) {
11+
return Promise.reject(new Error('Unsupported platform for privileged operations'))
12+
}
1313

14-
return new Promise((resolve, reject) => {
15-
sudoPrompt.exec(command, { name }, (error, stdout = '', stderr = '') => {
16-
if (stdout && onStdout) onStdout(stdout)
17-
if (stderr && onStderr) onStderr(stderr)
18-
if (error) {
19-
log.error('[sudo] command failed:', command, error)
20-
return reject(error)
21-
}
22-
resolve({ stdout, stderr })
14+
return new Promise((resolve, reject) => {
15+
sudoPrompt.exec(command, { name }, (error, stdout = '', stderr = '') => {
16+
if (stdout && onStdout) onStdout(stdout)
17+
if (stderr && onStderr) onStderr(stderr)
18+
if (error) {
19+
const msg = `[sudo] command failed or was denied. Command: ${command}`
20+
log.error(msg, error)
21+
const wrapped = new Error(`${msg} Please approve the prompt or run manually with elevated privileges.`)
22+
wrapped.cause = error
23+
return reject(wrapped)
24+
}
25+
resolve({ stdout, stderr })
26+
})
2327
})
24-
})
2528
}
2629

2730
module.exports = sudo

packages/core/test/killByPortTest.js

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const assert = require('node:assert')
22
const path = require('node:path')
33

4-
// Stub Shell.execute and sudo to test fallback without running real commands
4+
// Stub Shell.execute and sudo to test direct sudo invocation without running real commands
55
const shellModulePath = path.join(__dirname, '../src/shell/index.js')
66
const sudoModulePath = path.join(__dirname, '../src/shell/sudo.js')
77

@@ -13,14 +13,8 @@ require.cache[shellModulePath] = {
1313
filename: shellModulePath,
1414
loaded: true,
1515
exports: {
16-
// Simulate linux execution path and a permission error on normal kill
17-
execute: async (executor, _args) => {
18-
const fakeExec = async () => {
19-
const err = new Error('Operation not permitted')
20-
throw err
21-
}
22-
return executor.linux(fakeExec, { port: 12345 })
23-
},
16+
// Simulate linux execution path; sudo should be called directly
17+
execute: async (executor, _args) => executor.linux(async () => { }, { port: 12345 }),
2418
execFile: async () => { }
2519
}
2620
}
@@ -40,7 +34,7 @@ const killByPort = require('../src/shell/scripts/kill-by-port')
4034

4135
(async () => {
4236
await killByPort({ port: 12345 })
43-
assert.ok(sudoCalled, 'Expected sudo fallback to be called')
37+
assert.ok(sudoCalled, 'Expected sudo to be called')
4438
assert.ok(/lsof -i:12345/.test(sudoCmd), 'Expected sudo command to target the specified port')
4539
console.log('killByPortTest passed: sudo fallback invoked as expected')
4640
})()

packages/gui/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
"lint": "vue-cli-service lint",
1414
"electron:build": "vue-cli-service electron:build",
1515
"electron": "vue-cli-service electron:serve",
16+
"electron:termux": "NODE_OPTIONS=\"--require ${HOME:-/data/data/com.termux/files/home}/dev-sidecar/packages/gui/src/utils/os-network-fallback.cjs\" ELECTRON_FORCE_NO_SANDBOX=1 ELECTRON_NO_SANDBOX=1 ELECTRON_DISABLE_SANDBOX=1 vue-cli-service electron:serve",
17+
"electron:build:termux": "NODE_OPTIONS=\"--require ${HOME:-/data/data/com.termux/files/home}/dev-sidecar/packages/gui/src/utils/os-network-fallback.cjs\" ELECTRON_FORCE_NO_SANDBOX=1 ELECTRON_NO_SANDBOX=1 ELECTRON_DISABLE_SANDBOX=1 vue-cli-service electron:build",
1618
"postinstall": "electron-builder install-app-deps",
1719
"postuninstall": "electron-builder install-app-deps",
1820
"electron:icons": "electron-icon-builder --input=./public/logo/win.png --output=build --flatten",

0 commit comments

Comments
 (0)