@clazic/urban 0.2.14 → 0.2.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/install/daemon.js +38 -33
package/package.json
CHANGED
package/src/install/daemon.js
CHANGED
|
@@ -69,36 +69,36 @@ WantedBy=default.target
|
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
71
|
* 순수 함수: Windows PowerShell 커맨드 생성
|
|
72
|
+
*
|
|
73
|
+
* VBScript 방식 폐기 이유:
|
|
74
|
+
* - Set-Content -Encoding ASCII가 한글 사용자 경로를 깨뜨림 (조용히 실패)
|
|
75
|
+
* - oWsh.Run True(동기) + RestartCount 충돌 → 0xC000013A CTRL+BREAK 강제 종료
|
|
76
|
+
* - stdout/stderr 버려져 진단 불가
|
|
77
|
+
*
|
|
78
|
+
* 새 방식: cmd.exe /c + S4U Principal + -Hidden
|
|
79
|
+
* - S4U(Service For User): 비밀번호 없이 비대화형 세션에서 실행 → 콘솔 창 절대 안 뜸
|
|
80
|
+
* - cmd.exe로 URBAN_HOME 환경변수 주입 + 로그 리다이렉트
|
|
81
|
+
* - -Hidden: 작업 자체를 숨김
|
|
72
82
|
*/
|
|
73
|
-
export function buildPowerShellCmd({ nodePath, daemonJs, urbanHome }) {
|
|
74
|
-
const
|
|
83
|
+
export function buildPowerShellCmd({ nodePath, daemonJs, urbanHome, logsDir }) {
|
|
84
|
+
const psQ = (s) => String(s).replace(/'/g, "''");
|
|
75
85
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const vbsPath = join(urbanHome, 'urban-launcher.vbs');
|
|
79
|
-
const escapedVbsPath = psEscape(vbsPath);
|
|
80
|
-
// VBScript 문자열 내 쌍따옴표 이스케이프 ("" = 리터럴 ")
|
|
81
|
-
const vbsNodePath = nodePath.replace(/"/g, '""');
|
|
82
|
-
const vbsDaemonJs = daemonJs.replace(/"/g, '""');
|
|
86
|
+
const outLog = join(logsDir, 'out.log');
|
|
87
|
+
const errLog = join(logsDir, 'err.log');
|
|
83
88
|
|
|
84
89
|
return `
|
|
85
|
-
$
|
|
86
|
-
$
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
'
|
|
90
|
-
|
|
91
|
-
$action
|
|
92
|
-
$trigger
|
|
93
|
-
$
|
|
94
|
-
-ExecutionTimeLimit
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
-StartWhenAvailable \`
|
|
98
|
-
-MultipleInstances IgnoreNew \`
|
|
99
|
-
-RestartCount 5 \`
|
|
100
|
-
-RestartInterval (New-TimeSpan -Minutes 1)
|
|
101
|
-
Register-ScheduledTask -TaskName 'Urban' -Action $action -Trigger $trigger -Settings $settings -Force
|
|
90
|
+
$nodePath = '${psQ(nodePath)}'
|
|
91
|
+
$daemonJs = '${psQ(daemonJs)}'
|
|
92
|
+
$urbanHome = '${psQ(urbanHome)}'
|
|
93
|
+
$outLog = '${psQ(outLog)}'
|
|
94
|
+
$errLog = '${psQ(errLog)}'
|
|
95
|
+
$cmdArgs = '/c set "URBAN_HOME=' + $urbanHome + '" && "' + $nodePath + '" "' + $daemonJs + '" 1>>"' + $outLog + '" 2>>"' + $errLog + '"'
|
|
96
|
+
$action = New-ScheduledTaskAction -Execute 'cmd.exe' -Argument $cmdArgs -WorkingDirectory $urbanHome
|
|
97
|
+
$trigger = New-ScheduledTaskTrigger -AtLogOn -User $env:USERNAME
|
|
98
|
+
$principal = New-ScheduledTaskPrincipal -UserId $env:USERNAME -LogonType S4U -RunLevel Limited
|
|
99
|
+
$settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit ([TimeSpan]::Zero) -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -MultipleInstances IgnoreNew -RestartCount 5 -RestartInterval (New-TimeSpan -Minutes 1) -Hidden
|
|
100
|
+
Unregister-ScheduledTask -TaskName 'Urban' -Confirm:$false -ErrorAction SilentlyContinue | Out-Null
|
|
101
|
+
Register-ScheduledTask -TaskName 'Urban' -Action $action -Trigger $trigger -Principal $principal -Settings $settings | Out-Null
|
|
102
102
|
`;
|
|
103
103
|
}
|
|
104
104
|
|
|
@@ -139,15 +139,23 @@ export async function installDaemon() {
|
|
|
139
139
|
return { ok: true, message: `macOS 데몬 등록 완료: ${plistPath}` };
|
|
140
140
|
} else if (isWindows) {
|
|
141
141
|
// Windows: Task Scheduler (PowerShell)
|
|
142
|
-
const ps = buildPowerShellCmd({ nodePath, daemonJs, urbanHome: URBAN_HOME });
|
|
142
|
+
const ps = buildPowerShellCmd({ nodePath, daemonJs, urbanHome: URBAN_HOME, logsDir });
|
|
143
143
|
try {
|
|
144
144
|
// -EncodedCommand: Base64(UTF-16LE) — 따옴표/특수문자 인젝션 방지
|
|
145
|
+
// stdio: pipe로 PowerShell 에러 메시지 캡처해 진단 가능하게
|
|
145
146
|
const encoded = Buffer.from(ps, 'utf16le').toString('base64');
|
|
146
|
-
execSync(`powershell -NoProfile -EncodedCommand ${encoded}`, {
|
|
147
|
+
execSync(`powershell -NoProfile -ExecutionPolicy Bypass -EncodedCommand ${encoded}`, {
|
|
148
|
+
shell: false,
|
|
149
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
150
|
+
});
|
|
147
151
|
} catch (err) {
|
|
148
|
-
|
|
149
|
-
return { ok: false, message: `Windows 데몬 등록
|
|
152
|
+
const stderr = err.stderr ? err.stderr.toString('utf8').trim() : '';
|
|
153
|
+
return { ok: false, message: `Windows 데몬 등록 실패: ${err.message}${stderr ? '\n ' + stderr : ''}` };
|
|
150
154
|
}
|
|
155
|
+
// AtLogOn 트리거는 다음 로그온까지 대기 → 즉시 1회 시작
|
|
156
|
+
try {
|
|
157
|
+
execSync(`powershell -NoProfile -Command "Start-ScheduledTask -TaskName 'Urban'"`, { shell: true, stdio: 'ignore' });
|
|
158
|
+
} catch { /* 이미 실행 중이면 무시 */ }
|
|
151
159
|
return { ok: true, message: `Windows 데몬 등록 완료 (작업 스케줄러: Urban)` };
|
|
152
160
|
} else if (isLinux) {
|
|
153
161
|
// Linux: systemd user service
|
|
@@ -206,9 +214,6 @@ export async function uninstallDaemon() {
|
|
|
206
214
|
} catch (err) {
|
|
207
215
|
// 작업이 없거나 권한 부족 → 무시
|
|
208
216
|
}
|
|
209
|
-
// VBScript 런처 파일 정리
|
|
210
|
-
const vbsPath = join(URBAN_HOME, 'urban-launcher.vbs');
|
|
211
|
-
if (existsSync(vbsPath)) rmSync(vbsPath);
|
|
212
217
|
return { ok: true, message: `Windows 데몬 제거 완료` };
|
|
213
218
|
} else if (isLinux) {
|
|
214
219
|
try {
|