Benutzer-Werkzeuge

Webseiten-Werkzeuge


 [[anwenderwiki:usr2amp_thoschi]] 

Inhaltsverzeichnis

Einleitung

Es kann notwendig sein, einzelnen oder mehreren Benutzern zu ermöglichen, eine Webseite zu erstellen oder mit einer Datenbank zu arbeiten.

Da z.B. bei uns regelmäßig wechselnde Informatik-Kurse mit MySQL arbeiten, könnte man dies natürlich über lokale bzw. separate xAMP-Server realisieren.

Das folgende Skript ermöglicht eine Alternative. Es legt für bestimmte Benutzer ein Verzeichnis in dessen Home an und gibt dieses im LAN oder global frei. Gleichzeitig wird für diesen Benutzer ein MySQL-Nutzer eingerichtet und eine Datenbank seines Namens.

Man kann eine Nutzerliste sowohl als Textdatei oder ein sophomorix-Projekt übergeben. Daneben ist auch die manuelle Pflege der Benutzer möglich. Falls man mit Liste oder Projekt synchronisiert, kann man nur die (zusäzlichen) Nutzer anlegen oder nur die (nicht auf der Liste stehenden) Benutzer löschen. Außerdem ist eine vollständige Synchronisation mit einer Liste möglich.

Damit sich diese Liste nicht mit vorhandenen Systembenutzern beißt, kann zum einen ein Präfix vergebene werden, welches diese Nutzer kennzeichnet (standardmäßig lmn_), zum anderen können im Skript bestimmte Benutzernamen in einem Array für die Bearbeitung ausgeschlossen werden.

Neben dem Standard-Betriebsmodus „lmn“, der für die Benutzer auf Sophomorix zurückgreift, gibt es einen Modus „sys“, der mit lokalen Linux-Benutzern arbeitet. Damit ist dieses Skript auch auf externen Servern einsetzbar.

Die Benutzer-Webseiten können so eingeschränkt werden, dass sie nur am lokalen Rechner, nur vom LAN oder von beliebigen Rechnern (also bei Erreichbarkeit von außen auch über das Internet) erreichbar sind.

Das Skript ist noch Beta und steht hier vor allem als Basis für Rückmeldungen und für den Fall, dass sich jemand Teile der Bash-Befehle herauskopieren mag.

Funktionsweise

Aufgerufen wird das Skript entweder ohne Parameter (manuelle Bearbeitung der Benutzer) oder mit den Parametern -f <Dateiname> (Textdatei, jede Zeile ein Nutzer) bzw. -p <Projekt> (Sophomorix-Projekt). In den beiden letzteren Fällen stehen weitere Menüpunkt für die Synchronisierung zur Verfügung.

Zunächst erstellt das Skript die aktuelle Nutzerliste und - falls übergeben - eine Liste der übergebenen Datei bzw. dem Projekt. Diese werden dann verglichen.

Das diff wird dann abgearbeitet. Beim Anlegen wird jeweils: * eine conf-Datei für Apache erstellt (mit den gewünschten Berechtigungen) * ein HTML-Verzeichnis im Home der Benutzer erstellt (und mit den passenden Rechten versehen) * ein Datenbankbenutzer (im lmn-Modus mit dem sophomorix-Initialpasswort) erstellt * eine Datenbank mit dem Namen des Benutzers erstellt, für welche der Nutzer alle Rechte besitzt

Beim Löschen wird jeweils: * der HTML-Ordner NICHT gelöscht (das kann der Benutzer selbst tun) * der Datenbank-Benutzer gelöscht * die Datenbank auf Nachfrage gesichert und im Anshluss gelöscht. Das Backup wird ggf. im Home des Benutzers (mit Timestamp) gespeichert. Falls das Skript beim Anlegen eines Nutzers Backups findet, können diese sowohl vom Benutzer (z.B. per phpmyadmin) als auch vom Skript (per Auswahlmenü) eingelesen werden.

Das Skript versucht, fehlerhafte Eingaben/leere Liste, etc. abzufangen. Es kann aber sein, dass das nicht überall konsequent genug erfolgt. Bei Fehlern bitte eine Nachricht über die Liste oder im Forum - oder einfach selbst hier korrigieren!

Quellcode

#!/bin/bash

# mode kann "sys" (es wird auf systembenutzer zurückgegriffen) "lmn" (es wird auf linuxmuster-Benutzer/sophomorix zurückgegriffen)
mode="lmn"
# das unterscheidet die skripterzeugten einträge von sonstigen - nicht leichtfertig ändern (-> Inkonsistenz)
prefix="lmn_"
# zur Sicherheit: Datenbanken/Benutzer, die nicht vom Skript bearbeitet werden
exclude=( "horde5" "nagios3" )
apachedir="/etc/apache2/conf.d"
htmldir="HTML"

# lokales netzwerk (bei manueller Änderung von /etc/networks muss hier nachgearbeitet werden)
localnet="$(cat /etc/networks | grep localnet | sed "s/localnet//" | tr -d " \t")/16"

# ein paar Fehler abfangen
[[ $mode == "lmn" || $mode == "sys" ]] || { echo "Modus nicht korrekt gesetzt - bitte Skript überprüfen!"; exit 0; }
[[ -e $apachedir ]] || { echo "apache-Dir existiert nicht - bitte Skript überprüfen!"; exit 0; }
[[ "${apachedir#${apachedir%?}}" == "/" ]] || apachedir+="/"

# grobes Abfangen des Parameters (ist es/existiert die Datei)
if [[ $1 ]]; then
  [[ "$1" == "-f" || "$1" == "-p" && "$mode" == "lmn" ]] || { echo "Fehlerhafte Parameter! Ich akzeptiere -f <Dateiname> $([[ "$mode" == "lmn" ]] && echo "oder -p <Projektname>") - bitte Eingabe prüfen"; exit 0; }
  [[ "$1" == "-f" && ! -f $2 ]] && { echo "Die Datei wurde nicht gefunden - bitte Eingabe prüfen"; exit 0; }
  [[ "$1" == "-p" && ! $2 ]] && { echo "Kein Projektname übergeben - bitte Eingabe prüfen"; exit 0; }
  [[ "$mode" == "lmn" && "$1" == "-p" && "$(sophomorix-project -i -p $2 | grep -c "not exist")" == "1" ]] && { echo "Das Projekt existiert nicht - bitte Eingabe prüfen"; exit 0; }
fi

# nun definieren wir die Funktionen zum anlegen und löschen
create() {

  # home bestimmen (je nach system) und anlegen
  [[ "$mode" == "lmn" ]] && home=$(sophomorix-user -u $1 | grep "/home" | tr -d " " | cut -d ":" -f 2 | cut -d "(" -f 1
) || home=$(cat /etc/passwd | grep ":$1:" | cut -d ":" -f 6)
  # wenn kein home - machen wir nicht weiter
  if [[ $home ]]; then
    [[ ! -d $home/$htmldir ]] && mkdir $home/$htmldir
    [[ "$mode" == "sys" ]] && chown $usr.$usr $home/$htmldir
    [[ "$mode" == "lmn" ]] && chown $usr.teachers $home/$htmldir
    # unter linuxmuster.net 6 ist www-data die Gruppe für die Lehrer-Homeverzeichnisse
    [[ "$mode" == "lmn" && "$(echo "$home" | cut -d "/" -f 3)" == "teachers" ]] && chown $usr.www-data $home/$htmldir
    chmod ugo+rwx $home/$htmldir;
    # Apache-Dateien anlegen
    echo -e "# Durch das Apache-Skript angelegte conf-Datei für den Benutzer $1\n"\
            "Alias /$1 $home/$htmldir\n"\
            "<Directory $home/$htmldir>\n"\
            "  Order allow,deny\n"\
            "$([[ "$access" == "1"  ]] && echo "  Allow from all\n")"\
            "$([[ "$access" == "2"  ]] && echo "  Allow from $localnet\n")"\
            "$([[ "$access" == "3"  ]] && echo "  Allow from 127\n")"\
            "  AllowOverride Limit\n"\
            "  DirectoryIndex index.html\n"\
            "</Directory>\n\n<IfModule mod_php5.c>"\
            "\n  php_value display_errors on\n</IfModule>" >> /etc/apache2/conf.d/$prefix$usr.conf

    # prüfe, ob nutzer oder db vorhanden
    if [[ "$(mysql -e "SHOW DATABASES" | grep -c $1)" == "0" && "$(mysql -e "SELECT user FROM mysql.user" | grep -c $1)" == "0" ]]; then
      # hole erstpasswort aus sophomorix oder frage nach
      [[ "$mode" == "lmn" ]] && pass=$(sophomorix-user -u $1 -v | grep Pass | sed "s/$1.//" | tr -d " " | cut -d ":" -f 2) || pass=$(whiptail --inputbox "Passwort eingeben: " 10 40 "" --title "MySQL-Passwort" 3>&1 1>&2 2>&3)
      # lege benutzer/db an
      mysql -e "CREATE DATABASE $1;"
      mysql -e "CREATE USER '$1'@'localhost' IDENTIFIED BY '$pass';"
      mysql -e "GRANT ALL ON $1.* TO '$1'@'localhost';"

      # zurückspielen von backups
      sqlmenu=(); for i in $(find $home -name "$1*.sql" -printf "%f\n"); do sqlmenu=( "${sqlmenu[@]}" "$i" "einlesen" ); done
      if [[ "${#sqlmenu[@]}" != "0" ]]; then
        sqlfile=$(whiptail --title "SQL-Restore" --menu "Welche Datei soll wiederhergestellt werden?" $(tput lines) $(tput cols) $(expr $(tput lines) - 8) "${sqlmenu[@]}" 3>&1 1>&2 2>&3)
        [[ $sqlfile ]] && mysql $1 < $home/$sqlfile
      fi
    else
      whiptail --title "Hinweis" --msgbox "Datenbank oder Benutzer $1 bereits vorhanden. Datenbank wird nicht angelegt!"  10 40
    fi
  else
    whiptail --title "Hinweis" --msgbox "Der Benutzer $1 hat keine Heimat. Abbruch!"  10 40
  fi
}

delete() {
  # löschen der apache-conf
  rm $apachedir$prefix$1.conf
  # löschen des HTML-Verzeichnisses, wenn leer (!)
  [[ "$mode" == "lmn" ]] && home=$(sophomorix-user -u $1 | grep "/home" | tr -d " " | cut -d ":" -f 2 | cut -d "(" -f 1
) || home=$(cat /etc/passwd | grep ":$1:" | cut -d ":" -f 6)
  [[ "$(ls -A $home/$htmldir)" ]] || rmdir $home/$htmldir

  # prüfe, ob nutzer oder db vorhanden
  if [[ "$(mysql -e "SHOW DATABASES" | grep -c $1)" == "0" || "$(mysql -e "SELECT user FROM mysql.user" | grep -c $1)" == "0" ]]; then
    whiptail --title "Hinweis" --msgbox "Datenbank oder Benutzer $1 nicht vorhanden. Es kann nichts gelöscht werden!"  10 40
  else
    # löschen von DB und user (wenn etwas in der Datenbank, dump ins user-home)
    [[ "$(mysql $1 -e "SHOW TABLES")" ]] && mysqldump $1 > $home/${1}_$(date +%Y%m%d_%H%M).sql
    mysql -e "DROP DATABASE $1;"
    mysql -e "DROP USER '$1'@'localhost';"
    
  fi
}

menu=( "1" "Neuen Benutzer anlegen" \
       "2" "Einen Benutzer loeschen" \
       "3" "ALLE Benutzer loeschen" )

[[ $1 ]] && { type=$([[ "$1" == "-f" ]] && echo "Datei" || echo "Projekt");
              menu=( "${menu[@]}" \
                     "4" "Nutzer nach $type anlegen" \
                     "5" "Nutzer nach $type löschen" \
                     "6" "Nutzer komplett mit $type synchronisieren" ); }
menu=( "${menu[@]}" "0" "Ende" )

while choice=$(whiptail --backtitle "$([[ $1 ]] && echo "$type übergeben: $2" || echo "keine Daten übergeben")" --title "Alles kleine Apachen" --menu "Was tun wir heute:" $(tput lines) $(tput cols) $(expr $(tput lines) - 8) "${menu[@]}" 3>&1 1>&2 2>&3); do

  # Einlesen der aktuellen Liste und ggf. der übergebenen Datei (prefix und .conf werden enfernt - hier nur Nuternamen!
  conf_cur=( $(find $apachedir -name "$prefix*.conf" -printf "%f\n" | sed -e "s/$prefix//;s/.conf//") )
  [[ "$1" == "-f" ]] && conf_new=( $(cat $2) )
  [[ "$1" == "-p" ]] && conf_new=( $(sophomorix-project -p $2 -u | tail -n +6 | head -n -3 | cut -d '|' -f 2) )

  # filtern um ausgeschlossene Elemente
  for ((i=0;i<${#conf_cur[@]};i++)); do for usr in ${exclude[@]}; do
    [[ "${conf_cur[$i]}" == "$usr" ]] && unset conf_cur[$i]
    [[ $1 && "${conf_new[$i]}" == "$usr" ]] && unset conf_new[$i]
  done; done

  case $choice in
    "0")
      # Apache neu starten
      echo "Apache neu starten"; /etc/init.d/apache2 restart > /dev/null
      exit 0
    ;;
    "1")
      usr=$(whiptail --inputbox "Benutzername: " 10 40 "" --title "Benutzer anlegen" 3>&1 1>&2 2>&3)
      exitstatus=$?; if [ $exitstatus = 0 ]; then
        # prüfen ob auf Sperrliste
        doit=1
        for testusr in ${exclude[@]}; do
          [[ "$testusr" == "$usr" ]] && whiptail --title "FEHLER" --msgbox "Benutzername $usr ist gesperrt." 8 78 3>&1 1>&2 2>&3 && doit=0
        done

        # prüfen ob schon vorhanden
        for testusr in ${conf_cur[@]}; do
          [[ "$testusr" == "$usr" ]] && whiptail --title "FEHLER" --msgbox "Benutzername $usr existiert bereits." 8 78 3>&1 1>&2 2>&3 && doit=0
        done
        # welches Netz ist erlaubt
        if [[ "$doit" == "1" ]]; then
          access=$(whiptail --title "Berechtigungen" --menu "Aus welchem Netz darf auf das Home zugegriffen werden?" $(tput lines) $(tput cols) $(expr $(tput lines) - 8) "1" "all" "2" "LAN ($localnet)" "3" "local (127.0.0.1)" 3>&1 1>&2 2>&3)
          [[ $access ]] && create $usr
        fi
      fi
      ;;
    "2")
      menu2=(); for i in "${conf_cur[@]}"; do menu2=( "${menu2[@]}" "$(echo $i | sed "s/".conf"//")" "loeschen" ); done
      if [[ "${#menu2[@]}" != "0" ]]; then 
        usr=$(whiptail --title "Nutzerliste" --menu "Wen loeschen wir heute:" $(tput lines) $(tput cols) $(expr $(tput lines) - 8) "${menu2[@]}" 3>&1 1>&2 2>&3)
        if [[ $usr ]]; then
          whiptail --title "Warnung" --yesno "$usr wird geloescht\n\nSICHER?" 10 40
          exitstatus=$?; [[ $exitstatus = 0 ]] && delete $usr
        fi
         else
        whiptail --title "Hinweis" --msgbox "Es gibt keine Einträge mit Prefix $prefix." 10 40
      fi
      ;;
    "3")
      if [[ "${#conf_cur[@]}" != 0 ]]; then 
        whiptail --title "Warnung" --yesno "ALLE Benutzer ($(echo ${conf_cur[@]})) werden geloescht\n\nSICHER?" 10 40
        exitstatus=$?;  [[ $exitstatus = 0 ]] && for i in "${conf_cur[@]}"; do delete $i; done
      else
        whiptail --title "Hinweis" --msgbox "Es gibt keine Einträge mit Prefix $prefix." 10 40
      fi
      ;;
    *)
      # diff besti	mmen
      diff_cre=( ); diff_crn=( ); diff_del=( ); diff_den=( )
      if [[ "$choice" == "4" || "$choice" == "6" ]]; then
        for usr in ${conf_new[@]}; do 
          doit=1; for usrtest in ${conf_cur[@]}; do [[ "$usr" == "$usrtest" ]] && doit=0; done
          [[ "$doit" == "1" ]] && diff_cre=( ${diff_cre[@]} $usr ) || diff_crn=( ${diff_crn[@]} $usr )
        done
      fi
      if [[ "$choice" == "5" || "$choice" == "6" ]]; then
        for usr in ${conf_cur[@]}; do 
          doit=1; for usrtest in ${conf_new[@]}; do [[ "$usr" == "$usrtest" ]] && doit=0; done
          [[ "$doit" == "1" ]] && diff_del=( ${diff_del[@]} $usr ) || diff_den=( ${diff_den[@]} $usr )
        done
      fi
      [[ "$choice" == "4" ]] && { whiptail --title "Warnung" --yesno " Ich lege an: ${diff_cre[@]}\n$([[ "${#diff_crn[@]}" != "0" ]] && echo "Ich ignoriere: ${diff_crn[@]} (ist vorhanden)")\n\nSICHER?" 10 40; exitstatus=$?; }
      [[ "$choice" == "5" ]] && { whiptail --title "Warnung" --yesno " Ich lösche:  ${diff_del[@]}\n$([[ "${#diff_den[@]}" != "0" ]] && echo "Ich ignoriere: ${diff_den[@]} (steht in Liste)")\n\nSICHER?" 10 40; exitstatus=$?; }
      [[ "$choice" == "6" ]] && { whiptail --title "Warnung" --yesno " Ich lege an: ${diff_cre[@]}\nIch lösche: ${diff_del[@]}\n\nSICHER?" 10 40; exitstatus=$?; }
      if [[ $exitstatus = 0 ]]; then
        [[ "$choice" == "4" || "$choice" == "6" ]] && for i in "${diff_cre[@]}"; do create $i; done
        [[ "$choice" == "5" || "$choice" == "6" ]] && for i in "${diff_del[@]}"; do delete $i; done
      fi
      ;;
  esac
done
 [[anwenderwiki:usr2amp_thoschi]] anwenderwiki/usr2amp_thoschi.txt · Zuletzt geändert: 2013/12/10 23:51 (Externe Bearbeitung)