1

svc: implement system mode

This commit is contained in:
eleksir
2020-02-24 13:46:37 +03:00
parent cea7035d86
commit 3b6a9575db
2 changed files with 47 additions and 32 deletions

78
svc
View File

@@ -3,9 +3,6 @@
# runit sv utility ignores evironment variable SVDIR # runit sv utility ignores evironment variable SVDIR
# and unable to list services, fully relying to user this knowlege # and unable to list services, fully relying to user this knowlege
# TODO handle root user case as system mode!
# TODO handle system mode correctly
use strict; use strict;
use warnings "all"; use warnings "all";
use JSON::PP; use JSON::PP;
@@ -14,29 +11,45 @@ sub help;
sub ctrl ($); sub ctrl ($);
sub status; sub status;
my $sep = $/; my $c;
$/ = '';
open (CONF, "$ENV{HOME}/.local/etc/svc.json") or die "No config at $ENV{HOME}/.local/etc/svc.json\n"; if ($>) {
# looks like we run in user-mode, so manage user services
die "\$HOME is not set\n" unless (defined($ENV{HOME}));
die "$ENV{HOME} does not exist\n" unless (-d $ENV{HOME});
my $c = <CONF>; my $sep = $/;
close CONF; $/ = '';
$/ = $sep;
$c = decode_json($c); # TODO: actually, to be the most XDG-compatible, we should put config to $ENV{HOME}/.config/svc/svc.json
open (CONF, "$ENV{HOME}/.local/etc/svc.json") or die "No config at $ENV{HOME}/.local/etc/svc.json\n";
$c = <CONF>;
close CONF;
$/ = $sep;
if ($c->{mode} eq 'user') { $c = decode_json($c);
die "\$HOME is no set\n" unless (defined($ENV{HOME})); $c->{dir} = sprintf("%s%s", $ENV{HOME}, $c->{dir});
die "$ENV{HOME} does not exist" unless (-d $ENV{HOME}); $c->{servicedir} = sprintf("%s%s", $ENV{HOME}, $c->{servicedir});
chdir $ENV{HOME};
die "No such directory $ENV{HOME}$c->{dir}\n" unless(-d "$ENV{HOME}$c->{dir}");
chdir "$ENV{HOME}$c->{dir}";
} else { } else {
die "No such directory $c->{dir}" unless(-d $c->{dir}); # looks like we run with root privileges, manage system services
chdir $c->{dir}; $c->{mode} = "system";
$c->{dir} = "/etc/service";
if (-d "/etc/service.d") {
$c->{servicedir} = "/etc/service.d";
} else {
# guideline of runit suggest to use /service directory, also sv utility expects services placed there by default
$c->{servicedir} = "/service";
}
$c->{timeout} = 3;
} }
unless(defined($ARGV[0])) { die "No such directory $c->{dir}\n" unless (-d $c->{dir});
chdir $c->{dir};
unless (defined($ARGV[0])) {
help; help;
} else { } else {
if ($ARGV[0] ne 'list') { if ($ARGV[0] ne 'list') {
@@ -48,32 +61,32 @@ if ($ARGV[0] eq 'list') {
my $d; my $d;
if (defined($ARGV[1]) && $ARGV[1] eq '--all') { if (defined($ARGV[1]) && $ARGV[1] eq '--all') {
$d = "$ENV{HOME}$c->{servicedir}"; $d = $c->{servicedir};
} else { } else {
$d = "$ENV{HOME}$c->{dir}"; $d = $c->{dir};
} }
opendir(D, $d) or die "Unable to list services\n"; opendir(D, $d) or die "Unable to list services, no such directory $d\n";
print join("\n", sort(grep {!/^\.{1,2}$/} readdir(D))) . "\n"; print join("\n", sort (grep {!/^\.{1,2}$/} readdir(D))) . "\n";
closedir D; closedir D;
} elsif ($ARGV[1] eq 'disable') { } elsif ($ARGV[1] eq 'disable') {
my $d = "$ENV{HOME}$c->{dir}/$ARGV[0]"; my $d = "$c->{dir}/$ARGV[0]";
if (-l $d) { if (-l $d) {
unlink("$d") or die "Unable to disable $ARGV[0]\n"; unlink ("$d") or die "Unable to disable $ARGV[0]\n";
} else { } else {
die "No such service $ARGV[0]\n"; die "No such service $ARGV[0]\n";
} }
} elsif ($ARGV[1] eq 'enable') { } elsif ($ARGV[1] eq 'enable') {
my $d = "$ENV{HOME}$c->{dir}/$ARGV[0]"; my $d = "$c->{dir}/$ARGV[0]";
if (-l $d) { if (-l $d) {
die "Service $ARGV[0] already enabled\n"; die "Service $ARGV[0] already enabled\n";
} else { } else {
my $svcdir = "$ENV{HOME}$c->{servicedir}/$ARGV[0]"; my $svcdir = "$c->{servicedir}/$ARGV[0]";
if (-d $svcdir) { if (-d $svcdir) {
symlink($svcdir, $d) or die "Unable to enable service $ARGV[0]\n"; symlink ($svcdir, $d) or die "Unable to enable service $ARGV[0]\n";
} else { } else {
die "No such service $ARGV[0]\n"; die "No such service $ARGV[0]\n";
} }
@@ -132,16 +145,17 @@ sub help {
sub ctrl ($) { sub ctrl ($) {
my $command = shift; my $command = shift;
open (C, ">", "control") or die; open (C, ">", "control") or die "Unable to write to control socket\n";
print C $command; print C $command;
close C; close C;
} }
sub status { sub status {
open (S, "stat") or die; open (S, "stat") or die "Unable to read status.\n";
my $status = <S>; my $status = <S>;
chomp($status); chomp $status;
close S; close S;
return $status; return $status;
} }
# vim: set ft=perl noet ai :
# vim: set ft=perl noet ai ts=4 sw=4 sts=4:

View File

@@ -1,5 +1,6 @@
{ {
"mode": "user", "mode": "user",
"dir": "/.local/etc/services", "dir": "/.local/etc/services",
"servicedir": "/.local/etc/service.d",
"timeout": 3 "timeout": 3
} }