import { readFile } from "node:fs/promises"; import path from "node:path"; import { Alpine } from "../alpine.js"; export class Runit { alpine: Alpine; private constructor({ alpine }: { alpine: Alpine }) { this.alpine = alpine; } private static async getScript(name: string): Promise { return await readFile(path.join("runit/scripts", name), "utf8"); } static async setup(alpine: Alpine): Promise { await alpine.mkdirP("/etc/runit/runsvdir/default"); await alpine.symlink( "/etc/runit/runsvdir/default", "/etc/runit/runsvdir/current" ); await alpine.symlink("/etc/runit/runsvdir/current", "/etc/service"); await alpine.symlink("/run/runit/stopit", "/etc/runit/stopit"); await alpine.symlink("/run/runit/reboot", "/etc/runit/reboot"); // Estos scripts fueron robados de Void Linux await alpine.writeExecutable( "/etc/runit/functions", await this.getScript("functions") ); await alpine.writeExecutable( "/etc/runit/core-services/00-pseudofs.sh", await this.getScript("00-pseudofs.sh") ); await alpine.writeExecutable( "/etc/runit/core-services/01-static-devnodes.sh", await this.getScript("01-static-devnodes.sh") ); await alpine.writeExecutable( "/etc/runit/core-services/02-udev.sh", await this.getScript("02-udev.sh") ); await alpine.writeExecutable( "/etc/runit/core-services/03-filesystems.sh", await this.getScript("03-filesystems.sh") ); await alpine.writeExecutable( "/etc/runit/core-services/04-swap.sh", await this.getScript("04-swap.sh") ); await alpine.writeExecutable( "/etc/runit/core-services/05-misc.sh", await this.getScript("05-misc.sh") ); for (let stage = 1; stage <= 3; stage++) await alpine.writeExecutable( "/etc/runit/" + stage, await this.getScript("" + stage) ); // https://wiki.gentoo.org/wiki/Runit#Reboot_and_shutdown await alpine.sudoWriteExecutable( "/usr/local/sbin/rpoweroff", `#!/bin/sh runit-init 0` ); await alpine.sudoWriteExecutable( "/usr/local/sbin/rreboot", `#!/bin/sh runit-init 6` ); await alpine.addPackages(["runit", "eudev"]); const runit = new Runit({ alpine }); await runit.addService( "getty-tty1", `#!/bin/sh exec chpst -P getty 38400 tty1 linux`, false ); await runit.addService( "getty-tty2", `#!/bin/sh exec chpst -P getty 38400 tty2 linux`, false ); await runit.addService( "getty-ttyS0", `#!/bin/sh exec chpst -P getty 38400 ttyS0 linux`, false ); return runit; } async addService( name: string, script: string, log: boolean = true ): Promise { const runScriptPath = path.join("/etc/sv/", name, "/run"); await this.alpine.sudoWriteExecutable(runScriptPath, script); if (log) { const logScriptPath = path.join("/etc/sv/", name, "/log/run"); await this.alpine.sudoWriteExecutable( logScriptPath, `#!/bin/sh exec logger -p daemon.info -t '${name}'` ); await this.alpine.symlink( `/run/runit/supervise.${name}.log`, path.join("/etc/sv/", name, "/log/supervise") ); } // Activar servicio await this.alpine.symlink( path.join("/etc/sv/", name), path.join("/etc/runit/runsvdir/default/", name) ); await this.alpine.symlink( `/run/runit/supervise.${name}`, path.join("/etc/sv/", name, "/supervise") ); } }