/usr/sbin/aptitude-robot is in aptitude-robot 1.3.3-1.
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 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 | #!/usr/bin/env perl
# vim: set filetype=perl :
use strict;
use warnings;
use 5.010;
use English qw( -no_match_vars );
use Carp;
use autodie;
use Run::Parts;
main() unless caller(0);
sub main {
use Pod::Usage;
use Getopt::Long qw( :config pass_through no_auto_abbrev );
my $help;
my $pass_through_options;
my $show_cmdline;
my $force_install;
my $config_dir = '/etc/aptitude-robot';
GetOptions(
'help' => \$help,
'show-cmdline' => \$show_cmdline,
'force-install' => \$force_install,
'config-dir=s' => \$config_dir,
);
pod2usage('-verbose' => 2, '-exit_status' => 0) if $help;
my $aptitude_robot = Aptitude::Robot::Command->new(
config_dir => $config_dir,
force_install => $force_install,
pass_through_options => \@ARGV,
);
die $aptitude_robot->error_msg() . "\n" if $aptitude_robot->error_msg();
_run_triggers("$config_dir/triggers.pre", $show_cmdline);
my @command = $aptitude_robot->command();
if ($show_cmdline) {
say "'" . join("' '", @command) . "'";
}
else {
system(@command);
if ($CHILD_ERROR == -1) {
die "aptitude failed to execute: $OS_ERROR\n";
}
elsif ($CHILD_ERROR) {
my $exit_code = ($CHILD_ERROR >> 8);
printf STDERR "aptitude exited with value %d\n", $exit_code;
exit $exit_code;
}
}
_run_triggers("$config_dir/triggers.post", $show_cmdline);
}
sub _run_triggers {
return unless @_;
my ($triggers, $show_cmdline) = @_;
if ( -d $triggers ) {
my $rp = Run::Parts->new($triggers);
if ($show_cmdline) {
say $rp->test;
} else {
$rp->run;
}
}
return;
}
BEGIN{
package Aptitude::Robot::Command;
use Moo;
has( 'config_dir' => (
is => 'ro',
required => 1,
)
);
has( 'pass_through_options' => (
is => 'ro',
required => 0,
)
);
has( 'force_install' => (
is => 'rw',
default => sub { return 0; },
)
);
has( 'error_msg' => (
is => 'ro',
init_arg => undef,
default => sub {
my $self = shift;
if ( -d $self->config_dir() . '/pkglist.d/.' ) {
return '';
}
else {
return 'Error: ' . $self->config_dir . ' is not a aptitude-robot config directory';
}
},
)
);
sub command {
my $self = shift;
return () if $self->error_msg();
my %pkg_action = ();
for my $line ($self->run_parts_lines('pkglist.d')) {
my ($action, $pkg) = split(/\s+/, $line, 2);
# ignore extra ':' and '=' entries on force-install
next if
$self->force_install() and
defined($pkg_action{$pkg}) and
($action eq ':' or $action eq '=');
$pkg_action{$pkg} = $action;
}
my @cmd = ( 'aptitude' );
push(@cmd, @{$self->pass_through_options()}) if $self->pass_through_options();
push(@cmd, $self->options(), 'full-upgrade', '~U !~ahold' );
for my $pkg (sort keys %pkg_action) {
push(@cmd, $pkg . $pkg_action{$pkg});
}
return @cmd;
}
sub options {
my $self = shift;
return () if $self->error_msg();
return
_split_parameters($self->run_parts_lines('options.d'));
}
sub run_parts_lines {
my ($self, $parts_dir) = @_;
return () if $self->error_msg();
my $full_path = $self->config_dir() . "/$parts_dir";
return () unless -d $full_path;
my $rp = Run::Parts->new($full_path);
return _clean_comments_and_whitespace( $rp->concat );
}
sub _clean_comments_and_whitespace {
my (@lines) = @_;
for my $line (@lines) {
$line =~ s{\# .* \Z}{}xms; # remove comments
$line =~ s{\A \s+}{}xms; # remove leading space
$line =~ s{\s+ \Z}{}xms; # remove trailing space
}
return grep { $_ ne '' } @lines; # non-empty lines only
}
sub _split_parameters {
my (@lines) = @_;
my @parameters = ();
for my $line (@lines) {
push(@parameters, split(qr(=|\s+), $line, 2));
}
return @parameters;
}
no Moo;
1;
}
__END__
=head1 NAME
aptitude-robot - automate package choice management
=head1 SYNOPSIS
aptitude-robot [options]
aptitude-robot --help
=head1 DESCRIPTION
aptitude-robot uses configuration files to install and remove Debian software
packages automatically. This allows hands-off setup and maintenance of
workstations and servers. Create package lists in a development environment
and copy the package lists over to the production machines. aptitude-robot
will then make sure that the packages mentioned in the lists are installed or
removed as indicated.
=head1 OPTIONS
=over 4
=item B<--force-install>
give priority to install(+), remove(-), and purge(_) actions over keep(:) and hold(=)
=item B<--config-dir F</path/to/config/dir>>
specify an alternate configuration directory. Defaults to F</etc/aptitude-robot>
=item B<--show-cmdline>
only show the command that would be executed
=item B<--help>
Prints this page.
=item I<other options>
any option not recognized by aptitude-robot itself is passed through to
aptitude. The options B<-q> and B<-s> are likely to be used occasionally. See
L<aptitude(8)> for details.
=back
=head1 CONFIGURATION
The configuration directory given by the C<--config-dir> (or
F</etc/aptitude-robot> by default) must contain a directory named F<pkglist.d>.
This directory may have several package list files that are chosen according to
the criteria of L<run-parts(8)>. They are concatenated in the order given by
L<run-parts(8)>.
Each line shall contain an action and a package name separated by white space.
The actions are those used by the C<aptitude> command line interface (see
aptitude documentation). Typically they are:
I<+ package # install package>
I<+M package # install package and mark it as automatically installed>
I<- package # remove package>
I<_ package # purge package>
I<: package # keep package at current version>
I<= package # mark a package as "hold", i.e., prevent automatic updates>
If a package is mentioned several times the last entry will determine the
action. If the C<--force-install> option is given the keep(:) and hold(=)
actions are given lower priority, i.e., the appear only when no other action
for the package is specified.
A C<#> character starts a comment extending to the end of line. Empty lines or
extra white space at the beginning or end of line is ignored.
Optionally the configuration directory may contain a file name F<options>
containing extra options given to aptitude in the form of one option per line.
Optionally the configuration directory may contain two directories
F<triggers.pre> and F<triggers.post> with scripts that are executed by
L<run-parts(8)> before and after aptitude respectively.
=head1 SEE ALSO
L<aptitude(8)>, L<aptitude-robot-session(8)>
=head1 AUTHORS
Elmar S. Heeb <elmar@heebs.ch> and Axel Beckert <abe@debian.org>
=cut
|