/usr/bin/dh_systemd_start is in dh-systemd 1.14.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
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 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | #!/usr/bin/perl -w
=head1 NAME
dh_systemd_start - start/stop/restart systemd unit files
=cut
use strict;
use Debian::Debhelper::Dh_Lib;
use File::Find;
use Text::ParseWords qw(shellwords); # in core since Perl 5
use Cwd qw(getcwd abs_path);
=head1 SYNOPSIS
B<dh_systemd_start> [S<I<debhelper options>>] [B<--restart-after-upgrade>] [B<--no-restart-on-upgrade>] [S<I<unit file> ...>]
=head1 DESCRIPTION
B<dh_systemd_start> is a debhelper program that is responsible for
starting/stopping or restarting systemd unit files in case no corresponding
sysv init script is available.
As with B<dh_installinit>, the unit file is stopped before
upgrades and started afterwards (unless B<--restart-after-upgrade> is
specified, in which case it will only be restarted after the upgrade).
This logic is not used when there is a corresponding SysV init script
because invoke-rc.d performs the stop/start/restart in that case.
=head1 OPTIONS
=over 4
=item B<--restart-after-upgrade>
Do not stop the unit file until after the package upgrade has been completed.
This is different than the default behavior, which stops the unit file in the
F<prerm> and starts it again in the F<postinst> maintscript.
This can be useful for daemons that should not have a possibly long
downtime during upgrade. But you should make sure that the daemon will not
get confused by the package being upgraded while it's running before using
this option.
=item B<-r>, B<--no-restart-on-upgrade>
Do not stop service on upgrade.
=item B<--no-start>
Do not start the unit file after upgrades and after initial installation (the
latter is only relevant for services without a corresponding init script).
=back
=head1 NOTES
Note that this command is not idempotent. L<dh_prep(1)> should be called
between invocations of this command (with the same arguments). Otherwise, it
may cause multiple instances of the same text to be added to maintainer
scripts.
Note that B<dh_systemd_start> should be run after B<dh_installinit> so that it
can detect corresponding SysV init scripts. The default sequence in B<dh> does
the right thing, this note is only relevant when you are calling
B<dh_systemd_start> manually.
=cut
init(options => {
"r" => \$dh{R_FLAG},
"no-restart-on-upgrade" => \$dh{R_FLAG},
"no-start" => \$dh{NO_START},
"R|restart-after-upgrade" => \$dh{RESTART_AFTER_UPGRADE},
"no-also" => \$dh{NO_ALSO},
});
# Extracts the Also= or Alias= line(s) from a unit file.
# In case this produces horribly wrong results, you can pass --no-also, but
# that should really not be necessary. Please report bugs to
# pkg-systemd-maintainers.
sub extract_key {
my ($unit_path, $key) = @_;
my @values;
my $fh;
if ($dh{NO_ALSO}) {
return @values;
}
if (!open($fh, '<', $unit_path)) {
warning("Cannot open($unit_path) for extracting the Also= line(s)");
return;
}
while (my $line = <$fh>) {
chomp($line);
if ($line =~ /^\s*$key=(.+)$/i) {
@values = (@values, shellwords($1));
}
}
close($fh);
return @values;
}
foreach my $package (@{$dh{DOPACKAGES}}) {
my $tmpdir = tmpdir($package);
my @installed_units;
my @units;
my %aliases;
my $oldcwd = getcwd();
find({
wanted => sub {
my $name = $File::Find::name;
return unless -f;
return unless $name =~ m,^$tmpdir/lib/systemd/system/[^/]+$,;
if (-l) {
my $target = abs_path(readlink());
$target =~ s,^$oldcwd/,,g;
$aliases{$target} = [ $_ ];
} else {
push @installed_units, $name;
}
},
}, $tmpdir);
chdir($oldcwd);
# Handle either only the unit files which were passed as arguments or
# all unit files that are installed in this package.
my @args = @ARGV > 0 ? @ARGV : @installed_units;
# This hash prevents us from looping forever in the following while loop.
# An actual real-world example of such a loop is systemd’s
# systemd-readahead-drop.service, which contains
# Also=systemd-readahead-collect.service, and that file in turn
# contains Also=systemd-readahead-drop.service, thus forming an endless
# loop.
my %seen;
# We use while/shift because we push to the list in the body.
while (@args) {
my $name = shift @args;
my $base = basename($name);
# Try to make the path absolute, so that the user can call
# dh_installsystemd bacula-fd.service
if ($base eq $name) {
# NB: This works because @installed_units contains
# files from precisely one directory.
my ($full) = grep { basename($_) eq $base } @installed_units;
if (defined($full)) {
$name = $full;
} else {
warning(qq|Could not find "$name" in the /lib/systemd/system of $package. | .
qq|This could be a typo, or using Also= with a service file from another package. | .
qq|Please check carefully that this message is harmless.|);
}
}
# Skip template service files like e.g. getty@.service.
# Enabling, disabling, starting or stopping those services
# without specifying the instance (e.g. getty@ttyS0.service) is
# not useful.
if ($name =~ /\@/) {
next;
}
# Handle all unit files specified via Also= explicitly.
# This is not necessary for enabling, but for disabling, as we
# cannot read the unit file when disabling (it was already
# deleted).
my @also = grep { !exists($seen{$_}) } extract_key($name, 'Also');
$seen{$_} = 1 for @also;
@args = (@args, @also);
push @{$aliases{$name}}, $_ for extract_key($name, 'Alias');
my @sysv = grep {
my $base = $_;
$base =~ s/\.(?:service|socket)$//g;
-f "$tmpdir/etc/init.d/$base"
} ($base, @{$aliases{$name}});
if (@sysv == 0 && !grep { $_ eq $name } @units) {
push @units, $name;
}
}
next if @units == 0;
# The $package and $sed parameters are always the same.
# This wrapper function makes the following logic easier to read.
my $sd_autoscript = sub {
my ($script, $filename) = @_;
my $unitargs = join(" ", map { basename($_) } @units);
autoscript($package, $script, $filename, "s/#UNITFILES#/$unitargs/");
};
if ($dh{RESTART_AFTER_UPGRADE}) {
$sd_autoscript->("postinst", "postinst-systemd-restart");
} elsif (!$dh{NO_START}) {
# We need to stop/start before/after the upgrade.
$sd_autoscript->("postinst", "postinst-systemd-start");
}
$sd_autoscript->("postrm", "postrm-systemd-reload-only");
if ($dh{R_FLAG} || $dh{RESTART_AFTER_UPGRADE}) {
# stop service only on remove
$sd_autoscript->("prerm", "prerm-systemd-restart");
} elsif (!$dh{NO_START}) {
# always stop service
$sd_autoscript->("prerm", "prerm-systemd");
}
}
=head1 SEE ALSO
L<debhelper(7)>
=head1 AUTHORS
pkg-systemd-maintainers@lists.alioth.debian.org
=cut
|