#!/bin/bash #--------------------------------------------------------------- # Project : Mageia Linux # Module : rpm-helper # File : add-service # Version : $Id$ # Authors : Frederic Lepied, Andrey Borzenkov # Created On : Mon Jul 8 08:14:34 2002 # Purpose : helper script for rpm scriptlets to add a # service. #--------------------------------------------------------------- if [ "x$1" = x--no-sysv ]; then do_sysv=no shift else do_sysv=yes fi if [ $# -lt 3 ]; then echo "usage: $0 [--no-sysv] [] [ ...]" 1>&2 exit 1 fi # What init system are we currently using? if [ -d /run/systemd/system/ ]; then init=systemd else init=sysvinit fi pkg=$1 # name of the package num=$2 # number of packages installed if [ $do_sysv = yes ]; then srv=$3 # name of the SysV script shift 3 else srv= shift 2 fi units="$*" # systemd units units_to_enable= # units enabled by msec systemd_migration_dir=/var/lib/rpm-helper/systemd-migration mkdir -p "${systemd_migration_dir}" USERUNITDIR=/etc/systemd/system RUNTIMEUNITDIR=/run/systemd/system SYSTEMUNITDIR=/lib/systemd/system find_unit() { unit=$(basename "$1") # We need to normalise the systemd unit name as the native unit may not have # the same filename (sans it's .service suffix) as sysvinit script. # In this case, symlinks are used to mask the sysvinit file, but for enabling # and disabling units we must use the official name. searchunit= if [ -L "$USERUNITDIR/$unit" ]; then searchunit=$(/usr/bin/readlink -m "$USERUNITDIR/$unit") elif [ -e "$USERUNITDIR/$unit" ]; then searchunit="$USERUNITDIR/$unit" elif [ -L "$RUNTIMEUNITDIR/$unit" ]; then searchunit=$(/usr/bin/readlink -m "$RUNTIMEUNITDIR/$unit") elif [ -e "$RUNTIMEUNITDIR/$unit" ]; then searchunit="$RUNTIMEUNITDIR/$unit" elif [ -L "$SYSTEMUNITDIR/$unit" ]; then searchunit=$(/usr/bin/readlink -m "$SYSTEMUNITDIR/$unit") elif [ -e "$SYSTEMUNITDIR/$unit" ]; then searchunit="$SYSTEMUNITDIR/$unit" fi if [ -n "$searchunit" ]; then echo -n "$searchunit" fi } # If only a sysvinit service is given, then deal with a systemd unit of the same # name. Specific specs can enable specific unit names as needed but this should # catch the most common usage. if [ -z "$units" ] && [ -n "$srv" ] && [ ! -f "/etc/xinetd.d/$srv" ]; then units="$srv.service" searchunit=$(find_unit $units) if [ -n "$searchunit" ]; then units=$(basename "$searchunit") fi fi add_service() { # Add the service if [ -r /etc/sysconfig/msec ]; then . /etc/sysconfig/msec fi # High security: add only authorized services LIST=/etc/security/msec/server # during the install the symlink isn't done so find the right file # by ourselves if [ -n "$DURING_INSTALL" ] && [ ! -f $LIST ]; then LIST=/etc/security/msec/server.$SECURE_LEVEL fi # This is half-hearted support for msec: we check "srv" for a unit # with name "srv.service". This should account for most(?) common # case when SysV script srv is replaced by single unit srv.service # If SysV name was supplied, we assume units are equivalent and do # not need to be checked. # TODO should msec support full unit name? if [ -f "$LIST" ]; then if [ -n "$srv" ]; then if grep -Fqx "${srv}" "$LIST"; then units_to_enable="$units" else srv= fi elif [ -n "$units" ]; then for i in $units; do [ "$i" != "${i%.service}" ] && ! grep -Fqx "${i%.service}" "$LIST" && continue [ "$i" != "${i%.socket}" ] && ! grep -Fqx "${i%.socket}" "$LIST" && continue [ "$i" != "${i%.path}" ] && ! grep -Fqx "${i%.path}" "$LIST" && continue units_to_enable="$units_to_enable $i" done fi else units_to_enable="$units" fi # Actually do enable/disable foo if [ -n "$units_to_enable" ]; then # Prefer preset (for native systemd units), but fall back to enable (for sysvinit units) /bin/systemctl --quiet preset $units_to_enable >/dev/null 2>&1 || /bin/systemctl --quiet enable $units_to_enable >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "Warning: Problems encountered when activating services." >&2 echo " Please check and enable manually if necessary." >&2 echo " Service units affected: $units_to_enable" >&2 fi if [ -n "$srv" ] && [ ! -f "${systemd_migration_dir}/$srv" ]; then touch "${systemd_migration_dir}/$srv" fi fi # When no native systemd unit exists, the above command will actually # just end up running chkconfig anyway, but if a native systemd unit exists # the legacy init script will not be enabled. # In order to enable switching back ot sysvinit, we should enable the # sysvinit scripts too. if [ -n "$srv" ]; then if [ -f /etc/rc.d/init.d/$srv ] || [ -f /etc/xinetd.d/$srv ]; then /sbin/chkconfig --add $srv if [ -r /etc/sysconfig/system ]; then . /etc/sysconfig/system fi # TODO what to do with system units here? if [ -z "$ADD_SERVICES_TO_CURRENT_PROFILE_ONLY" ]; then # add the service to all the profiles at once if [ -d /etc/netprofile/profiles/default/services ]; then for dir in /etc/netprofile/profiles/*/services; do touch "$dir/$srv" done fi fi fi fi } check_sysvinit_service() { rl=$1 srv=$2 set -- /etc/rc${rl}.d/S??$srv if [ $# -gt 1 ]; then echo 1>&2 "add-service: Error: $srv appears multiple times at runlevel $rl: $*" fi echo -n "$1" } if [ "$num" = 1 ]; then # First install mode if [ "null" != "$units" ]; then add_service fi else # Upgrade mode. reloaded=no # Handle migration to systemd. # If a previously installed package only had a sysvinit script, but an # updated package has a native systemd unit, we need to make sure we migrate # any service enablement for various targets (née runlevels) if [ -n "$srv" ] && [ -n "$units" ]; then if [ ! -f "${systemd_migration_dir}/$srv" ]; then full_path_units= for unit in $units; do [ "null" = "$unit" ] && continue # We need a full path for the symlink. Also it's possible # that $unit contains "foo.service" where foo is actually # a sysvinit script and thus we'll not have anything native. # We only consider a "migration" to have taken place when # we genuinely have a native systemd unit. unit=$(find_unit "$unit") if [ -n "$unit" ]; then full_path_units="$full_path_units $unit" fi done if [ -n "$full_path_units" ]; then enable_targets= # We have not yet migrated this service # First we check in which runlevels the legacy service is enabled # Only bother checking runlevels 1 3 and 5 script=$(check_sysvinit_service 1 "$srv") # NB We only check that the link exists as the old sysvinit # script may have been removed during migration to systemd # native unit. if [ -L "$script" ]; then enable_targets="$enable_targets rescue.target" fi script=$(check_sysvinit_service 3 "$srv") if [ -L "$script" ]; then enable_targets="$enable_targets multi-user.target" else # As graphical.target includes everything in multi-user.target, # we only need to check 5 when 3 does NOT give us a result. script=$(check_sysvinit_service 5 "$srv") if [ -L "$script" ]; then enable_targets="$enable_targets graphical.target" fi fi if [ -n "$enable_targets" ]; then for unit in $full_path_units; do bn_unit="$(basename "$unit")" if grep -qE "^(WantedBy|Alias)=" "$unit"; then if [ x$init = xsystemd ] && [ x$reloaded = xno ]; then /bin/systemctl --system daemon-reload reloaded=yes fi echo 1>&2 "Migrating sysvinit service '$srv' to systemd native unit '$bn_unit' via systemd install rules." /bin/systemctl enable "$bn_unit" elif [[ "$bn_unit" =~ @.service ]]; then echo 1>&2 "Migrating sysvinit service '$srv' to systemd native template unit '$bn_unit': Failed - no install rules" else for enable_target in $enable_targets; do wantsdir="$USERUNITDIR/${enable_target}.wants" mkdir -p "$wantsdir" if [ ! -f "$wantsdir/$bn_unit" ]; then echo 1>&2 "Migrating sysvinit service '$srv' to systemd native unit '$bn_unit' for target '${enable_target}'" ln -s "$unit" "$wantsdir/$bn_unit" reloaded=no fi done fi done fi # It could be that a package is installed but not enabled. # If that is the case, we should still consider it "migrated" # even when we do not enable anything. touch "${systemd_migration_dir}/$srv" elif [ "null" = "$units" ]; then # New package masks the unit be we still consider this a migration echo 1>&2 "Migrating sysvinit service '$srv': Masked under systemd." touch "${systemd_migration_dir}/$srv" fi fi fi if [ "x$init" = xsystemd ]; then # Package install may have changed the unit file, so reload the daemon # before trying to restart anything if [ "x$reloaded" = xno ]; then /bin/systemctl --system daemon-reload fi # There may be template units, so attempt to find all instances and # restart them. for unit in $units; do if [[ "$unit" =~ @.service ]]; then instances=$(/bin/systemctl -a --full list-units | grep -E "${unit%@.service}@[^ ]+.service" | awk '{ print $1 }') if [ -n "$instances" ]; then for iunit in $instances; do /bin/systemctl --quiet try-restart "$iunit" done fi elif [ "null" != "$unit" ]; then /bin/systemctl --quiet try-restart "$unit" fi done elif [ -f "/etc/rc.d/init.d/$srv" ]; then script=$(check_sysvinit_service 3 "$srv"); if [ -f "$script" ]; then /sbin/chkconfig --add "$srv" fi # restart the service if already running if [ -f "/var/lock/subsys/$srv" ]; then /sbin/service "$srv" restart > /dev/null || : fi fi fi # add-service ends here