From d912ba4f2edbcd72c4750222e9870fb10b95b874 Mon Sep 17 00:00:00 2001 From: Dmitry Bogatov Date: Sun, 14 Aug 2016 08:19:08 +0300 Subject: * Breaking change package.runit file format to improve interoperability with other tools (supply dh_runit arguments on command line) and make format extensible. See dh_runit(1). * Introduce support for automatic generation of log scripts. --- debian/changelog | 9 +++ dh_runit | 184 ++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 144 insertions(+), 49 deletions(-) diff --git a/debian/changelog b/debian/changelog index 7309546..865bb98 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +dh-runit (1.5) UNRELEASED; urgency=medium + + * Breaking change package.runit file format to improve interoperability + with other tools (supply dh_runit arguments on command line) and make + format extensible. See dh_runit(1). + * Introduce support for automatic generation of log scripts. + + -- Dmitry Bogatov Sat, 13 Aug 2016 11:40:10 +0300 + dh-runit (0.4) unstable; urgency=medium * Fix bug, that caused dh-runit to attempt to create directory diff --git a/dh_runit b/dh_runit index dec63dd..6ec66c8 100755 --- a/dh_runit +++ b/dh_runit @@ -1,53 +1,28 @@ #!/usr/bin/perl -w -=head1 NAME - -dh_runit - install/enable runit runscripts - -=cut +use v5.10.1; use strict; use Debian::Debhelper::Dh_Lib; use File::Find; use File::stat; use feature 'signatures'; -no warnings 'experimental::signatures'; - -=head1 SYNOPSIS - -B [S>] - -=head1 DESCRIPTION - -B is a debhelper program that is responsible for -installing and enabling I runscripts. If file named -F.runit> exists, then different actions -are performed, depending on its format. - -For runit, every unit of supervision, simply speaking program, is -represented by directory under F, containing at least F -executable file. Every enabled program is represented by symbolic link -under F pointing to some directory under F. - -F.runit> is a list of lines, where -every line is either starts with hash symbol and considered comment, -or contains two or three space-separated words. - - # In this case file is installed as 'run' script. Directory name under - # /etc/sv is derived from file basename - enable path/to/file/to/be/installed/as/run/script - - # Same, but install directory as whole. It is your responsibility - # to ensure is contains everything required. - enable path/to/directory - - # Same as above, but do not create symlink under /etc/service - disable path/to/directory - - # Also, you can explicitly specify name of directory under /etc/sv - enable path/to/directory my-preferred-name - -=cut +no warnings 'experimental'; + +sub parse_options($opts) { + my $conf = { enable => 1 }; + for my $opt (split(/,/, $opts)) { + given($opt) { + when (/^disable$/) { $conf->{enable} = 0; }; + when (/^name=(.*)$/) { $conf->{name} = $1; }; + when (/^logscript$/) { $conf->{logscript} = 1}; + when (/^logdir=(.*)$/) { $conf->{logdir} = $1 }; + when (/^defaults$/) { "do nothing"; }; + default { error("unknown option `$opt'"); } + } + } + return $conf; +} sub ensure_executable($directory) { for my $f ('run', 'finish', 'log/run', 'log/finish') { @@ -65,20 +40,28 @@ init(); PKG: foreach my $pkg (@{$dh{DOPACKAGES}}) { next if is_udeb($pkg); + my @entries = (); + if (my $pkgfile = pkgfile($pkg, 'runit')) { + @entries = filedoublearray($pkgfile); + } + while (@ARGV) { + (my $path, my $opts) = splice(@ARGV, 0, 2); + push @entries, [$path, $opts]; + } + my $tmp = tmpdir($pkg); my $sv_dir = "$tmp/etc/sv"; - my $runit = pkgfile($pkg, 'runit'); - next unless $runit; runit_autoscript($pkg, 'preinst', ''); install_dir($sv_dir); - for my $words (filedoublearray($runit)) { - (my $enable, my $path, my $name) = @{$words}; - $name = $name || basename($path); - + for (@entries) { + (my $path, my $opts) = @$_; error("can't read `$path'") unless -r $path; + my $conf = parse_options($opts); + my $name = $conf->{name} || basename($path); + if ( -f $path) { install_dir("$sv_dir/$name"); install_prog($path, "$sv_dir/$name/run"); @@ -91,13 +74,116 @@ PKG: foreach my $pkg (@{$dh{DOPACKAGES}}) { "/var/lib/runit/supervise/$name", $tmp); install_dir("$tmp/var/lib/runit/supervise/$name"); - if ($enable eq 'enable' && !$dh{NO_ENABLE}) { + if ($conf->{enable}) { runit_autoscript($pkg, 'postinst', "s/#NAME#/$name/"); } runit_autoscript($pkg, 'prerm', "s/#NAME#/$name/"); runit_autoscript($pkg, 'postrm', "s/#NAME#/$name/"); + if ($conf->{logscript}) { + my $logdir = $conf->{logdir} || "/var/log/runit/$name"; + $logdir = "$tmp/$logdir"; + + install_dir("$sv_dir/$name/log"); + install_dir($logdir); + + my $run_log = "$sv_dir/$name/log/run"; + my $log_user = $name . "log_"; + open(RUN_LOG, ">$run_log") || die $!; + print RUN_LOG "#!/bin/sh\n"; + print RUN_LOG "mkdir -p '$logdir'\n"; + print RUN_LOG "chown -R '$log_user' '$logdir'\n"; + print RUN_LOG "exec chpst -u '$log_user' svlogd -tt '$logdir'\n"; + close(RUN_LOG); + chmod(0755, $run_log); + doit('dh_sysuser', $log_user, 'defaults'); + } } addsubstvar($pkg, 'misc:Depends', 'runit', '>= 2.1.2-4'); } # PROMISE: DH NOOP WITHOUT runit + +=head1 NAME + +dh_runit - install/enable runit runscripts + +=head1 SYNOPSIS + +B [S>] [I I] ... + +=head1 DESCRIPTION + +B is a debhelper program that is responsible for +installing and enabling I runscripts. If file named +F.runit> exists, then different actions +are performed, depending on its format. + +For runit, every unit of supervision, simply speaking program, is +represented by directory under F, containing at least F +executable file. Every enabled program is represented by symbolic link +under F (which itself is symbolic link to +F) pointing to some directory under +F. + +B reads it's arguments from command line and +F.runit> by two, with first one being an +file/directory and second one is options. If first argument is file, +it is considered 'run' script, and it is installed under +F, executable bit is added. If first argument is +directory, it is copied as whole under F. + +Options are comma-separated, like to mount. Unsupported option +is error, following are supported: + +=over + +=item I + + With this option, runscript is installed, but not enabled by + default. It means that corresponding service will not be started. + System administrator can always do it manually or via + update-service(8). + +=item I=preferred-name + + By default, name of directory under F for given runscript + is basename of first argument of pair. This option allows you to + be explicit about it. + +=item I + + Install standard F script, which invokes svlogd(8) with + rights of dedicated user. It is error, if first argument in pair + is directory, which already contains F script. + +=item I=/path/to/log/directory + + This option is meaningful only with I. It allows + overriding default log directory F>. + +=item I + + If you need no other options, put this one. + +=back + +=head1 EXAMPLES + +This section contains several example snippets from F.runit> + + # In this case file is installed as 'run' script. Directory name under + # /etc/sv is derived from file basename + path/to/file/to/be/installed/as/run/script defaults + + # Same, but install directory as whole. It is your responsibility + # to ensure is contains everything required. + path/to/directory defaults + + # Same as above, but do not create symlink under /etc/service + path/to/directory disable + + # You can explicitly specify name of directory under /etc/sv. + # Standard log/run script will be created. + path/to/directory name=my-preferred-name,logscript + +=cut -- cgit v1.2.3