150 lines
3.1 KiB
JavaScript
150 lines
3.1 KiB
JavaScript
const { execSync } = require("child_process");
|
|
const { statSync } = require("fs");
|
|
const { exit } = require("process");
|
|
|
|
module.exports = {
|
|
info,
|
|
runCommand,
|
|
logErrorAndExit,
|
|
registerSignalHandler,
|
|
initSignalHandlers,
|
|
assertOS,
|
|
assertEffectiveRoot,
|
|
assertFileExists,
|
|
assertInstalled
|
|
};
|
|
|
|
let signalHandlers = [];
|
|
|
|
function registerSignalHandler(cb) {
|
|
signalHandlers.push(cb);
|
|
|
|
return () => (signalHandlers = signalHandlers.filter(h => h === cb));
|
|
}
|
|
|
|
function initSignalHandlers() {
|
|
process.on("SIGTERM", handle);
|
|
process.on("SIGINT", handle);
|
|
process.on("SIGHUP", handle);
|
|
}
|
|
|
|
function handle(signal) {
|
|
console.log(`Received ${signal}`);
|
|
|
|
for (const handler of signalHandlers) {
|
|
handler(signal);
|
|
}
|
|
}
|
|
|
|
function info(msg) {
|
|
console.log(`\n${msg}`);
|
|
}
|
|
|
|
function runCommand(command, _options) {
|
|
const options = {
|
|
encoding: "utf8",
|
|
..._options,
|
|
shell: true
|
|
};
|
|
|
|
const { onError } = options;
|
|
delete options["onError"];
|
|
|
|
try {
|
|
const result = execSync(command, options);
|
|
|
|
return (typeof result === "string")
|
|
? result.trim()
|
|
: result;
|
|
} catch (error) {
|
|
if (onError) {
|
|
onError(error);
|
|
} else {
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
|
|
function logErrorAndExit(msg, error) {
|
|
const lines = msg.split("\n");
|
|
|
|
// Get rid of leading blank lines
|
|
while (lines.length) {
|
|
if (lines[0].trim().length == 0) {
|
|
lines.shift();
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Get rid of trailing blank lines
|
|
while (lines.length) {
|
|
if (lines.at(-1).trim().length == 0) {
|
|
lines.pop();
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
const [ whitespace ] = lines[0].match(/^\s*/);
|
|
|
|
console.error(lines
|
|
.map(line => line.replace(whitespace, "").trimEnd())
|
|
.join("\n")
|
|
);
|
|
|
|
if (error) {
|
|
console.error("Error:", JSON.stringify({
|
|
name: error.name,
|
|
code: error.code,
|
|
status: error.status,
|
|
signal: error.signal,
|
|
error: error.error,
|
|
pid: error.pid,
|
|
output: error.output,
|
|
msg: error.msg,
|
|
message: error.message
|
|
}, null, 4));
|
|
}
|
|
|
|
exit(1);
|
|
}
|
|
|
|
function assertOS() {
|
|
if (process.platform !== "linux") {
|
|
logErrorAndExit("This script requires linux.");
|
|
}
|
|
}
|
|
|
|
function assertEffectiveRoot() {
|
|
if (process.geteuid() !== 0) {
|
|
logErrorAndExit("Please run this script as root");
|
|
}
|
|
}
|
|
|
|
function assertFileExists(file) {
|
|
const stats = statSync(file);
|
|
if (!stats.isFile) {
|
|
logErrorAndExit(`${file} does not exist`);
|
|
}
|
|
}
|
|
|
|
function assertInstalled(tools) {
|
|
const missingTools = [];
|
|
|
|
for (const tool of tools) {
|
|
runCommand(`command -v ${tool}`, {
|
|
onError: () => missingTools.push(tool)
|
|
});
|
|
}
|
|
|
|
if (missingTools.length) {
|
|
logErrorAndExit(`
|
|
This script requires some tools that are not installed.
|
|
|
|
Install them via:
|
|
apt-get install -y ${missingTools.join(" ")}
|
|
`);
|
|
}
|
|
}
|