Linux: Der Unterschied zwischen /usr/local und /opt

Wenn man intensiv mit Linux arbeitet, wird man sich irgendwann mal fragen was der Unterschied zwischen den Verzeichnissen /usr/local und /opt ist – Denn gemäss dem Filesystem Hierarchy Standard (FHS) sind beide Verzeichnisse für „lokale Software Installationen“ zu verwenden. Doch welches Verzeichnis ist wann angebracht? Und Warum gibt es überhaupt zwei verschiedene Verzeichnisse? Dieser Artikel soll darüber Auskunft geben.

Warum gibt es zwei „konkurrierende“ Verzeichnisse?

Nun, dafür gibt es mehrere Gründe und die Systemadministratoren streiten sich nunmehr schon seit über 20 Jahren darum. 😉

Einer davon ist sicher, dass das Linux nicht „von Grund auf“ designet, worden, sondern gewachsen ist. So haben die einen Leute ihre lokale Software in /usr/local installiert, andere hingegen in /opt.

Ein anderer Grund ist, dass das /usr Verzeichnis ursprünglich mal dazu gedacht war über das Netzwerk auf mehreren Rechnern geteilt zu werden (was jedoch praktisch nie so gehandhabt wurde) und so wäre /usr/local häufig auch nicht „lokal“ gewesen. So hatte man dann Software, die allen Servern zur Verfügung stehen sollten in /usr/local installiert und tatsächlich „lokale Software“ in /opt

Weiter wurde einmal definiert, dass man das /usr filesystem read-only mounten können muss. So wäre dann aber /usr/local ebenfalls nicht beschreibbar gewesen und /opt wäre hierzu wieder die Lösung gewesen.

Doch, wann ist welches der beiden Verzeichnisse zu verwenden?

Heutzutage, wo das /usr filesystem weder mit anderen Rechnern geteilt- noch read-only gemounted wird, gibt es trotzdem noch einen Grund zwischen /usr/local und /opt zu Unterscheiden: Denn /usr/local ist ein „Abbild“ von /usr, mit all seinen Unterverzeichnissen wie /bin /lib, /src, /etc,…

So verwendet man /usr/local für Programme, die sich exakt an den Linux filesystem Standard halten, also etwa librairies in /usr/local/lib ablegen, ausführbare Dateien ind /usr/local/bin, Dokumentationen (natürlich im man-page Format) in /usr/local/share/man, usw.

Das /opt Verzeichnis hingegen benutzt man bei Software die diesen Standard nicht einhält, bzw. nicht einhalten kann, weil sie Plattform-Unabhängig geschrieben ist. Dort würde man dann die Programmbibliotheken, Ausführbare Dateien, Dokumentation, usw. alles im Programm Verzeichnis vorfinden, also z.B. /opt/myAPP/bin, /opt/myAPP/config, /opt/myAPP/librariers, usw.

Ersteres (hält den Standard nicht ein) trifft oft bei sog. „Windows Style“ Programmen zu, die ihre Dateien z.B. alle unter C:Programme ablegen würden.

Zweiteres trifft dann z.B. bei Java Software zu, da in Java geschriebene Programme meist schon „von Haus aus“ Plattform unabhängig sind und so auch auf mehreren Systemen installiert werden können. – So findet man beispielsweise die Java Installation oft unter /opt/java, anstatt im /usr Verzeichnis verteilt und auch darauf basierende Software, wie z.B. der JBOSS Applikationsserver wird besser in /opt/jboss installiert, anstatt in /usr/local.

Gibt es noch andere solche Fälle?

Es gibt tatsächlich noch solche Inkonsistenzen, die historisch heran gewachsen ist, z.B. die Verwendung von /var anstatt /srv für sich ändernde Daten von Programmen.
Hier wird leider der apache Webserver auf den meisten Installationen unter /var/www, anstatt /srv/www abgelegt. Dies ist jedoch vor allem heute, wo ein Webserver viel mehr als 2-3 Seiten zur Verfügung stellt nicht hinnehmbar und man sollte notfalls das Verzeichnis /var/www auf /srv/www verlinken und für reine „Hosting Webserver“ am besten gleich /home dafür nehmen.

Quellen

Filesystem Hierarchy Standard
Linux Journal: Point/Counterpoint – /opt vs. /usr/local
unix.com: Difference between /opt and /usr/local
unix.stackexchange.com: What is the difference between /opt and /usr/local?
Google Suche zum Thema

Suchen und Ersetzen in Variablen

In einem anderen KB-Eintrag ging es um das suchen & ersetzen von strings in Dateien. Dies geht jedoch auch in Variablen:

Will man Beispielsweise in der folgenden variable:

VAR1=“Ich fahre Velo“

Den Text „Velo“ mit „Auto“ ersetzen geht dies wie folgt:

VAR2=${VAR1//Velo/Auto}

Quellen

unix.com: search & replace in variable

Mit lsof Speicherplatz von gelöschten offenen Dateien finden & freigeben

Bei Linux kann es manchmal zum Phänomen kommen, dass viel Speicherplatz verbraucht wird, aber tatsächlich gar nicht so viel auf der Disk vorhanden scheint, wenn man alle Files zusammen zählt:

[root@host ~]# df -h /usr/
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda3              22G   20G  357M  99% /usr
 
[root@host ~]# du -sh /usr/
<ol>
12G     /usr/
</ol>

In diesem Beispiel wird mit df auf /usr ein Speicherplatzverbrauch von 20GB angezeigt; tatsächlich sind aber nur 12GB mit Dateien belegt, wenn man diese mit du zusammen zählt. – Wo sind also die restlichen 8GB?

Grund dafür ist, wenn man einem Prozess, der gerade eine Datei schreibt, ihm diese Datei löscht. So wird der Prozess nicht benachrichtigt, dass die Datei nicht mehr im Filesystem ist und er schreibt weiterhin auf die Festplatte, resp. in das sog. "File Handle" wie das ein Programmierer ausdrücken würde.

Solche Prozesse, die gelöschte Dateien noch offen haben, findet man mit dem lsof Kommando:

[root@host ~]# lsof -a +L1
COMMAND  PID   USER   FD   TYPE DEVICE       SIZE NLINK    NODE NAME
perl    5844 oracle    5w   REG    8,3    4194360     0 1337313 /usr/local/myapp.log (deleted)

Startet man dann den entsprechenden Prozess neu, wird der Platz wieder frei gegeben.

[stextbox id=“note“ caption=“Hinweis“]Grundsätzlich sollte man, wenn man files löscht, sicherstellen, dass diese nicht gerade beschrieben werden (gilt besonders für logfiles).

So sollte man bei "aktiven" Dateien am besten vorher den Prozess beenden, der darauf schreibt, oder nach dem löschen diesen neu starten.[/stextbox]

Quellen

http://www.jfranken.de/homepages/johannes/vortraege/lsof_inhalt.de.html

drupal: Alle Benutzer zu einem simplenews Newsletter anmelden

Wenn man Drupal mit bereits einigen usern hat und dann simplenews installiert, will man warhscheinlich alle user zu einem erstellten newsletter hinzufügen.

Dies geht ganz einfach mit zwei SQL kommandos:

INSERT INTO drupal_simplenews_subscriptions(activated,mail,uid) SELECT 1,mail,uid FROM drupal_users WHERE uid > 0 ORDER BY uid ASC;
INSERT INTO drupal_simplenews_snid_tid(snid,tid) SELECT snid,1 FROM drupal_simplenews_subscriptions;

Wobei in diesem Code "1" jeweils die ID des Newsletters ist (muss evtl. angepasst werden!).

Quellen

http://cc.com.au/2010/02/03/drupal-simplenews-mass-subscribe
http://stackoverflow.com/questions/4738403/drupal-simplenews-how-to-subscribe-all-existing-users

apache: Am ActiveDirectory authentifizieren

Den Weg Benutzer über .htaccess und .htpasswd beim apache Webserver zu authentifizieren ist hinlänglich bekannt.
Noch interessanter ist jedoch die Authentifizierung über ein Zentrales ActiveDirectory (oder einen beliebigen LDAP Server) – Und dabei ist es fast so einfach wie über die .htpasswd files.

Als erstes benötigt man das modul yum install mod_ldap:

yum install mod_ldap

Danach erstellt man im zu schützenden Web-verzeichnis einfach eine Datei mit dem Namen .htaccess und folgendem Inhalt:

# Username to bind
AuthLDAPBindDN "CN=unprivilegierter-user,OU=User Accounts,DC=ad,DC=example,DC=net"
AuthLDAPBindPassword "xxxxxx"
 
# search for users
AuthLDAPURL "ldap://ad.example.net/OU=User Accounts,DC=ad,DC=example,DC=net?sAMAccountName?sub?(objectClass=*)"
 
AuthType Basic
AuthName "WINDOWS ACCOUNT LOGIN"
AuthBasicProvider ldap
 
# Important, otherwise "(9)Bad file descriptor: Could not open password file: (null)"
AuthUserFile /dev/null
require valid-user

[stextbox id=“note“ caption=“Hinweis bei der Verwendung von SSL (ldaps://)“]
Verwendet man SSL, also als AuthLDAPURL beispielsweise: ldaps://ad.example.net/, muss man im apache in der Server Konfiguration das checken des CA-Zertifikats deaktivieren, z.B. mit der folgenden Zeile in: /etc/httpd/conf.d/ldap.conf:

LDAPVerifyServerCert Off

Alternativ kann man auch das CA-Zertifikat vom LDAP-Server auf den Webserver kopieren (z.B. nach: /etc/openldap/certs/ldap_ca.crt und dann in: /etc/httpd/conf.d/ldap.conf anstelle von: LDAPVerifyServerCert Off die Option:

LDAPTrustedGlobalCert CA_BASE64 "/etc/openldap/certs/samba_ca.crt"

einfügen.
[/stextbox]

Die einzelnen Anweisungen bedeuten folgendes:

  • AuthLDAPBindDN: Dies ist der DN eines unprivilegierten users; da man beim ActiveDirectory nur schon einen user braucht um andere user zu suchen. 😉
  • AuthLDAPBindPassword: Das Passwort für diesen (system-) user
  • AuthLDAPURL: Die URL für die Domain Suche (muss mindestens ein Unterverzeichnis (OU) enthalten!)

Der Rest entspricht den Standard Apache-Authentifizierungs Konfigurationen.

[stextbox id=“tip“ caption=“mod_ldap debuggen“]
Falls bei mod_ldap etwas nicht funktioniert, erhält man nicht mehr als einen HTTP 500 Fehler im apacher error.log und mit dieser Info lässt sich leider nicht so viel anfangen.
Glücklicherweise gibt es die Option: LDAPLibraryDebug, welche man in der Server-Konfiguration, beipspielsweise mit der folgenden Zeile in: /etc/httpd/conf.d/ldap.conf hinzufügen kann:

LDAPLibraryDebug 7

Nach einem restart des apache servers steht dann die ganze LDAP connection info im error.log.

Hinweis: Auch SELinux kann in diesem Kontext für Probleme verantwortlich sein.
[/stextbox]

Quellen

Red Hat init-script Vorlagen

Sobald man mal ein eigenes start script schreiben will, sucht man nach einem guten template, welches Möglichst die Standard Funktionen benutzt; diese sind bei RedHat z.B. in der Datei: /etc/init.d/functions zu finden.

Nachfolgend finden sich zwei Beispiele; das erste benutzt man, wenn man das „daemon-handling“ selbst machen will, dass zweite nutzt die entsprechende Funktion in der functions Datei.

# Init-Script template
#
# Written by Steven Varco <email@adresse.tld>
#
# chkconfig: - 80 20
# description: SERVICENAME daemon
#
# processname: SERVICENAME
# config: /etc/SERVICENAME.conf
# pidfile: /var/run/SERVICENAME
 
# source functions library
. /etc/init.d/functions
 
 
APP_NAME=myApp                                  # Name of the application (will be excecuted!)
APP_DESC="SERVICE DESCRIPTION"                  # Short description
APP_PID=/var/run/$APP_NAME                      # PID file
APP_CONFIG="/etc/SERVICENAME.conf"              # Config file
 
 
case "$1" in
start)
  echo -n "Starting $APP_NAME..."
 
  # Start functions
  #$(which runuser) -l myuser $APP_NAME
  echo $! > $APP_PID
 
  # Output OK or FAIL
  RETVAL=$?
  if [ $RETVAL -eq 0 ]; then
    echo_success
  else
    echo_failure
  fi
 
  # Create PID-File
  if [ ! -f "$APP_PID" ] ; then
    touch $APP_PID
  fi
;;
 
 
 
stop)
  echo "Stopping $APP_NAME..."
 
# Stop functions
  if [ -f $APP_PID ] ; then
    kill $($APP_PID)
 
    # Output OK or FAIL
    RETVAL=$?
    if [ $RETVAL -eq 0 ]; then
      echo_success
    else
      echo_failure
    fi
  else
    echo "$APP_NAME is not running"
  fi
 
  # Remove PID-File
  if [ -f "$APP_PID" ] ; then
    rm -f $APP_PID
  fi
;;
 
 
 
restart)
$0 stop && sleep 3 && $0 start || return=$0
;;
 
 
status)
  if [ -f "$APP_PID" ] ; then
    PID=$(cat $PID_FILE)
    PSPID=$(ps -p $PID -o comm=)
    if [ -n "$PSPID" ]; then
      echo -n "$APP_NAME is running as PID: $PID and command: $PSPID"
      echo_success
    else
      echo -n "$APP_NAME dead but pid file exists!"
      echo_warn
    fi
  else
    echo -n "$APP_NAME is not running"
  fi
  exit $RETVAL
;;
 
*)
  echo "Usage: $0 {start|stop|restart|status}"
  exit 1
esac
#!/bin/bash
#
# Init file for myApp
#
# Written by Vorname Name <email@adresse.tld>.
#
# chkconfig: - 80 20
# description: MyApp daemon
#
# processname: myapp
# config: /etc/myapp.cfg
# pidfile: /var/run/myapp
 
source /etc/rc.d/init.d/functions
 
### Default variables
CONFIG="/etc/myapp.cfg"
 
[ -x /usr/sbin/myapp ] || exit 1
[ -r "$CONFIG" ] || exit 1
 
RETVAL=0
prog="myapp"
desc="myApp daemon"
 
start() {
        echo -n $"Starting $desc ($prog): "
        daemon $prog -c "$CONFIG" -d
        RETVAL=$?
        echo
        [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
        return $RETVAL
}
 
stop() {
        echo -n $"Shutting down $desc ($prog): "
        killproc $prog
        RETVAL=$?
        echo
        [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
        return $RETVAL
}
 
restart() {
        stop
        start
}
 
reload() {
        echo -n $"Reloading $desc ($prog): "
        killproc $prog -HUP
        RETVAL=$?
        echo
        return $RETVAL
}
 
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart)
        restart
        ;;
  reload)
        reload
        ;;
  status)
        status $prog
        RETVAL=$?
        ;;
*)
  echo $"Usage: $0 {start|stop|restart|reload|condrestart|status}"
  RETVAL=1
esac
 
exit $RETVAL

Drupal7: Bildergalerie erstellen

In Drupal7 wuede einiges vereinfacht, z.B. das erstellen einer Bilder-Galerie, was früher unzählige module brauchte, lässt sich jetzt mit einem Bewerkstelligen – inlk. "shadowbox effekt".

Folgendes vorgehen ist dazu vonnöten:

  • Einen neuen content type erstellen (admin/structure/types/add)

Titel: Bildergalerie Name: bildergalerie

  • Speichern und Felder hinzufügen wählen
  • Neues Feld: hinzugügen

Beschriftung: Bild Name: field_image Feld: Bild Steuerelement: Bild

  • Feldeinstellungen speichern wählen
  • Im nachfolgenden Dialog den Wert von: Anzahl von Werten auf unbegrenzt setzen
  • Einstellungen speichern
  • Das "shadowbox" Modul herunter laden und installieren
  • Eine View (Ansicht" für die Galerie erstellen

Nun funktioniert die Galerie zwar schon, die Bilder werden jedoch untereinander angezeigt.
Damit die Bilder nun nebeneinander angezeigt werden muss man das "style.css" seines verwendeten Themes um diese Zeile erweitern:

.node-bildergalerie .field-name-field-picture .field-item {float:left; margin:20px;}

Ressourcen

http://drupal.org/node/1025556#comment-4355506
http://drupal.org/node/1025556#comment-4784220

BIND: forward pro Zone

Die Option forwarders in der bind Konfiguration, die meist im globalen "options" Teil zu finden ist, ist hinlänglich bekannt; damit kann man nämlich DNS-Anfragen an einen anderen server weiter leiten. – Doch, was ist, wenn man dies nur für bestimmte Domänen und nicht generell machen möchte?

Die forwarders option lässt sich dazu auch in einer Zone definieren; so kann man für eine bestimmte zone angeben, dass nur diese queries forwarded werden sollen, was z.B. nützlich ist, wenn man im Heimnetzwerk eine eigene DNS Zone hat und für eine allfällige VPN-Verbindung zur Firma, dann für die Firmen Domain deren Nameserver nutzen möchte.

So kann man z.B. eine zones.conf wie folgt machen:

zone "home.lan" { type master; file "/etc/named/zones/home.lan"; allow-query { any; }; };
zone "company.net" { type forward; forwarders { x.x.x.x; }; };

Anfragen an .home.lan werden so lokal abgehandelt, solche an .company.net jedoch weiter geleitet auf x.x.x.x. Alle anderen anfragen können weiterhin lokal über die root-server oder über eine globale forwardes Option an die Nameserver des ISPs weitergeleitet werden.

Weitere Infos: http://www.zytrax.com/books/dns/ch7/queries.html#forwarders

MPC: Playlisten vom Kontextmenü erstellen

Einige Windows Anwender sind vom „neuen“ Windows Media Player ab Version 7 nicht begeistert: Zu aufgebläht, unübersichtlich, etc.

Deshalb gibt es den wunderbaren MediaPlayerClassic. Mit einem kleine Trick, kann man sich sogar im Kontextmenü einen Eintrag machen: „Der MPC Wiedergabeliste hinzufügen“ und so einfach MP3 Dateien markieren und diese automatisch in der Liste abspielen lassen.

Dazu muss man wie folgt Vorgehen:

  • Einen Ordner öffnen und im Menu Extras->Ordneroptionen->TAB: Dateitypen wählen
  • Die gewünschte Dateiendung aussuchen und auf Erweitert klicken.
  • Auf Neu klicken

Hier macht man folgende Angaben:
Vorgang: Zur MPC Playliste hinzufügen
Anwendung für diesen Vorgang: „<PFAD_ZU>mpc-hc.exe“ /play /add „%1″

{img fileId=“61″ thumb=“y“ rel=“box[g]“ imalign=“left“}

Dann auf OK und man kann entsprechend mehrere Files gleich aus dem Kontextmenü abspielen!

Drupal: CKEditor konfigurieren

In einem anderen KB-Eintrag wurde erklärt, wie man dem bei [http://www.tech-island.com/kb-Platformunabh%C3%A4ngig-Internet-WordPress%3A+Mehrfache+Zeilenumbr%C3%BCche&structure=kb|Wordpress dem WYSIWYG-Editor einen schmaleren Zeilenumbruch] hinkriegt.

Das selbe kann man auch beim in Drupal erhaltenen CKEditor machen:

Erstelle ein Verzeichnis mit dem Namen overrides in sites/all/modules

Erstelle darin folgende zwei Dateien:

overrides.info und overrides.module

in overrides.info schreibe dies:

name = Overrides
description = Overrides settings
core = 7.x
 
package = own

und in overrides.module:

<?php
/<em> wysiwyg overrides </em>/
 
function overrides_wysiwyg_editor_settings_alter(&$settings, $context) {
  if($context['profile']->editor == 'ckeditor') {
    $settings['enterMode'] = 2;
    $settings['shiftEnterMode'] = 1;
  } else if($context['profile']->editor == 'tinymce') {
    $settings['forced_root_block'] = FALSE;
    $settings['force_br_newlines'] = TRUE;
    $settings['force_p_newlines'] = FALSE;
  }
}

Achtung: Das end-tag von <?php ist hier bewusst weg gelassen!

Gehe danach zur Module seite in: admin/modules Dort findest du in der Kategorie "OWN", das Modul "overrides". Aktiviere dieses.

Die Änderung sollte sofort wirksam werden, falls nicht wähle im cache menu: "Flush all caches".

Quelle: Dieser Tip stammt von: http://wdtutorials.com/drupal7/50