diff options
Diffstat (limited to 'perl-install/services.pm')
-rw-r--r-- | perl-install/services.pm | 307 |
1 files changed, 215 insertions, 92 deletions
diff --git a/perl-install/services.pm b/perl-install/services.pm index 7b122b097..a99ef038e 100644 --- a/perl-install/services.pm +++ b/perl-install/services.pm @@ -1,4 +1,4 @@ -package services; # $Id: services.pm 267089 2010-03-28 12:51:44Z tv $ +package services; @@ -11,8 +11,7 @@ use strict; use common; use run_program; -use common; -use run_program; +use File::Basename; sub description { my %services = ( @@ -24,6 +23,7 @@ It can also be used for shutting down the machine when the battery is low."), atd => N_("Runs commands scheduled by the at command at the time specified when at was run, and runs batch commands when the load average is low enough."), 'avahi-deamon' => N_("Avahi is a ZeroConf daemon which implements an mDNS stack"), +chronyd => N_("An NTP client/server"), cpufreq => N_("Set CPU frequency settings"), crond => N_("cron is a standard UNIX program that runs user-specified programs at periodic scheduled times. vixie cron adds a number of features to the basic @@ -50,8 +50,6 @@ many services, including telnet, ftp, rsh, and rlogin. Disabling inetd disables all of the services it is responsible for."), ip6tables => N_("Automates a packet filtering firewall with ip6tables"), iptables => N_("Automates a packet filtering firewall with iptables"), -ipchains => N_("Launch packet filtering for Linux kernel 2.2 series, to set -up a firewall to protect your machine from network attacks."), irqbalance => N_("Evenly distributes IRQ load across multiple CPUs for enhanced performance"), keytable => N_("This package loads the selected keyboard map as set in /etc/sysconfig/keyboard. This can be selected using the kbdconfig utility. @@ -98,7 +96,7 @@ portreserve => N_("Reserves some TCP ports"), postfix => N_("Postfix is a Mail Transport Agent, which is the program that moves mail from one machine to another."), random => N_("Saves and restores system entropy pool for higher quality random number generation."), -rawdevices => N_("Assign raw devices to block devices (such as hard drive +rawdevices => N_("Assign raw devices to block devices (such as hard disk drive partitions), for the use of applications such as Oracle or DVD players"), resolvconf => N_("Nameserver information manager"), routed => N_("The routed daemon allows for automatic IP router table updated via @@ -113,6 +111,7 @@ rwhod => N_("The rwho protocol lets remote users get a list of all of the users logged into a machine running the rwho daemon (similar to finger)."), saned => N_("SANE (Scanner Access Now Easy) enables to access scanners, video cameras, ..."), shorewall => N_("Packet filtering firewall"), +shorewall6 => N_("Packet filtering firewall for IPv6"), smb => N_("The SMB/CIFS protocol enables to share access to files & printers and also integrates with a Windows Server domain"), sound => N_("Launch the sound system on your machine"), 'speech-dispatcherd' => N_("layer for speech analysis"), @@ -130,14 +129,20 @@ xinetd => N_("Starts other deamons on demand."), if ($s) { $s = translate($s); } else { - my $file = find { -e $_ } map { "$::prefix$_/$name" } '/etc/rc.d/init.d', '/etc/init.d', '/etc/xinetd.d'; - $s = cat_($file); - $s =~ s/\\\s*\n#\s*//mg; - $s = - $s =~ /^#\s+(?:Short-)?[dD]escription:\s+(.*?)^(?:[^#]|# {0,2}\S)/sm ? $1 : - $s =~ /^#\s*(.*?)^[^#]/sm ? $1 : ''; - - $s =~ s/#\s*//mg; + my $file = "$::prefix/usr/lib/systemd/system/$name.service"; + if (-e $file) { + $s = cat_($file); + $s = $s =~ /^Description=(.*)/mg ? $1 : ''; + } else { + $file = find { -e $_ } map { "$::prefix$_/$name" } '/etc/rc.d/init.d', '/etc/init.d', '/etc/xinetd.d'; + $s = cat_($file); + $s =~ s/\\\s*\n#\s*//mg; + $s = + $s =~ /^#\s+(?:Short-)?[dD]escription:\s+(.*?)^(?:[^#]|# {0,2}\S)/sm ? $1 : + $s =~ /^#\s*(.*?)^[^#]/sm ? $1 : ''; + + $s =~ s/#\s*//mg; + } } $s =~ s/\n/ /gm; $s =~ s/\s+$//; $s; @@ -146,20 +151,26 @@ xinetd => N_("Starts other deamons on demand."), sub ask_ { my ($in) = @_; my %root_services = ( - N("Printing") => [ qw(cups cupslpd lpr lpd oki4daemon hpoj cups-lpd) ], - N("Internet") => [ qw(httpd boa tux roxen ftp pftp tftp proftpd wu-ftpd pure-ftpdipsec proftpd-xinetd - ipchains iptables ip6tables ipvsadm isdn4linux ibod jabber jabber-icq adsl squid - portsentry prelude nessusd junkbuster radvd cddbp ippl iptoip jail.init) ], - N("File sharing") => [ qw(nfs-common nfs-server nfslock smb nettalk netfs mcserv autofs amd - venus.init auth2.init codasrv.init update.init swat) ], - N("System") => [ qw(usb usbd pcmcia irda xinetd inetd kudzu harddrake apmd sound network xfs - alsa functions halt kheader killall mageia_everytime mageia_firstime - random rawdevices single keytable syslog crond medusa-init portmap rpcbind acon - anacron atd gpm psacct wine acpid numlock jserver sensors mosix bpowerd bpowerfail - fcron powertweak.init ups syslog-ng cvs apcupsd) ], - N("Remote Administration") => [ qw(sshd telnetd telnet rsh rlogin rexec webmin cfd heartbeat ldirectord - iplog mon vncserver netsaint olympusd drakxtools_http) ], -# N("Network Client") => [ qw(ypbind nscd arpwatch fetchmail dnrd_rc diald rsync) ], + N("Printing") => [ qw(cups cupslpd cups-lpd hpoj lpd lpr oki4daemon) ], + + # FIXME: split part of 'Internet' into 'Security' or 'Firewall'? + N("Internet") => [ qw(adsl boa cddbp ftp httpd ibod ip6tables ippl iptables iptoip ipvsadm + isdn4linux jabber jabber-icq jail.init junkbuster mandi nessusd pftp portsentry + prelude proftpd proftpd-xinetd pure-ftpd ipsec radvd roxen shorewall shorewall6 squid + tftp) ], + + N("_: Keep these entry short\nNetworking") => [ qw(network network-auth network-up resolvconf) ], + + N("System") => [ qw(acon acpid alsa anacron apcupsd apmd atd bpowerd bpowerfail crond cvs dm fcron functions + gpm halt harddrake inetd irda jserver keytable kheader killall mageia_everytime + mandrake_firstime mdadm medusa-init messagebus microcode_ctl mosix netconsole numlock partmon + pcmcia portmap powertweak.init psacct + random rawdevices rpcbind sensors single sound syslog syslog-ng ups usb usbd wine xfs xinetd) ], + + N("Remote Administration") => [ qw(cfd drakxtools_http heartbeat iplog ldirectord mon netsaint olympusd rexec + rlogin rsh sshd telnet telnetd vncserver webmin) ], + +# N("Network Client") => [ qw(arpwatch diald dnrd_rc fetchmail nscd rsync ypbind) ], # N("Network Server") => [ qw(named bootparamd ntpd xntpd chronyd postfix sendmail # imap imaps ipop2 ipop3 pop3s routed yppasswdd ypserv ldap dhcpd dhcrelay # hylafax innd identd rstatd rusersd rwalld rwhod gated @@ -200,9 +211,7 @@ sub ask_ { }, get_info => sub { formatLines(description($_[0])) }, interactive_help => sub { - interactive::gtk::display_help($in, - { interactive_help_id => - 'misc-params#drakxid-configureServices' }, $::main_window) }, + interactive::gtk::display_help($in, { interactive_help_id => 'configureServices' }) }, }) or return $l, $on_services; #- no change on cancel. [ grep { $services{$_} } @$l ]; } @@ -210,47 +219,34 @@ sub ask_ { sub ask_standalone_gtk { my ($_in) = @_; my ($l, $on_services) = services(); - my @xinetd_services = map { $_->[0] } @{(services_raw())[1]}; - - require ugtk2; - ugtk2->import(qw(:wrappers :create)); - - my $W = ugtk2->new(N("Services")); - my ($x, $y, $w_popup); - my $nopop = sub { $w_popup and $w_popup->destroy; undef $w_popup }; - my $display = sub { - my ($text) = @_; - $nopop->(); - gtkshow(gtkadd($w_popup = Gtk2::Window->new('popup'), - gtksignal_connect(gtkadd(Gtk2::EventBox->new, - gtkadd(gtkset_shadow_type(Gtk2::Frame->new, 'etched_out'), - gtkset_justify(Gtk2::Label->new($text), 'left'))), - button_press_event => sub { $nopop->() } - )))->move($x, $y) if $text; - }; + my @xinetd_services = map { $_->[0] } xinetd_services(); + + require ugtk3; + ugtk3->import(qw(:wrappers :create)); + + my $W = ugtk3->new(N("Services")); my $update_service = sub { my ($service, $label) = @_; - my $started = -e "/var/lock/subsys/$service"; + my $started = is_service_running($service); $label->set_label($started ? N("running") : N("stopped")); }; - my $b = Gtk2::EventBox->new; - $b->set_events('pointer_motion_mask'); + my $b = Gtk3::EventBox->new; + $b->set_events(${ Gtk3::Gdk::EventMask->new("pointer_motion_mask") }); gtkadd($W->{window}, gtkadd($b, gtkpack_($W->create_box_with_title, - 0, mygtk2::gtknew('Title1', label => N("Services and daemons")), + 0, mygtk3::gtknew('Title1', label => N("Services and daemons")), 1, gtkset_size_request(create_scrolled_window(create_packtable({ col_spacings => 10, row_spacings => 3 }, map { my $service = $_; my $is_xinetd_service = member($service, @xinetd_services); my $infos = warp_text(description($_), 40); $infos ||= N("No additional information\nabout this service, sorry."); - my $label = gtkset_justify(Gtk2::Label->new, 'left'); + my $label = gtkset_justify(Gtk3::Label->new, 'left'); $update_service->($service, $label) if !$is_xinetd_service; - [ gtkpack__(Gtk2::HBox->new(0,0), $_), - gtkpack__(Gtk2::HBox->new(0,0), $label), - gtkpack__(Gtk2::HBox->new(0,0), gtksignal_connect(Gtk2::Button->new(N("Info")), clicked => sub { $display->($infos) })), + [ gtkpack__(Gtk3::HBox->new(0,0), gtkset_tip(Gtk3::Label->new($_), $infos)), + gtkpack__(Gtk3::HBox->new(0,0), $label), - gtkpack__(Gtk2::HBox->new(0,0), gtkset_active(gtksignal_connect( - Gtk2::CheckButton->new($is_xinetd_service ? N("Start when requested") : N("On boot")), + gtkpack__(Gtk3::HBox->new(0,0), gtkset_active(gtksignal_connect( + Gtk3::CheckButton->new($is_xinetd_service ? N("Start when requested") : N("On boot")), clicked => sub { if ($_[0]->get_active) { push @$on_services, $service if !member($service, @$on_services); } else { @@ -258,7 +254,7 @@ sub ask_standalone_gtk { } }), member($service, @$on_services))), map { my $a = $_; - gtkpack__(Gtk2::HBox->new(0,0), gtksignal_connect(Gtk2::Button->new(translate($a)), + gtkpack__(Gtk3::HBox->new(0,0), gtksignal_connect(Gtk3::Button->new(translate($a)), clicked => sub { my $action = $a eq "Start" ? 'restart' : 'stop'; log::explanations(qq(GP_LANG="UTF-8" service $service $action)); @@ -266,19 +262,14 @@ sub ask_standalone_gtk { local $_ = `GP_LANG="UTF-8" service $service $action 2>&1`; s/\033\[[^mG]*[mG]//g; c::set_tagged_utf8($_); $update_service->($service, $label); - $display->($_); })) if !$is_xinetd_service; } (N_("Start"), N_("Stop")) ]; } @$l), [ $::isEmbedded ? 'automatic' : 'never', 'automatic' ]), -1, $::isEmbedded ? -1 : 400), - 0, gtkpack(gtkset_border_width(Gtk2::HBox->new(0,0),5), $W->create_okcancel) + 0, gtkpack(gtkset_border_width(Gtk3::HBox->new(0,0),5), $W->create_okcancel) )) ); - $b->signal_connect(motion_notify_event => sub { my ($w, $e) = @_; - my ($ox, $oy) = $w->window->get_origin; - $x = $e->x+$ox; $y = $e->y+$oy }); - $b->signal_connect(button_press_event => sub { $nopop->() }); $::isEmbedded and gtkflush(); $W->main or return; $on_services; @@ -291,17 +282,39 @@ sub ask { sub _set_service { my ($service, $enable) = @_; - my $script = "/etc/rc.d/init.d/$service"; - run_program::rooted($::prefix, "chkconfig", $enable ? "--add" : "--del", $service); - #- FIXME: handle services with no chkconfig line and with no Default-Start levels in LSB header - if ($enable && cat_("$::prefix$script") =~ /^#\s+chkconfig:\s+-/m) { - run_program::rooted($::prefix, "chkconfig", "--level", "35", $service, "on"); + + my @xinetd_services = map { $_->[0] } xinetd_services(); + + # General Note: We use --no-reload here as this code is sometimes triggered + # from code at boot and reloading systemd during boot is generally a bit + # racy just now it seems. + if (member($service, @xinetd_services)) { + run_program::rooted($::prefix, "chkconfig", "--no-reload", $enable ? "--add" : "--del", $service); # Probably still a bug here as xinet support in chkconfig shells out to /sbin/service.... + } elsif (running_systemd() || has_systemd()) { + # systemctl rejects any symlinked units. You have to enabled the real file + if (-l "/lib/systemd/system/$service.service") { + $service = basename(readlink("/lib/systemd/system/$service.service")); + } else { + $service = $service . ".service"; + } + run_program::rooted($::prefix, "/bin/systemctl", $enable ? "enable" : "disable", "--no-reload", $service); + } else { + my $script = "/etc/rc.d/init.d/$service"; + run_program::rooted($::prefix, "chkconfig", "--no-reload", $enable ? "--add" : "--del", $service); + #- FIXME: handle services with no chkconfig line and with no Default-Start levels in LSB header + if ($enable && cat_("$::prefix$script") =~ /^#\s+chkconfig:\s+-/m) { + run_program::rooted($::prefix, "chkconfig", "--no-reload", "--level", "35", $service, "on"); + } } } sub _run_action { my ($service, $action) = @_; - run_program::rooted($::prefix, "/etc/rc.d/init.d/$service", $action); + if (running_systemd()) { + run_program::rooted($::prefix, '/bin/systemctl', '--no-block', $action, "$service.service"); + } else { + run_program::rooted($::prefix, "/etc/rc.d/init.d/$service", $action); + } } sub doit { @@ -322,43 +335,149 @@ sub doit { } } -sub services_raw() { +sub running_systemd() { + run_program::rooted($::prefix, '/bin/mountpoint', '-q', '/sys/fs/cgroup/systemd'); +} + +sub has_systemd() { + run_program::rooted($::prefix, '/bin/rpm', '-q', 'systemd'); +} + +sub xinetd_services() { local $ENV{LANGUAGE} = 'C'; - my (@services, @xinetd_services); - foreach (run_program::rooted_get_stdout($::prefix, '/sbin/chkconfig', '--list')) { - if (my ($xinetd_name, $on_off) = m!^\t(\S+):\s*(on|off)!) { - push @xinetd_services, [ $xinetd_name, $on_off eq 'on' ]; - } elsif (my ($name, $l) = m!^(\S+)\s+(0:(on|off).*)!) { - push @services, [ $name, [ $l =~ /(\d+):on/g ] ]; - } + my @xinetd_services; + foreach (run_program::rooted_get_stdout($::prefix, '/sbin/chkconfig', '--list', '--type', 'xinetd')) { + if (my ($xinetd_name, $on_off) = m!^\t(\S+):\s*(on|off)!) { + push @xinetd_services, [ $xinetd_name, $on_off eq 'on' ]; + } } - \@services, \@xinetd_services; + @xinetd_services; } -#- returns: +sub _systemd_services() { + local $ENV{LANGUAGE} = 'C'; + my @services; + my %loaded; + # Running system using systemd + log::explanations("Detected systemd running. Using systemctl introspection."); + foreach (run_program::rooted_get_stdout($::prefix, '/bin/systemctl', '--no-legend', '--no-pager', '--full', '--all', 'list-units')) { + if (my ($name) = m!^(\S+)\.service\s+loaded!) { + # We only look at non-template, non-linked service files in /lib + # We also check for any non-masked sysvinit files as these are + # also handled by systemd + if ($name !~ /.*\@$/g && (-e "$::prefix/lib/systemd/system/$name.service" or -e "$::prefix/etc/rc.d/init.d/$name") && ! -l "$::prefix/lib/systemd/system/$name.service") { + push @services, [ $name, !!run_program::rooted($::prefix, '/bin/systemctl', '--quiet', 'is-enabled', "$name.service") ]; + $loaded{$name} = 1; + } + } + } + # list-units will not list disabled units that can be enabled + foreach (run_program::rooted_get_stdout($::prefix, '/bin/systemctl', '--no-legend', '--no-pager', '--full', 'list-unit-files')) { + if (my ($name) = m!^(\S+)\.service\s+disabled!) { + # We only look at non-template, non-linked service files in /lib + # We also check for any non-masked sysvinit files as these are + # also handled by systemd + if (!exists $loaded{$name} && $name !~ /.*\@$/g && (-e "$::prefix/lib/systemd/system/$name.service" or -e "$::prefix/etc/rc.d/init.d/$name") && ! -l "$::prefix/lib/systemd/system/$name.service") { + # Limit ourselves to "standard" targets which can be enabled + my $wantedby = cat_("$::prefix/lib/systemd/system/$name.service") =~ /^WantedBy=(graphical|multi-user).target$/sm ? $1 : ''; + if ($wantedby) { + push @services, [ $name, 0 ]; + } + } + } + } + + @services; +} + +sub _legacy_services() { + local $ENV{LANGUAGE} = 'C'; + my @services; + my $has_systemd = has_systemd(); + if ($has_systemd) { + # The system not using systemd but will be at next boot. This is + # is typically the case in the installer. In this mode we must read + # as much as is practicable from the native systemd unit files and + # combine that with information from chkconfig regarding legacy sysvinit + # scripts (which systemd will parse and include when running) + log::explanations("Detected systemd installed. Using fake service+chkconfig introspection."); + foreach (glob_("$::prefix/lib/systemd/system/*.service")) { + my ($name) = m!([^/]*).service$!; + + # We only look at non-template, non-symlinked service files + if (!(/.*\@\.service$/g) && ! -l $_) { + # Limit ourselves to "standard" targets + my $wantedby = cat_($_) =~ /^WantedBy=(graphical|multi-user).target$/sm ? $1 : ''; + if ($wantedby) { + # Exclude if enabled statically + # Note DO NOT use -e when testing for files that could + # be symbolic links as this will fail under a chroot + # setup where -e will fail if the symlink target does + # exist which is typically the case when viewed outside + # of the chroot. + if (!-l "$::prefix/lib/systemd/system/$wantedby.target.wants/$name.service") { + push @services, [ $name, !!-l "$::prefix/etc/systemd/system/$wantedby.target.wants/$name.service" ]; + } + } + } + } + } else { + log::explanations("Could not detect systemd. Using chkconfig service introspection."); + } + + # Regardless of whether we expect to use systemd on next boot, we still + # need to instrospect information about non-systemd native services. + my $runlevel; + my $on_off; + if (!$::isInstall) { + $runlevel = (split " ", `/sbin/runlevel`)[1]; + } + foreach (run_program::rooted_get_stdout($::prefix, '/sbin/chkconfig', '--list', '--type', 'sysv')) { + if (my ($name, $l) = m!^(\S+)\s+(0:(on|off).*)!) { + # If we expect to use systemd (i.e. installer) only show those + # sysvinit scripts which are not masked by a native systemd unit. + my $has_systemd_unit = systemd_unit_exists($name); + if (!$has_systemd || !$has_systemd_unit) { + if ($::isInstall) { + $on_off = $l =~ /\d+:on/g; + } else { + $on_off = $l =~ /$runlevel:on/g; + } + push @services, [ $name, $on_off ]; + } + } + } + @services; +} + +#- returns: #--- the listref of installed services #--- the listref of "on" services sub services() { - my ($services, $xinetd_services) = services_raw(); - my @l = @$xinetd_services; - if ($::isInstall) { - push @l, map { [ $_->[0], @{$_->[1]} > 0 ] } @$services; + my @services; + if (running_systemd()) { + @services = _systemd_services(); } else { - my $runlevel = (split " ", `/sbin/runlevel`)[1]; - push @l, map { [ $_->[0], member($runlevel, @{$_->[1]}) ] } @$services; + @services = _legacy_services(); } + + my @l = xinetd_services(); + push @l, @services; @l = sort { $a->[0] cmp $b->[0] } @l; [ map { $_->[0] } @l ], [ map { $_->[0] } grep { $_->[1] } @l ]; } - - +sub systemd_unit_exists { + my ($name) = @_; + # we test with -l as symlinks are not valid when the system is chrooted: + -e "$::prefix/lib/systemd/system/$name.service" or -l "$::prefix/lib/systemd/system/$name.service"; +} sub service_exists { my ($service) = @_; - -x "$::prefix/etc/rc.d/init.d/$service"; + -x "$::prefix/etc/rc.d/init.d/$service" or systemd_unit_exists($service); } sub restart ($) { @@ -400,7 +519,11 @@ sub is_service_running ($) { my ($service) = @_; # Exit silently if the service is not installed service_exists($service) or return 1; - run_program::rooted($::prefix, "/etc/rc.d/init.d/$service", '>', '/dev/null', '2>', '/dev/null', "status"); + if (running_systemd()) { + run_program::rooted($::prefix, '/bin/systemctl', '--quiet', 'is-active', "$service.service"); + } else { + run_program::rooted($::prefix, '/sbin/service', $service, 'status'); + } } sub starts_on_boot { |