78 lines
2.2 KiB
TypeScript
78 lines
2.2 KiB
TypeScript
|
|
import { DEFAULT_CONFIG_PATH } from './config.ts';
|
||
|
|
|
||
|
|
const SERVICE_FILE_PATH = '/etc/systemd/system/uptimerunner.service';
|
||
|
|
|
||
|
|
export class UptimeRunnerSystemd {
|
||
|
|
private readonly serviceTemplate = `[Unit]
|
||
|
|
Description=uptime.link Runner Agent
|
||
|
|
After=network-online.target
|
||
|
|
Wants=network-online.target
|
||
|
|
|
||
|
|
[Service]
|
||
|
|
ExecStart=/usr/local/bin/uptimerunner run --config ${DEFAULT_CONFIG_PATH}
|
||
|
|
Restart=always
|
||
|
|
RestartSec=10
|
||
|
|
User=root
|
||
|
|
Group=root
|
||
|
|
Environment=PATH=/usr/bin:/usr/local/bin
|
||
|
|
WorkingDirectory=/opt/uptimerunner
|
||
|
|
|
||
|
|
[Install]
|
||
|
|
WantedBy=multi-user.target
|
||
|
|
`;
|
||
|
|
|
||
|
|
public async install(): Promise<void> {
|
||
|
|
this.assertRoot();
|
||
|
|
await Deno.writeTextFile(SERVICE_FILE_PATH, this.serviceTemplate);
|
||
|
|
await run('systemctl', ['daemon-reload']);
|
||
|
|
await run('systemctl', ['enable', 'uptimerunner.service']);
|
||
|
|
console.log(`Service installed: ${SERVICE_FILE_PATH}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
public async uninstall(): Promise<void> {
|
||
|
|
this.assertRoot();
|
||
|
|
await run('systemctl', ['disable', '--now', 'uptimerunner.service']).catch(() => null);
|
||
|
|
await Deno.remove(SERVICE_FILE_PATH).catch(() => null);
|
||
|
|
await run('systemctl', ['daemon-reload']);
|
||
|
|
console.log('Service removed.');
|
||
|
|
}
|
||
|
|
|
||
|
|
public async start(): Promise<void> {
|
||
|
|
await run('systemctl', ['start', 'uptimerunner.service']);
|
||
|
|
}
|
||
|
|
|
||
|
|
public async stop(): Promise<void> {
|
||
|
|
await run('systemctl', ['stop', 'uptimerunner.service']);
|
||
|
|
}
|
||
|
|
|
||
|
|
public async restart(): Promise<void> {
|
||
|
|
await run('systemctl', ['restart', 'uptimerunner.service']);
|
||
|
|
}
|
||
|
|
|
||
|
|
public async status(): Promise<void> {
|
||
|
|
await run('systemctl', ['status', 'uptimerunner.service', '--no-pager']);
|
||
|
|
}
|
||
|
|
|
||
|
|
public async logs(): Promise<void> {
|
||
|
|
await run('journalctl', ['-u', 'uptimerunner.service', '-n', '120', '--no-pager']);
|
||
|
|
}
|
||
|
|
|
||
|
|
private assertRoot(): void {
|
||
|
|
if (Deno.uid && Deno.uid() !== 0) {
|
||
|
|
throw new Error('This service command must run as root.');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async function run(commandArg: string, argsArg: string[]): Promise<void> {
|
||
|
|
const command = new Deno.Command(commandArg, {
|
||
|
|
args: argsArg,
|
||
|
|
stdout: 'inherit',
|
||
|
|
stderr: 'inherit',
|
||
|
|
});
|
||
|
|
const output = await command.output();
|
||
|
|
if (!output.success) {
|
||
|
|
throw new Error(`${commandArg} ${argsArg.join(' ')} exited with ${output.code}`);
|
||
|
|
}
|
||
|
|
}
|