Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl
- # vim:ts=4:sw=4:expandtab
- # © 2013 Michael Stapelberg <[email protected]>
- #
- # All rights reserved.
- #
- # Redistribution and use in source and binary forms, with or without
- # modification, are permitted provided that the following conditions are met:
- #
- # * Redistributions of source code must retain the above copyright
- # notice, this list of conditions and the following disclaimer.
- #
- # * Redistributions in binary form must reproduce the above copyright
- # notice, this list of conditions and the following disclaimer in the
- # documentation and/or other materials provided with the distribution.
- #
- # * Neither the name of Michael Stapelberg nor the
- # names of contributors may be used to endorse or promote products
- # derived from this software without specific prior written permission.
- # .
- # THIS SOFTWARE IS PROVIDED BY Michael Stapelberg ''AS IS'' AND ANY
- # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- # DISCLAIMED. IN NO EVENT SHALL Michael Stapelberg BE LIABLE FOR ANY
- # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- =head1 NAME
- deb-systemd-invoke - wrapper around systemctl, respecting policy-rc.d
- =head1 SYNOPSIS
- B<deb-systemd-invoke> [B<--user>] start|stop|restart S<I<unit file> ...>
- =head1 DESCRIPTION
- B<deb-systemd-invoke> is a Debian-specific helper script which asks
- /usr/sbin/policy-rc.d before performing a systemctl call.
- B<deb-systemd-invoke> is intended to be used from maintscripts to start
- systemd unit files. It is specifically NOT intended to be used interactively by
- users. Instead, users should run systemd and use systemctl, or not bother about
- the systemd enabled state in case they are not running systemd.
- =cut
- use strict;
- use warnings;
- use Getopt::Long; # in core since Perl 5
- if (@ARGV < 2) {
- print STDERR "Syntax: $0 <action> <unit file> [<unit file> ...]\n";
- exit 1;
- }
- my $is_system = 1;
- my @instances = ();
- my $result = GetOptions(
- "user" => sub { $is_system = 0; },
- "system" => sub { $is_system = 1; }, # default
- );
- my $policyhelper = '/usr/sbin/policy-rc.d';
- if (length $ENV{DPKG_ROOT}) {
- $policyhelper = $ENV{DPKG_ROOT} . $policyhelper;
- }
- my @units = @ARGV;
- my $action = shift @units;
- if (-x $policyhelper) {
- for my $unit (@units) {
- system(qq|$policyhelper $unit "$action"|);
- # 0 or 104 means run
- # 101 means do not run
- my $exitcode = ($? >> 8);
- if ($exitcode == 101) {
- print STDERR "$policyhelper returned 101, not running '" . join(' ', @ARGV) . "'\n";
- exit 0;
- } elsif ($exitcode != 104 && $exitcode != 0) {
- print STDERR "deb-systemd-invoke only supports $policyhelper return codes 0, 101, and 104!\n";
- print STDERR "Got return code $exitcode, ignoring.\n";
- }
- }
- }
- if (!$is_system) {
- # '--machine <ID>@' was added in v250 and v249.10, before that we can't talk to arbitrary user instances
- my $systemctl_version = `systemctl --version --quiet | sed -n -r "s/systemd ([0-9]+) \\(.*/\\1/p"`;
- chomp ($systemctl_version);
- if (system('dpkg', '--compare-versions', $systemctl_version, 'ge', '249') != 0) {
- print STDERR "systemctl version $systemctl_version does not support acting on user instance, skipping\n";
- exit 0;
- }
- # Each user instance of the manager has a corresponding user@<id<.service unit.
- # Get the full list of IDs, so that we can talk to each user instance to start/stop
- # user units.
- @instances = `systemctl --no-legend --quiet list-units 'user@*' | sed -n -r 's/.*user@([0-9]+).service.*/\\1/p'`;
- } else {
- push @instances, 'system';
- }
- # If the job is disabled and is not currently running, the job is not started or restarted.
- # However, if the job is disabled but has been forced into the running state, we *do* stop
- # and restart it since this is expected behaviour for the admin who forced the start.
- # We don't autostart static units either.
- if ($action eq "start" || $action eq "restart") {
- my $global_exit_code = 0;
- my @start_units = ();
- for my $instance (@instances) {
- my @instance_args = ();
- if ($instance eq 'system') {
- push @instance_args, '--system';
- } else {
- chomp ($instance);
- push @instance_args, '--user', '--machine', "$instance@";
- }
- for my $unit (@units) {
- my $unit_installed = 0;
- my $enabled_output = `systemctl @instance_args is-enabled -- '$unit'`;
- # matching enabled and enabled-runtime as an installed non static unit
- if ($enabled_output =~ /enabled/) {
- $unit_installed = 1;
- }
- system('systemctl', @instance_args, '--quiet', 'is-active', '--', $unit);
- my $unit_active = $?>>8 == 0 ? 1 : 0;
- if (!$unit_installed && $action eq "start") {
- print STDERR "$unit is a disabled or a static unit, not starting it.\n";
- } elsif (!$unit_installed && !$unit_active && $action eq "restart") {
- print STDERR "$unit is a disabled or a static unit not running, not starting it.\n";
- }
- else {
- push @start_units, $unit;
- }
- }
- if (@start_units) {
- system('systemctl', '--quiet', @instance_args, $action, @start_units) == 0 or die("Could not execute systemctl: $!");
- }
- }
- exit(0);
- } elsif ($action eq "stop" && !$is_system) {
- my $global_exit_code = 0;
- for my $instance (@instances) {
- chomp ($instance);
- system('systemctl', '--quiet', '--user', '--machine', "$instance@", $action, @units);
- }
- exit(0);
- } else {
- exec('systemctl', @ARGV);
- }
Advertisement
Add Comment
Please, Sign In to add comment