5. Installation, Bootprozess, Shutdown

5.1. Paketinstallation

Die Installation von Software-Paketen unter eisfair erfolgt durch den Paketmanager (eisman), der sicherstellt, dass das System jederzeit in einem konsistenten Zustand verbleibt. Zu diesem Zweck arbeitet der Paketmanager die folgenden Schritte ab:

  1. Ermittlung aller Abhängigkeiten des zu installierenden Pakets anhand der lokalen Paketdatenbank.

  2. Download aller zur Installation erforderlichen Pakete.

  3. Installation der Pakete in umgekehrter Reihenfolge zu der der Abhängigkeiten.

Falls einer der Schritte nicht vollständig abgearbeitet werden kann, wird der gesamte Installationsprozess abgebrochen.

Bei der Installation eines einzelnen Pakets werden die im Paketarchiv enthaltenen Dateien in das Dateisystem des Rechners übertragen. Optional kann ein Paket eine Reihe von Skripten enthalten, mit deren Hilfe der Paketersteller Einfluss auf den Installations- bzw. auf den Deinstallationsprozess nehmen kann. Dies sind:

  • preinstall.sh: Wird ausgeführt, bevor die eigentliche Installation erfolgt.

  • install.sh: Wird ausgeführt, nachdem die Paketdateien entpackt worden sind.

5.1.1. preinstall.sh

Das optionale Script /tmp/preinstall.sh wird verwendet um das System auf die Installation vorzubereiten, bevor eine eventuell vorhandete ältere Version deinstalliert bzw. bevor das gesamte Paketarchiv der neuen Version entpackt wird. Dazu wird die Datei einzeln aus dem Archiv extrahiert, im Dateisystem unter /tmp abgelegt und dort ausgeführt.

Im Normalfall muss zu diesem Zeitpunkt nicht in den Installationsprozess eingegriffen werden, weshalb dieses Skript bei den meisen Paketen einfach entfallen kann. Es kann jedoch verwendet werden, um beispielsweise die Deinstallationsroutine der bereits installierten Version zu korrigieren oder einzelne Dateien zu sichern.

Der Rückgabewert von preinstall.sh bestimmt, ob die Installation fortgesetzt werden kann oder nicht. Damit der Vorgang fortgesetzt wird, muss das Skript mit dem Exit-Code 0 beendet werden. Tritt jedoch ein Fehler auf, gibt das Skript einen Rückgabewert zurück, der von Null verschieden ist.

Hinweis

In früheren Versionen von eisfair musste das Skript preinstall.sh dazu verwendet werden, eine bereits installierte Version des Pakets zu deinstallieren. Dieser Schritt wird inzwischen jedoch vom Paketmanager durchgeführt und ist daher nicht mehr notwendig.

Warnung

Bei der Ausführung der preinstall.sh sind die Dateien des Pakets noch nicht installiert. Auf Paketbestandteile kann daher nicht zugegriffen werden!

Warnung

Bei der Ausführung von preinstall.sh ist darauf zu achten, dass nur Textausgaben erfolgen, die absolut notwendig zur Information des Anwenders sind. Unter allen Umständen ist darüber hinaus auf interaktive Bestandteile (anykey) zu verzichten!

5.1.2. install.sh

Sofern das Preinstall-Skript nicht durch einem Fehler abgebrochen worden ist, (d.h. ein Rückgabewert von 0 zurückgegeben wurde), wird im nächsten Schritt das komplette Paketarchiv entpackt. Dabei werden alle Dateien relativ zum Root-Verzeichnis / abgelegt und befinden sich anschließend in den Verzeichnissen, in denen sie bereits im Archiv vorhanden waren.

Danach wird - falls vorhanden - das Skript /tmp/install.sh ausgeführt. Dieses Skript dient zur Einrichtung des Pakets auf dem System, was beispielsweise die Anlage von Menüeinträgen, die Initialisierung von Konfigurationsvariablen oder die Übernahme der Konfiguration aus einer zuvor installierten Version beinhaltet.

Hinweis

Falls das Paket keine weitere Einrichtung benötigt, soll das Skript entfallen.

Beispiel für die Installation eines eisfair-Pakets:

#!/bin/sh
# ---------------------------------------------------------------------------
# /tmp/install.sh - foo installation
#
# Creation   :  2009-12-31 starwarsfan
# Last update:  $Id: foo 22527 2010-01-02 16:51:38Z starwarsfan $
#
# Copyright (c) 2001-2019 the eisfair team, team(at)eisfair(dot)org
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# ---------------------------------------------------------------------------

# set package name
package_name=foo

# ---------------------------------------------------------------------------
# Setup step 1
# ---------------------------------------------------------------------------

# ---------------------------------------------------------------------------
# add menu
# ---------------------------------------------------------------------------
/var/install/bin/add-menu     \
        setup.services.menu   \
        setup.services.${package_name}.menu \
        "${package_name}"

# ---------------------------------------------------------------------------
# Create default config
# ---------------------------------------------------------------------------
if [ -f "/etc/config.d/${package_name}" ]
then
    update=true
fi

/var/install/config.d/${package_name}-update.sh


# ---------------------------------------------------------------------------
# Aktivate configuration if necessary
# ---------------------------------------------------------------------------
if "${update:-false}"
then
    /var/install/config.d/${package_name}.sh --quiet

    . /etc/config.d/${package_name}
    if [ "${START_FOO}" = "yes" ]
    then
         /etc/init.d/${package_name} start
    fi
fi

exit 0
# ---------------------------------------------------------------------------
# End
# ---------------------------------------------------------------------------

Warnung

Bei der Ausführung von install.sh ist darauf zu achten, dass nur Textausgaben erfolgen, die absolut notwendig zur Information des Anwenders sind. Unter allen Umständen ist darüber hinaus auf interaktive Bestandteile (anykey) zu verzichten!

5.2. Update von Paketen

Beim Update eines Pakets gibt es mehrere Dinge zu beachten. Besonders ist zu berücksichtigen, dass das Upgrade oftmals nicht von der letzten Version aus erfolgt, sondern dass ein Update auch von einer sehr viel älteren (oder neueren) Version aus durchgeführt werden kann.

In jedem Fall müssen beim Update die Dateien entfernt werden, die von älteren Versionen übrig geblieben sind. Zudem ist es für eisfair-Pakete verpflichtend, dass die Konfiguration der Vorversion übernommen wird. Dabei müssen auch eventuelle Änderungen der Konfiguration (z.B. Hinzufügen und Initialisieren von neuen Variablen) durchgeführt werden.

Zu Entfernen der Vorversion kann ein Deinstallationsskript verwendet werden, wie es weiter unten unter Deinstallieren von Paketen beschrieben ist. An dieser Stelle sei erwähnt, dass im Update-Fall vom Paketmanager das Argument --update an das Skript übergeben wird, um zwischen einer normalen Deinstallation und einem Update unterscheiden zu können. Im zweiten Fall müssen gewisse Bestandteile (z.B. die Konfiguration) von der Deinstallation ausgenommen werden, damit sie der neuen Version später zur Verfügung stehen.

Bei der Übernahme der Konfiguration ist sicherzustellen, dass nach dem Update alle Variablen für die neue Version gültige Werte besitzen. Dabei kann es - wie bei einer Neuinstallation auch - vorkommen, dass neue Variable dazu gekommen sind, die mit einem Standardwert belegt werden müssen. Standardwerte sind dabei aus der Default-Konfiguration zu entnehmen, die in der Datei unter /etc/default.d/ zu finden ist.

Optionen die bereits in einer Vorversion verwendet wurden, sind dagegen mit den Werten zu initialisieren, die von der Vorversion in der Datei unter /etc/config.d/ abgelegt worden sind. Dabei müssen:

  • alte Konfigurationsvariablen, die es in der aktuellen Paketversion nicht mehr gibt, entfernt werden.

  • Konfigurationsvariablen, die sich geändert haben, angepasst werden. (z.B. Umbenennung, Anpassung der Syntax…)

  • Unveränderte Konfigurationsvariablen übernommen werden.

Für diese Übernahme der Konfiguration muss daher ein eigenes Skript erstellt werden, das üblicherweise /var/install/config.d/$package-update.sh genannt wird.

Beispiel für ein Skript zur Übernahme der Konfiguration eines eisfair-Pakets:

#!/bin/sh
# ---------------------------------------------------------------------------
# /var/install/config.d/foo-update.sh - paramater update script
#
# Creation   :  2009-12-31 starwarsfan
# Last update:  $Id: foo-update.sh 2342 2010-01-02 16:51:38Z starwarsfan $
#
# Copyright (c) 2001-2019 the eisfair team, team(at)eisfair(dot)org
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# ---------------------------------------------------------------------------

#exec 2> $(pwd)/foo-update-trace$$.log
#set -x

# include configlib for using printvar
. /var/install/include/configlib

# set package name
package_name=foo

# ---------------------------------------------------------------------------
# Set the default val"us for configuration
# ---------------------------------------------------------------------------
get_defaults()
{
    START_FOO='no'
}

# ---------------------------------------------------------------------------
# Read old configuration and rename old variables
# ---------------------------------------------------------------------------
rename_old_variables()
{
    # read old values
    if [ -f /etc/config.d/${package_name} ]
    then
        /var/install/bin/backup-file --quiet ${package_name}
        . /etc/config.d/${package_name}
    fi
}

# ---------------------------------------------------------------------------
# Write config and default files
# ---------------------------------------------------------------------------
make_config_file()
{
    internal_conf_file=${1}
    {
    # -----------------------------------------------------------------------
    printgpl --conf ${package_name} '2009-12-31' 'starwarsfan'
    # -----------------------------------------------------------------------


    # -----------------------------------------------------------------------
    printgroup 'Basic configuration'
    # -----------------------------------------------------------------------
    printvar 'START_FOO' 'Use: yes or no'

    # -----------------------------------------------------------------------
    printend
    # -----------------------------------------------------------------------

    } > ${internal_conf_file}
    # Set rights
    chmod 0600 ${internal_conf_file}
    chown root ${internal_conf_file}
}

# ---------------------------------------------------------------------------
# Create the check.d file
# ---------------------------------------------------------------------------
make_check_file()
{
    printgpl --check ${package_name} '2009-12-31' 'starwarsfan' \
        >/etc/check.d/${package_name}
    cat >> /etc/check.d/${package_name} <<EOFG
# Variable       OPT_VARIABLE         VARIABLE_N           VALUE
START_FOO      -                -                   YESNO

EOFG

    # Set rights for check.d file
    chmod 0600 /etc/check.d/${package_name}
    chown root /etc/check.d/${package_name}

#    printgpl --check_exp ${package_name} '2009-12-31' 'starwarsfan' \
#        >/etc/check.d/${package_name}.exp
#    cat >> /etc/check.d/${package_name}.exp <<EOFG
#
#
#EOFG

    # Set rights for check.exp file
#    chmod 0600 /etc/check.d/${package_name}.exp
#    chown root /etc/check.d/${package_name}.exp

#    printgpl -check_ext ${package_name} '2009-12-31' 'starwarsfan' \
#        >/etc/check.d/${package_name}.ext
#    cat >> /etc/check.d/${package_name}.ext <<EOFG
#
#
#EOFG

    # Set rights for check.ext file
#    chmod 0600 /etc/check.d/${package_name}.ext
#    chown root /etc/check.d/${package_name}.ext
}

# ---------------------------------------------------------------------------
# main
# ---------------------------------------------------------------------------
main()
{
    get_defaults

    # Write default config file
    make_config_file /etc/default.d/${package_name}

    # Update from old version
    rename_old_variables

    # Write new config file
    make_config_file /etc/config.d/${package_name}

    # Write check.d file
    make_check_file

    exit 0
}

# ---------------------------------------------------------------------------
# call function main
# ---------------------------------------------------------------------------
main "${@}"

# ---------------------------------------------------------------------------
# end
# ---------------------------------------------------------------------------

Je nach Anwendungsfall muss dieses Script natürlich noch um die Behandlung weiterer Fälle wie „Löschen von Variablen“, „Umbenennen von Variablen“ oder ähnlichem erweitert werden.

Es ist zu beachten, das bei array Variablen der erste Eintrag vorhanden sein muss, auch wenn das gesamte array nicht verwendet wird. Dies ist besonders bei Nutzung von joe oder vi an Stelle des ece als Editor relevant.

Hinweis

Falls das Paket einen Dienst enthält, wird dieser während der Deinstallation der Vorversion gestoppt, muss jedoch nach dem Update wieder gestartet werden, falls dies von der Konfiguration vorgegeben ist. Dies erfolgt während der Ausführung von /tmp/install.sh, nachdem die Konfiguration übernommen wurde.

5.2.1. Erweitertes update

Bei Verwendung dieses Beispiels werden die Dateien unter /etc/default.d und /etc/check.d nicht mit ausgeliefert, da diese beim Verarbeiten des $package-update.sh erzeugt werden. Gleichzeitig wird bei den check Dateien mit ‚Here-Documents‘ gearbeitet.

#!/bin/sh
# ---------------------------------------------------------------------------
# /var/install/config.d/eisfax-update.sh - parameter update script
#
# Creation:     2005-05-29 jv
# Last Update:  2006-06-11 hb
#
# Copyright (c) 2001-2019 the eisfair team, team(at)eisfair(dot)org
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# ---------------------------------------------------------------------------


#exec 2>/public/eisfax-update-trace$$.log
#set -x

package_name=eisfax

# include configlib for using printvar
. /var/install/include/configlib
. /var/lib/eisfax/eisfax.info

# ---------------------------------------------------------------------------
# Set the default values for configuration
# ---------------------------------------------------------------------------
get_defaults()
{
    START_EISFAX='no'

    EISFAX_COUNTRY_CODE='49'
    EISFAX_AREAa_CODE='40'
    EISFAX_LONG_DISTANCE_PREFIX='0'
    EISFAX_INTERNATIONAL_PREFIX='00'
    EISFAX_MAX_DIALS='6'
    EISFAX_ADMIN_USER_FAX_PASSWD=''
    EISFAX_SAMBA_PRINTER_AUTO='yes'

    EISFAX_ANALOG_USE='no'

    EISFAX_ANALOG_N='1'

    EISFAX_ANALOG_1_NaME=''
    EISFAX_ANALOG_1_ACTIVE='no'
    EISFAX_ANALOG_1_DEVICE='ttyS0'
    EISFAX_ANALOG_1_FAaX_PRINTER_NAME='EISFAX'
    EISFAX_ANALOG_1_CONFIGURE_AUTO='yes'
    EISFAX_ANALOG_1_ID='+49.40.12345678'
    EISFAX_ANALOG_1_LOCaL_IDENTIFIER='Fax-Station'
    EISFAX_ANALOG_1_SERVER_NaME='EISFAX Server'
    EISFAX_ANALOG_1_FAX_HEADER='von %%l %%n an %%d Seite %%P von %%T /'
    EISFAX_ANALOG_1_HEAaDER_DaTE='%F %R'
    EISFAX_ANALOG_1_RINGS_BEFORE_ANSWER='1'
    EISFAX_ANALOG_1_SPEAKER_VOLUME='off'
    EISFAX_ANALOG_1_SND='yes'
    [...]
}

# ---------------------------------------------------------------------------
# Read old configuration and rename old variables
# ---------------------------------------------------------------------------
rename_old_variables()
{
    # read old values
    if [ -f /etc/config.d/${package_name} ]
    then
        /var/install/bin/backup-file --quiet ${package_name}
        . /etc/config.d/${package_name}
    fi

}

# ---------------------------------------------------------------------------
# Write config and default files
# ---------------------------------------------------------------------------
make_config_file()
{
    internal_conf_file=${1}
    {
    # -----------------------------------------------------------------------
    printgpl --conf ${package_name} '2005-06-26' 'hb'
    # -----------------------------------------------------------------------

    # -----------------------------------------------------------------------
    printgroup 'Basic configuration'
    # -----------------------------------------------------------------------

    printvar 'START_EISFAX'
    printcomment            'Start EISFAX server'

    printvar 'EISFAX_COUNTRY_CODE'
    printcomment            ''

    printvar 'EISFAX_AREA_CODE'
    printcomment            ''

    printvar 'EISFAX_LONG_DISTANCE_PREFIX'
    printcomment            ''

    printvar 'EISFAaX_INTERNATIONAL_PREFIX'
    printcomment            ''

    printvar 'EISFAX_MAX_DIALS'
    printcomment            'Wieviele Wahlwiederholungen'
    printcomment            'ausgefuehrt werden sollen'

    printvar 'EISFAX_ADMIN_USER_FAX_PASSWD'
    printcomment            'Passwd for admin-user fax'

    printvar 'EISFAX_SAMBA_PRINTER_AUTO'
    printcomment            'Soll EISFAX die Samba config'
    printcomment            'aufrufen: yes or no'

    # -----------------------------------------------------------------------
    printgroup 'ANALOG settings'
    # -----------------------------------------------------------------------

    printvar 'EISFAX_ANALOG_USE'
    printcomment            'Use: yes or no'

    printvar 'EISFAX_ANALOG_N'
    printcomment            'number of modems'

    # begin EISFAX_ANALOG_N
    idx=1

    while [ ${idx} -le ${EISFAX_ANALOG_N} ]
    do

        # section marker EISFAX_ANALOG_N
        if [ ${idx} -le  ${EISFAX_ANALOG_N} ]
        then
            # ---------------------------------------------------------------
            printgroup 'EISFAX_ANALOG_'${idx}
            # ---------------------------------------------------------------
        fi

        printvar 'EISFAX_ANALOG_'${idx}'_NAME'
        printcomment        "Use a name what ever you want, it's only for you"

        printvar 'EISFAX_ANALOG_'${idx}'_ACTIVE'
        printcomment        'Use only: yes or no'

        printvar 'EISFAX_ANALOG_'${idx}'_DEVICE'
        printcomment        'ttyS0 or ttyS1 or ttyS2'

        printvar 'EISFAX_ANALOG_'${idx}'_FaX_PRINTER_NAME'
        printcomment        'Please, look at the Doku'

        printvar 'EISFAX_ANALOG_'${idx}'_CONFIGURE_AUTO'
        printcomment        'Use: yes or no or scratch'

        printvar 'EISFAX_ANALOG_'${idx}'_ID'
        printcomment        'Your Fax-ID (+49.40.12345678)'

        printvar 'EISFAX_ANALOG_'${idx}'_LOCAL_IDENTIFIER'
        printcomment        'Fax_Station name (fax header)'

        printvar 'EISFAX_ANALOG_'${idx}'_SERVER_NAME'
        printcomment        'EISFAX Server'

        printvar 'EISFAX_ANALOG_'${idx}'_FAX_HEADER'
        printcomment        'von %%l %%n an %%d Seite %%P von %%T /'

        printvar 'EISFAX_ANALOG_'${idx}'_HEADER_DATE'
        printcomment        '%F %R'

        printvar 'EISFAX_ANALOG_'${idx}'_RINGS_BEFORE_ANSWER'
        printcomment        '1'

        printvar 'EISFAX_ANALOG_'${idx}'_SPEAKER_VOLUME'
        printcomment        'off, quiet, low, medium, high'

        printvar 'EISFAX_ANALOG_'${idx}'_SND'
        printcomment        'Use: yes or no'

        [...]

    # end EISFAX_ANALG_N
    idx=$((${idx} + 1))
    done

    # -----------------------------------------------------------------------
    printend
    # -----------------------------------------------------------------------

    } > ${internal_conf_file}
    # Set rights
    chmod 0600 ${internal_conf_file}
    chown root ${internal_conf_file}
}

# ---------------------------------------------------------------------------
# Create the check.d file
# ---------------------------------------------------------------------------
make_check_file()
{
    printgpl --check ${package_name} '2005-06-26' 'jv' \
        >/etc/check.d/${package_name}
    cat >>/etc/check.d/${package_name} <<EOF
# Variable                          OPT_VARIABLE             VARIABLE_N        VALUE
START_EISFAX                        -                        -                 YESNO

EISFAX_COUNTRY_CODE                 START_EISFAX             -                 EISFAX_COUNTRYC
EISFAX_AREA_CODE                    START_EISFAX             -                 NONE
EISFAX_LONG_DISTANCE_PREFIX         START_EISFAX             -                 ENUMERIC
EISFAX_INTERNATIONAL_PREFIX         START_EISFAX             -                 ENUMERIC
EISFAX_MAX_DIALS                    START_EISFAX             -                 NUMERIC
EISFAX_ADMIN_USER_FAX_PASSWD        START_EISFAX             -                 NOTEMPTY
EISFAX_SAMBA_PRINTER_AUTO           START_EISFAX             -                 YESNO

EISFAX_ANALOG_USE                   START_EISFAX             -                 YESNO

EISFAX_ANALOG_N                     EISFAX_ANALOG_USE        -                 NUMERIC
EISFAX_ANALOG_%_NAME                EISFAX_ANALOG_USE        EISFAX_ANALOG_N   NONE
EISFAX_ANALOG_%_ACTIVE              EISFAX_ANALOG_USE        EISFAX_ANALOG_N   YESNO
EISFAX_ANALOG_%_DEVICE              EISFAX_ANALOG_%_ACTIVE   EISFAX_ANALOG_N   NOTEMPTY
EISFAX_ANALOG_%_FAX_PRINTER_NAME    EISFAX_ANALOG_%_ACTIVE   EISFAX_ANALOG_N   EISFAX_SPRINTER_ERR
EISFAX_ANALOG_%_FAX_PRINTER_NAME    EISFAX_ANALOG_%_ACTIVE   EISFAX_ANALOG_N   WARN_EISFAX_SPRINTER_WARN
EISFAX_ANALOG_%_CONFIGURE_AUTO      EISFAX_ANALOG_%_ACTIVE   EISFAX_ANALOG_N   EISFAX_CONFIGURE
EISFAX_ANALOG_%_ID                  EISFAX_ANALOG_%_ACTIVE   EISFAX_ANALOG_N   NOTEMPTY
EISFAX_ANALOG_%_LOCAL_IDENTIFIER    EISFAX_ANALOG_%_ACTIVE   EISFAX_ANALOG_N   NOTEMPTY
EISFAX_ANALOG_%_SERVER_NAME         EISFAX_ANALOG_%_ACTIVE   EISFAX_ANALOG_N   NOTEMPTY
EISFAX_ANALOG_%_FAX_HEADER          EISFAX_ANALOG_%_ACTIVE   EISFAX_ANALOG_N   NOTEMPTY
EISFAX_ANALOG_%_HEADER_DATE         EISFAX_ANALOG_%_ACTIVE   EISFAX_ANALOG_N   NOTEMPTY
EISFAX_ANALOG_%_RINGS_BEFORE_ANSWER EISFAX_ANALOG_%_ACTIVE   EISFAX_ANALOG_N   NUMERIC
EISFAX_ANALOG_%_SPEAKER_VOLUME      EISFAX_ANALOG_%_ACTIVE   EISFAX_ANALOG_N   EISFAX_SVOLUME
EISFAX_ANALOG_%_SND                 EISFAX_ANALOG_%_ACTIVE   EISFAX_ANALOG_N   YESNO
[...]
EOF

    # Set rights for check.d file
    chmod 0600 /etc/check.d/${package_name}
    chown root /etc/check.d/${package_name}


    printgpl --check_exp ${package_name} '2005-06-26' 'jv' \
        >/etc/check.d/${package_name}.exp
    cat >>/etc/check.d/${package_name}.exp <<EOF
EISFAX_USER          = '([-,_[:lower:]0-9])+'
                     : 'no valid user name, because only the following charctershare allowed: a-z, 0-9, ., _ and -'
EISFAX_COUNTRYC      = '(RE:NUMERIC)(RE:NUMERIC)'
                     : 'Use numeric country code: 00 ... 99'
EISFAX_FTYPE         = '()|pdf|tif|ps|png'
                     : 'Use only: pdf, tif, ps or png'
EISFAX_RFTYPE        = 'pdf|tif|ps'
                     : 'Use only: pdf, tif, or ps'
EISFAX_RSEND         = '()|no|faxmaster|(RE:MAILADDR)|(RE:EISFAX_USER)'
                     : 'Use only: no or faxmaster or e-mail address'
EISFAX_FMASTER     = 'yes|no|errors'
                     : 'Use only: yes, no, errors'
EISFAX_SVOLUME       = 'off|quiet|low|medium|high'
                     : 'Use only: off, quiet, low, medium or high'
EISFAX_PQUEUE        = 'pr[1-3]|repr[1-9]?[0-9]|usbpr[1-9]?[0-9]'
                     : 'Use only: pr1, pr2, pr3, repr1 ... repr99, usbpr1 ... usbpr99'
[...]
EOF

    # Set rights for check.exp file
    chmod 0600 /etc/check.d/${package_name}.exp
    chown root /etc/check.d/${package_name}.exp


    printgpl --check_ext ${package_name} '2005-08-31' 'hb' \
        >/etc/check.d/${package_name}.ext
    cat >>/etc/check.d/${package_name}.ext <<EOF
if ( EISFAX_ANALOG_use == "yes" && EISFAX_isdn_use == "yes" )
   then
   error "Either EISFAX_ANALOG_USE _or_ EISFAX_ISDN_USE can be 'yes' "
fi

EOF

    # Set rights for check.ext file
    chmod 0600 /etc/check.d/${package_name}.ext
    chown root /etc/check.d/${package_name}.ext
}

# ---------------------------------------------------------------------------
# main
# ---------------------------------------------------------------------------
main()
{
    get_defaults

    # write default config file
    make_config_file /etc/default.d/${package_name}

    # update from old version
    rename_old_variables

    # write new config file
    make_config_file /etc/config.d/${package_name}

    # write check.d file
    make_check_file

    exit 0
}

# ---------------------------------------------------------------------------
# call function main
# ---------------------------------------------------------------------------
main "${@}"

# ---------------------------------------------------------------------------
# end
# ---------------------------------------------------------------------------

5.3. Dateiliste $package-files.txt

Jedes Paket hat eine Datei mitzuführen, die eine Liste der enthaltenen Dateien enthält und unter dem Namen /etc/filelist.d/$package-files.txt abzulegen ist. Diese Liste kann zum einen dazu verwendet werden, um zu prüfen ob das Paket vollständig auf einem System installiert ist. Zum anderen kann die Deinstallation des Pakets anhand der Dateiliste erfolgen.

Die Datei ist wie folgt aufgebaut:

Filetype      b = Binaer,
              u = Unix-Text,
              s = symbolischer Link,
              h = harter Link,
              f = Ordner
Rights        Zugriffsrechte
User          Benutzer
Group         Gruppe
Package       Paketname
File          Datei mir relativem Verzeichnis

Beispiel:

# -----------------------------------------------------------------------
# foo-files.txt - list of all files of package 'foo'
#
# Creation:     2004-11-17 jv
# Last update:  2006-05-30 max
# -----------------------------------------------------------------------
u 0755 root root foo tmp/install.sh
u 0755 root root foo tmp/preinstall.sh
b 0755 root root foo usr/bin/foorun
b 0644 root root foo usr/lib/foo.so.0.6.7
s 0777 root root foo usr/lib/foo.so.0
u 0644 root root foo usr/share/UDF/foosql.sql
u 0644 root root foo usr/share/doc/foo/changes.txt
u 0644 root root foo usr/share/doc/foo/foo.txt
#
f 0755 root root foo usr/share/UDF
f 0755 root root foo usr/share/doc/foo
f 0755 root root foo usr/share/doc
f 0755 root root foo usr/share
f 0755 root root foo var/lib/foo
f 0755 root root foo usr/lib
f 0755 root root foo usr/bin
f 0755 root root foo tmp

Hinweis

Es sind alle Ordner innerhalb des Archivs mit dem Dateityp ‚f‘ aufzuführen, damit bei der Deinstallation neben den Dateien auch die Ordner gelöscht werden können. Falls Ordner betroffen sind, die nicht entfernt werden können, ohne die Funktion des Systems zu beeinträchtigen, wird dies vom Paketmanager abgefangen.

Die Reihenfolge der Einträge innerhalb der Dateiliste ist beliebig.

5.4. Deinstallieren von Paketen

Die Deinstallation von Paketen wird vom Paketmanager anhand der oben beschriebenen Dateiliste vorgenommen.

Optional kann ein Paket ein Skript (/var/install/deinstall/$package) mitbringen, das vor der eigentlichen Deinstallation vom Paketmanager aufgerufen wird. Es dient dazu, alle die Dateien und Einträge vom System zu entfernen, die von dem Paket angelegt wurden, jedoch nicht in der Dateiliste stehen. Unter anderem sind hier - sofern das für das jeweilige Paket relevant ist - die folgenden Aktionen durchzuführen:

  • Anhalten von Diensten.

  • Löschen der Konfigration, inklusive der Sicherungskopien, der Standardkonfiguration und der Check-Datei (falls nicht in der Dateiliste enthalten).

  • Löschen von Start-/Stop-Skripten inklusive der symbolischen Links (falls diese nicht in der Dateiliste enthalten sind).

  • Entfernen von Einträge aus dem Menü.

  • Entfernen von Cronjobs.

  • Entfernen von paketspezifischen Logdateien.

  • Entfernen von Datenbeständen, die nicht in der Dateiliste enthalten sind.

Nicht entfernt werden dürfen im allgemeinen:

  • Benutzer und Benutzergruppen, sofern es noch Dateien gibt, die diesen gehören. Die Accounts sind in diesem Fall zu sperren.

  • Dateien von Anwendern.

Falls ein Paket gegen eine neuere Version ausgetauscht werden soll (Update), wird vom Paketmanager das bereits installierte Paket deinstalliert und anschließend die neue Version installiert. In diesem speziellen Fall wird dem Deinstallationsskript beim Aufruf das Argument --update übergeben, was i.d.R. die folgenden Auswirkungen hat:

  • Die Konfigurationsdatei unter /etc/config.d inklusive der Sicherungskopien muss erhalten bleiben.

  • Die Verlinkung von Menüeinträgen wird nicht entfernt (damit die Reihenfolge der Menüeinträge erhalten bleibt).

Hinweis

Falls ein Paket lediglich aus einer Sammlung von Dateien besteht und keine weitere Intelligenz besitzt, wie das beispielsweise bei Bibliotheken der Fall ist, kann (und sollte) das Deinstallationsskript entfallen.

Hinweis

In früheren Versionen von eisfair war die Deinstallation von Paketdateien aus der Dateiliste durch das Deinstallationsskript erforderlich. Das ist nicht länger der Fall. Entsprechende Löschroutinen sollten aus Altpaketen entfernt werden.

Beispiel für ein Skript zur Übernahme der Konfiguration eines eisfair-Pakets:

#!/bin/sh
# ---------------------------------------------------------------------------
# /var/install/deinstall/foo - deinstall script
#
# Creation   :  2009-12-31 starwarsfan
# Last update:  $Id: foo 22527 2010-01-02 16:51:38Z starwarsfan $
#
# Copyright (c) 2001-2019 the eisfair team, team(at)eisfair(dot)org
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# ---------------------------------------------------------------------------

# Set package name
package_name=foo

# Set filelist
filelist=/etc/filelist.d/foo-files.txt

# Check if this is an update
if [ "${1}" = "--update" ]
then
    update=true
fi

# ---------------------------------------------------------------------------
# stop deamon
# ---------------------------------------------------------------------------
/etc/init.d/${package_name} stop

# ---------------------------------------------------------------------------
# remove start script and links
# ---------------------------------------------------------------------------
rm -f /etc/rc2.d/S??${package_name}
rm -f /etc/rc2.d/K??${package_name}

# ---------------------------------------------------------------------------
# Check files and default config must be removed separately because they
# are not on the file list.
# ---------------------------------------------------------------------------
rm -f /etc/check.d/foo
rm -f /etc/check.d/foo.*
rm -f /etc/default.d/foo*

# ---------------------------------------------------------------------------
# Stop remove for update only
# ---------------------------------------------------------------------------
if "${update:-false}"
then
    exit 0
fi

# ---------------------------------------------------------------------------
# Remove package from menu system / remove all menu and config files
# ---------------------------------------------------------------------------
/var/install/bin/del-menu   \
        setup.services.menu \
        setup.services.foo.menu

# ---------------------------------------------------------------------------
# Remove config file
# ---------------------------------------------------------------------------
rm -f /etc/config.d/foo
rm -f /etc/backup.d/foo.*

# ---------------------------------------------------------------------------
# Remove deinstall script
# ---------------------------------------------------------------------------
rm -f /var/install/deinstall/foo

exit 0
# ---------------------------------------------------------------------------
# end
# ---------------------------------------------------------------------------

5.5. Bootprozess und Shutdown

Wie bei Linux üblich werden im Rahmen des Systemstarts die einzelnen Dienste über Start-/Stop-Skripte („Init-Script“) im Verzeichnis /etc/init.d/ gestartet und beim Shutdown wieder beendet.

Um diesen Mechanismus nutzen zu können, benötigt man als erstes das Init-Skript namens /etc/init.d/$package. Dieses muss mehrere Startparameter verstehen –zumindest start zum Starten des Dienstes sowie stop zum Stoppen des Dienstes. Auch sollte es den Parameter ‚– quiet‘ verstehen, damit beim Aufruf mit diesem Parameter die ‚echo‘ Ausgaben auf die Console unterdrückt werden.

Um nun festzulegen, dass ein Dienst gestartet werden soll, und an welcher Stelle im Startprozess dies geschehen soll, muss dieses Skript unter /etc/rc2.d/Snn$package verlinkt werden.

Anstatt rc2.d können dabei je nach Runlevel die Verzeichnisse rc0.d, rc2.d, rc6.d und/oder rcS.d in Frage kommen, wobei für die meisten Serverdienste wohl nur Runlevel 2 relevant ist.

Die Startposition wird dabei numerisch direkt hinter dem S angegeben und ist oben mit nn symbolisiert. Die niedrigen Nummern werden dabei für die für den Serverbetrieb nötigen Funktionen (z.B. SCSI-Treiber, Netzwerktreiber + Einstellungen) verwendet. Bei der Auswahl der Startposition für das eigene Paket ist darauf zu achten, dass es sich harmonisch in die Startreihenfolge einfügt.

ANALOG dazu wird das selbe Skript unter /etc/rc2.d/Kmm$package verlinkt, um das Beenden des Dienstes beim Shutdown zu steuern. Hier ist darauf zu achten, dass unkritische Dienste als erstes beendet werden.

Warnung

Grundsatz: Die Summe der Start- und Stopposition muss immer 100 ergeben.

Bemerkung

Während der Link /etc/rc2.d/Kmm$package zum Beenden des Dienstes praktisch immer existiert, wird der Link /etc/rc2.d/Smm$package nur dann angelegt, wenn der Dienst in der Konfiguration aktiviert wurde.

Das Skript /etc/init.d/functions stellt die Funktionen wie sie im Nachfolgenden Beispiel benutzt werden bereit. Beispiel für ein Init-Script:

#!/bin/sh
# ---------------------------------------------------------------------------
# /etc/init.d/foo - init script for foo
#
# Creation:     2005-05-12  max
# Last Update:  2005-07-20  fabian
#
# Copyright (c) 2001-2019 the eisfair team, team(at)eisfair(dot)org
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# ---------------------------------------------------------------------------

# include functions
. /etc/init.d/functions

# include configuration
. /etc/config.d/foo


NAME=foo
DEAMON=/usr/bin/${NAME}
FOO_PIDFILE=/run/foo.pid

# ---------------------------------------------------------------------------
# usage
# ---------------------------------------------------------------------------
usage()
{
cat <<EOF

Usage:
${0}
                -q, --quiet      suppress all normal output
                [start]
                [stop]
                [status]
                [restart]

EOF
}

# ---------------------------------------------------------------------------
# start foo
# ---------------------------------------------------------------------------
foo_start()
{
    pidofproc -p ${FOO_PIDFILE} -s ${DAEMON}
    case ${?} in
    0)
        boot_mesg " * Foo is already running ..."
        echo_warning
        exit 0
        ;;
    1)
        /usr/bin/rm -f ${FOO_PIDFILE}
        ;;
    esac

    boot_mesg " * Starting foo ..."
    loadproc ${DAEMON}
}

# ---------------------------------------------------------------------------
# stop foo
# ---------------------------------------------------------------------------
foo_stop()
{
    pidofproc -p ${FOO_PIDFILE} -s ${DAEMON}
    if [ "${?}" -eq "3" -a "$(tty)" = "/dev/console" ]
    then
        _mesg=false
    fi

    if ${_mesg:-true}
    then
        boot_mesg ' * Stopping Foo daemon ...'
    fi

    killproc -p ${FOO_PIDFILE} ${DAEMON}
}

# ---------------------------------------------------------------------------
# restart foo
# ---------------------------------------------------------------------------
foo_restart()
{
    foo_stop
    foo_start
}

# ---------------------------------------------------------------------------
# status foo
# ---------------------------------------------------------------------------
foo_status()
{
    statusproc ${DAEMON}
}

#----------------------------------------------------------------------------
# main
#----------------------------------------------------------------------------

while [ ${#} -gt 0 ]
do
    case "${1}" in
        -q|--quiet)
            _quiet=true
            shift
        ;;
        *)
            _action=${1}
            shift
        ;;
    esac
done


case "${_action}" in
    start)
        foo_start
    ;;
    stop)
        foo_stop
    ;;
    restart)
        foo_stop
        foo_start
    ;;
    status)
        foo_status
    ;;
    *)
        usage
        exit 1
    ;;
esac

exit 0

Im Beispiel ist neben den oben bereits erklärten Parametern start und stop der Parameter restart aufgeführt, der für die Verarbeitung einer Konfiguartionsänderung notwendig ist und im weiteren Verlauf dieser Dokumentation noch näher erklärt wird.

Hinweis

Es muss garantiert sein, dass der Dienst im init.d-Script startbar ist, auch wenn START_FOO auf no gesetzt ist.

Als weiteres Startskript gibt es /etc/init.d/boot.$package. Dieses Skript dient zum Aufräumen vor dem eigentlichen Starten des Dienstes und wird vor den Init-Skripten beim Systemstart ausgeführt.

Für dieses Skript ist ANALOG ein Link /etc/init.d/boot.d/Snn$package zur Festlegung der Startposition zu erstellen. auch dieses Skript wird mit dem Parameter start aufgerufen.

Hier können z.B. übriggebliebene temporäre Dateien oder auch eventuell veränderte Zugriffsrechte einer Datei oder eines Verzeichnisses korrigiert werden.