github.com/easysoft/zendata@v0.0.0-20240513203326-705bd5a7fd67/client/src/app/core/zd.js (about) 1 import {app} from 'electron'; 2 import os from 'os'; 3 import path from 'path'; 4 import {execSync, spawn} from 'child_process'; 5 6 import {DEBUG, portServer, uuid} from '../utils/consts'; 7 import {IS_WINDOWS_OS} from "../utils/env"; 8 import {logErr, logInfo} from '../utils/log'; 9 10 let _zdProcess; 11 12 export async function startZdServer() { 13 if (process.env.SKIP_SERVER && parseInt(process.env.SKIP_SERVER)) { 14 logInfo(`>> skip to start zd Server by env "SKIP_SERVER=${process.env.SKIP_SERVER}".`); 15 return Promise.resolve(); 16 } 17 if (_zdProcess) { 18 return Promise.resolve(_zdProcess); 19 } 20 21 let {SERVER_EXE_PATH: serverExePath} = process.env; 22 if (!serverExePath && !DEBUG) { 23 const platform = os.platform(); // 'darwin', 'linux', 'win32' 24 const exePath = `bin/${platform}/server${platform === 'win32' ? '.exe' : ''}`; 25 serverExePath = path.join(process.resourcesPath, exePath); 26 } 27 if (serverExePath) { 28 if (!path.isAbsolute(serverExePath)) { 29 serverExePath = path.resolve(app.getAppPath(), serverExePath); 30 } 31 return new Promise((resolve, reject) => { 32 const cwd = process.env.SERVER_CWD_PATH || path.dirname(serverExePath); 33 logInfo(`>> starting zd server with command ` + 34 `"${serverExePath} -p ${portServer} -uuid ${uuid}" in "${cwd}"...`); 35 36 const cmd = spawn('"'+serverExePath+'"', ['-p', portServer, '-uuid', uuid], { 37 cwd, 38 shell: true, 39 }); 40 41 _zdProcess = cmd; 42 logInfo(`>> zd server process = ${_zdProcess.pid}`) 43 44 cmd.on('exit', (code) => { 45 logInfo(`>> zd server closed with code ${code}`); 46 _zdProcess = null; 47 cmd.kill() 48 }); 49 cmd.stdout.on('data', data => { 50 const dataString = String(data); 51 const lines = dataString.split('\n'); 52 for (let line of lines) { 53 if (true) { 54 logInfo('\t' + line); 55 } 56 if (line.includes('Now listening on: http')) { 57 resolve(line.split('Now listening on:')[1].trim()); 58 if (!DEBUG) { 59 break; 60 } 61 } else if (line.includes('启动HTTP服务于')) { 62 resolve(line.split(/启动HTTP服务于|,/)[1].trim()); 63 if (!DEBUG) { 64 break; 65 } 66 } else if (line.startsWith('[ERRO]')) { 67 reject(new Error(`start zd server failed, error: ${line.substring('[ERRO]'.length)}`)); 68 if (!DEBUG) { 69 break; 70 } 71 } 72 } 73 }); 74 cmd.on('error', spawnError => { 75 logErr('>>> start zd server failed with error', spawnError); 76 reject(spawnError) 77 }); 78 }); 79 } 80 81 return new Promise((resolve, reject) => { 82 const cwd = process.env.SERVER_CWD_PATH || path.resolve(app.getAppPath(), '../'); 83 logInfo(`>> starting zd development server from source with command "go run cmd/server/main.go -p ${portServer}" in "${cwd}"`); 84 const cmd = spawn('go', ['run', 'main.go', '-p', portServer], { 85 cwd, 86 shell: true, 87 }); 88 cmd.on('close', (code) => { 89 logInfo(`>> zd server closed with code ${code}`); 90 _zdProcess = null; 91 }); 92 cmd.stdout.on('data', data => { 93 const dataString = String(data); 94 const lines = dataString.split('\n'); 95 for (let line of lines) { 96 if (DEBUG) { 97 logInfo('\t' + line); 98 } 99 if (line.includes('Now listening on: http')) { 100 resolve(line.split('Now listening on:')[1].trim()); 101 if (!DEBUG) { 102 break; 103 } 104 } else if (line.startsWith('[ERRO]')) { 105 reject(new Error(`start zd server failed, error: ${line.substring('[ERRO]'.length)}`)); 106 if (!DEBUG) { 107 break; 108 } 109 } 110 } 111 }); 112 cmd.on('error', spawnError => { 113 console.error('>>> start zd server failed with error', spawnError); 114 reject(spawnError) 115 }); 116 _zdProcess = cmd; 117 }); 118 } 119 120 export function killZdServer() { 121 if (!IS_WINDOWS_OS) { 122 logInfo(`>> not windows`); 123 124 const cmd = `ps -ef | grep ${uuid} | grep -v "grep" | awk '{print $2}' | xargs -r kill -9` 125 logInfo(`>> exit cmd: ${cmd}`); 126 127 const cp = require('child_process'); 128 cp.exec(cmd, function (error, stdout, stderr) { 129 logInfo(`>> exit result: stdout: ${stdout}; stderr: ${stderr}; error: ${error}`); 130 }); 131 } else { 132 const cmd = 'WMIC path win32_process where "Commandline like \'%%' + uuid + '%%\'" get Processid,Caption'; 133 logInfo(`>> list process cmd: ${cmd}`); 134 135 const stdout = execSync(cmd, {windowsHide: true}).toString().trim() 136 logInfo(`>> list process result: exec ${cmd}, stdout: ${stdout}`) 137 138 let pid = 0 139 const lines = stdout.split('\n') 140 lines.forEach(function(line){ 141 line = line.trim() 142 console.log(`<${line}>`) 143 logInfo(`<${line}>`) 144 const cols = line.split(/\s/) 145 146 if (line.indexOf('server') > -1) { 147 const col3 = cols[cols.length-1].trim() 148 console.log(`col3=${col3}`); 149 logInfo(`col3=${col3}`) 150 151 if (col3 && parseInt(col3, 10)) { 152 pid = parseInt(col3, 10) 153 } 154 } 155 }); 156 157 if (pid && pid > 0) { 158 const killCmd = `taskkill /F /pid ${pid}` 159 logInfo(`>> exit cmd: exec ${killCmd}`) 160 161 const out = execSync(`taskkill /F /pid ${pid}`, {windowsHide: true}).toString().trim() 162 logInfo(`>> exit result: ${out}`) 163 } 164 } 165 }