UNPKG

@cocalc/project

Version:
104 lines 4.04 kB
"use strict"; /* * This file is part of CoCalc: Copyright © 2020 Sagemath, Inc. * License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.status = exports.start = void 0; const base_path_1 = __importDefault(require("@cocalc/backend/base-path")); const data_1 = require("@cocalc/backend/data"); const data_2 = require("@cocalc/project/data"); const info_json_1 = require("@cocalc/project/info-json"); const logger_1 = require("@cocalc/project/logger"); const child_process_1 = require("child_process"); const fs_1 = require("fs"); const get_port_1 = __importDefault(require("get-port")); const path_1 = require("path"); const util_1 = require("util"); const list_1 = __importDefault(require("./list")); const mkdir = (0, util_1.promisify)(fs_1.mkdir); const readFile = (0, util_1.promisify)(fs_1.readFile); const writeFile = (0, util_1.promisify)(fs_1.writeFile); const winston = (0, logger_1.getLogger)("named-servers:control"); // Returns the port or throws an exception. async function start(name) { winston.debug(`start ${name}`); const s = await status(name); if (s.status == "running") { winston.debug(`${name} is already running`); return s.port; } const port = await (0, get_port_1.default)({ port: preferredPort(name) }); // For servers that need a basePath, they will use this one. // Other servers (e.g., Pluto, code-server) that don't need // a basePath because they use only relative URL's are accessed // via .../project_id/server/${port}. let ip = info_json_1.INFO.location.host ?? "127.0.0.1"; if (ip == "localhost") { ip = "127.0.0.1"; } const base = (0, path_1.join)(base_path_1.default, `/${data_2.project_id}/port/${name}`); const cmd = await getCommand(name, ip, port, base); winston.debug(`will start ${name} by running "${cmd}"`); const child = (0, child_process_1.exec)(cmd, { cwd: process.env.HOME }); const p = await paths(name); await writeFile(p.port, `${port}`); await writeFile(p.pid, `${child.pid}`); await writeFile(p.command, `$!/bin/sh\n${cmd}\n`); return port; } exports.start = start; async function getCommand(name, ip, port, base) { const { stdout, stderr } = await paths(name); const spec = (0, list_1.default)(name); const cmd = spec(ip, port, base); return `${cmd} 1>${stdout} 2>${stderr}`; } // Returns the status and port (if defined). async function status(name) { const { pid, port } = await paths(name); try { const pidValue = parseInt((await readFile(pid)).toString()); // it might be running process.kill(pidValue, 0); // throws error if NOT running // it is running const portValue = parseInt((await readFile(port)).toString()); // and there is a port file, // and the port is a number. if (!Number.isInteger(portValue)) { throw Error("invalid port"); } return { status: "running", port: portValue }; } catch (_err) { // it's not running or the port isn't valid return { status: "stopped" }; } } exports.status = status; async function paths(name) { const path = (0, path_1.join)(data_1.data, "named_servers", name); try { await mkdir(path, { recursive: true }); } catch (_err) { // probably already exists } return { pid: (0, path_1.join)(path, "pid"), stderr: (0, path_1.join)(path, "stderr"), stdout: (0, path_1.join)(path, "stdout"), port: (0, path_1.join)(path, "port"), command: (0, path_1.join)(path, "command.sh"), }; } function preferredPort(name) { const p = process.env[`COCALC_${name.toUpperCase()}_PORT`]; if (p == null) return p; return parseInt(p); } //# sourceMappingURL=control.js.map