summaryrefslogtreecommitdiff
path: root/dh_runit
blob: a699692fa9ac1d08dd0d77658f4eb8f1fd7e8339 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#!/usr/bin/perl -w


use v5.10.1;
use strict;
use Debian::Debhelper::Dh_Lib;
use File::Find;
use File::stat;
use feature 'signatures';
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 (/^defaults$/)    { "do nothing"; };
            default                { error("unknown option `$opt'"); }
        }
    }
    return $conf;
}

sub ensure_executable($directory) {
    for my $f ('run', 'finish', 'log/run', 'log/finish') {
        my $file = "$directory/$f";
        doit('chmod', '+x', $file) if (-e $file);
    }
}

sub runit_autoscript($pkg, $script, $sed) {
    autoscript($pkg, $script, "$script-runit", $sed);
}

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";

    install_dir($sv_dir);

    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");
        } elsif ( -d $path) {
            doit('cp', '-r', $path, "$sv_dir/$name");
            # Unfortunately, dh_fixperms does not handle executable bit here.
            ensure_executable("$sv_dir/$name");
        }
        make_symlink("/etc/sv/$name/supervise",
                     "/var/lib/runit/supervise/$name", $tmp);
        install_dir("$tmp/var/lib/runit/supervise/$name");
        install_dir("$tmp/etc/runit/runsvdir/default");

        my $substitutions = {
            NAME   => $name,
            ENABLE => $conf->{enable} ? "yes" : "no"
        };

        runit_autoscript($pkg, 'postrm', $substitutions);
        runit_autoscript($pkg, 'postinst', $substitutions);

        if ($conf->{logscript}) {
            my $logdir = "/var/log/runit/$name";

            install_dir("$sv_dir/$name/log");
            install_dir($tmp . $logdir);

            my $run_log = "$sv_dir/$name/log/run";
            open(RUN_LOG, ">$run_log") || die $!;
            print RUN_LOG << "HERE";
#!/bin/sh
chown -R runit-log:adm '$logdir'
chmod 750 '$logdir'
chmod u+rw,g+r,o-rwx '$logdir'/*
exec chpst -u runit-log svlogd -tt '$logdir'
HERE
            close(RUN_LOG);
            chmod(0755, $run_log);
            make_symlink("/etc/sv/$name/log/supervise",
                         "/var/lib/runit/log/supervise/$name", $tmp);
            install_dir("$tmp/var/lib/runit/log/supervise/$name");
        }
    }
    # runit=2.1.2-20 introduced 'runit-log' user
    addsubstvar($pkg, 'runit:Conflicts', 'runit', '<< 2.1.2-20~');
    addsubstvar($pkg, 'misc:Depends', 'runit-helper', '>= 2.8.1~');
}

# PROMISE: DH NOOP WITHOUT runit

=head1 NAME

dh_runit - install/enable runit runscripts

=head1 SYNOPSIS

B<dh_runit> [S<I<debhelper options>>] [I<path> I<options>] ...

=head1 DESCRIPTION

B<dh_runit> is a debhelper program that is responsible for
installing and enabling I<runit> runscripts. If file named
F<debian/I<package>.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</etc/sv>, containing at least F<run>
executable file. Every enabled program is represented by symbolic link
under F</etc/services> (which itself is symbolic link to
F</etc/runit/runsvdir/default>) pointing to some directory under
F</etc/sv>.

B<dh_runit> reads it's arguments from command line and
F<debian/I<package>.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</etc/sv/*/run>, executable bit is added. If first argument is
directory, it is copied as whole under F</etc/sv>.

Options are comma-separated, like to mount. Unsupported option
is error, following are supported:

=over

=item I<disable>

    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<name>=preferred-name

    By default, name of directory under F</etc/sv> for given runscript
    is basename of first argument of pair. This option allows you to
    be explicit about it.

=item I<logscript>

    Install standard F<log/run> script, which invokes svlogd(8) with
    rights of dedicated user. It is error, if first argument in pair
    is directory, which already contains F</log/run> script.

=item I<defaults>

    If you need no other options, put this one.

=back

=head1 EXAMPLES

This section contains several example snippets from F<I<package>.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

# vim: et:sw=4