Installation eines LAMP Webservers mit Ubuntu

22 08 2012

Normalerweise nutze ich für meinen Test-Webserver die XAMPP Sammlung, da dieses keinerlei Installation erfordert und das komplette Paket portabel ist, also beispielsweise mit einem USB Stick überall hin mitgenommen und auf einem anderen Computer weiter verwendet werden kann. Trotzdem kann es manchmal von Vorteil sein, die Komponenten direkt zu installieren.

Die Mär, dass eine Installation eines funktionierenden Webservers mit allen wichtigen Komponenten für Testzwecke schwierig sei möchte ich heute ausräumen. Natürlich taugt ein solches System noch nicht für den Produktiveinsatz, sollte also nicht öffentlich an das Netz angebunden werden. Dazu benötigt es noch einigen Feinschliff insbesondere was die Sicherheit gegenüber böswilligen Angriffen angeht.

Im Folgenden wollen wir uns die gebräuchlichste Software installieren. Die wären der Apache Webserver, als Datenbank MySQL sowie die Skriptsprache PHP. Nimmt man dann noch unser Betriebssystem hinzu, wissen wir jetzt auch, wofür LAMP steht, nämlich für Linux, Apache, MySQL, PHP.

Was das genau für Programme sind, was man damit überhaupt anstellen kann, das ist nicht Inhalt dieses Artikels. Hier soll es lediglich um die Installation in Linux gehen. Ein grundsätzliches Verständnis der Materie wird also vorausgesetzt.

Apache
Installieren des Apache Webservers:

sudo apt-get install apache2

Der Server soll nicht von außen erreichbar sein. Deshalb sagen wir Apache, dass er nur auf localhost hören soll. Hierzu bearbeiten wir die ports.conf:

sudo vi /etc/apache2/ports.conf

Listen 80
ändern in
Listen localhost:80

Jetzt können wir unseren Webserver schon testen, indem wir die Adresse http://localhost/ in unsere Browser-Adresszeile eintippen.

Wollen wir Subdomains erstellen, kopieren wir uns das Default-Template aus /etc/apache2/sites-available in eine neue Datei mit dem Namen unseres virtuellen Hosts und editieren diese. Meine Subdomain heißt „ramtatta“, außerdem habe ich den Default-Pfad von /var/www/ noch abgeändert in mein Home-Verzeichnis.

sudo cp /etc/apache2/sites-available/default /etc/apache2/sites-available/ramtatta
sudo vi /etc/apache2/sites-available/ramtatta

<VirtualHost *:80>
   ServerName ramtatta.localhost
   ServerAdmin webmaster@localhost
   DocumentRoot /home/aaaaa/htdocs/RamTatTa
   <Directory /home/aaaaa/htdocs/RamTatTa/>
      Options Indexes FollowSymLinks MultiViews
      AllowOverride All
      # Die folgenden beiden Einträge waren unter Apache 2.2 gültig.
      # Order allow,deny
      # allow from all
      # Für Apache 2.4 müssen diese durch den nachstehenden Eintrag ersetzt werden:
      Require all granted
   </Directory>
   ErrorLog ${APACHE_LOG_DIR}/error.log
   LogLevel warn
   CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Damit die Umleitung funktioniert, müssen wir noch unsere hosts erweitern.
sudo vi /etc/hosts

Hinzufügen dieser Zeile:
127.0.0.1 ramtatta.localhost

Jetzt muss der virtuelle Host noch aktiviert und der Apache durchgestartet werden.
sudo a2ensite
sudo /etc/init.d/apache2 restart

Aufrufen können wir die Subdomain folgendermaßen: http://ramtatta.localhost/

Möchten wir unsere Links mittels mod_rewrite verschönern, so müssen wir dieses ggf. auch erst noch aktivieren.
sudo a2enmod rewrite
sudo /etc/init.d/apache2 restart

PHP
Installieren von PHP:

sudo apt-get install php libapache2-mod-php

Unsere HTML Seiten legen wir per Default in /var/www ab. PHP testen wir, indem wir hier eine Datei index.php mit folgendem Inhalt erzeugen.

vi /var/www/index.php
   <?php
   phpinfo();
   ?>

Laden wir jetzt wieder http://localhost/ im Browser, wird eine Seite mit vielen Informationen zu unserer Serverumgebung dargestellt.

MySQL
Installieren von MySQL. Den de facto Standard zur Administration von MySQL Datenbanken im Web stellt PHPMyAdmin dar. Um uns gleich daran zu gewöhnen, installieren wir das gleich mit.

sudo apt-get install mysql-server php5-mysql phpmyadmin

Ich selbst habe mich selbst an die Software Navicat gewöhnt. Auch in der kostenlosen Version bietet dieses Programm sehr viele schöne Funktionen und ist in seiner Eigenschaft als echtes Programm jederzeit flotter als die Weboberfläche von PHPMyAdmin. Einziges Manko ist, dass es sich eigentlich um Windows-Binaries handelt, das lediglich gebündelt mit der Wine Laufzeitumgebung als Linux-Version angeboten werden.

Auf die Datenbank können wir jetzt also auch zugreifen. Hierzu tippen wir in der Shell

mysql -u root

bzw. laden im Browser die Adresse http://localhost/phpmyadmin.

Eclipse
Einen sehr mächtigen Editor für die Entwicklung unserer PHP Dateien finden wir in Eclipse. Dieser ist grundsätzlich für die Java-Entwicklung gedacht, mit den PHP Development Tools (PDT) können wir diesen aber auch sehr gut für PHP verwenden.

Installation des Grundpaketes für Eclipse:

sudo apt-get install eclipse

Das Programm starten wir und klicken uns durch zur automatischen Installation der PDT:
Help -> Install new software… -> Work with: Indigo Update Site wählen -> Programming Languages -> PHP Development Tools (PDT) -> Installieren

Xdebug
Ein großer Nachteil von PHP ist, dass sich dieses normalerweise nicht wirklich debuggen lässt. Abhilfe schafft die Xdebug Erweiterung. Wir installieren zunächst das Paket.

sudo apt-get install php5-xdebug

Jetzt müssen wir das Binary und die Ini-Datei finden. Dazu aktualisieren wir unsere Datenbank für locate und lassen uns dann den Pfad für die xdebug.so und xdebug.ini ausgeben.

sudo updatedb

locate xdebug.so
/usr/lib/php5/20090626/xdebug.so

locate xdebug.ini
/etc/php5/cli/conf.d/xdebug.ini

Die Ini Datei editieren wir. Normalerweise sollte hier der Pfad für die Binary schon eingetragen sein, wir kontrollieren dies aber zur Sicherheit. Dann tragen wir noch ein paar Variablen ein, mit denen wir Xdebug aktivieren und starten den Apache neu.

sudo vi /etc/php5/cli/conf.d/xdebug.ini
   zend_extension=/usr/lib/php5/20090626/xdebug.so
   xdebug.remote_enable=1
   xdebug.remote_handler=dbgp
   xdebug.remote_mode=req
   xdebug.remote_host=127.0.0.1
   xdebug.remote_port=9000
sudo /etc/init.d/apache2 restart
Advertisements




MySQL Newlines entfernen

18 12 2011

Auf RamTatTa hatte ich einen kleinen Bug, dass ich Leerzeilen am Ende eines Feldes nicht entfernt habe. Da der ein oder andere Reporter gerne noch ein paar Mal Enter drückt am Ende seiner Eingabe wurde die Anzeige teilweise unnötig verlängert. Den Fehler hatte ich im Code schnell behoben, doch was ist mit den bereits in der Datenbank gespeicherten Daten? Die sollen ebenfalls korrigiert werden.

Man könnte mit REPLACE arbeiten, allerdings würden dann sämtliche Newlines gelöscht, auch mitten im Text. Das darf natürlich nicht passieren. Also nutzen wir die eingebaute Funktion TRIM, die allerdings in ihrer Standardfunktionalität lediglich Leerzeichen entfernt. Also müssen wir explizit angeben, dass wir Newlines (\n) gelöscht haben möchten. Mit „both“ geben wir an, dass sowohl Newlines am Anfang wie auch am Ende des Strings entfernt werden sollen. Dies in ein UPDATE verpackt, schreibt gleich wieder die korrigierten Daten in die Datenbank.

Probleme hatte ich dann noch mit der Ersetzung. Weder ein „\n“, noch ein „\r\n“ hat bei mir irgend etwas ersetzt. Erst nachdem ich den Character-Code verwendete, waren die Leerzeilen verschwunden.

update ramtatta_reviews set urls = trim(both char(13) from urls);




Oracle varchar2 Felder vergleichen

9 12 2011

Vergleicht man im PL/SQL varchar2 Variablen, so sind gleiche Inhalte manchmal doch nicht wirklich gleich. Zur Verdeutlichung soll dieses Beispiel herhalten:

declare
v_var1 varchar(20);
v_var2 varchar(30);
v_var3 varchar(30);

begin
v_var1 := 'Test';
v_var2 := 'Test';
v_var3 := 'Test   ';

if v_var1 = v_var2 then dbms_output.put_line('Eins ist ok'); end if;
if v_var1 = v_var3 then dbms_output.put_line('Zwei ist ok'); end if;
if v_var2 = v_var3 then dbms_output.put_line('Drei ist ok'); end if;
end;
/

Was würde man nun vermuten, kommt als Ausgabe heraus? Im Grunde sind die Texte identisch. Allerdings erhalten wir nur die erste Zeile zurück:
Eins ist ok
Was sagt uns das? Ob die Variable mit einer Länge von 20 oder 30 Zeichen definiert ist, ist egal. So weit so gut, nichts anderes hätten wir erwartet. Warum aber ist die Variable 3 nicht identisch zu den anderen Beiden? Dazu beachte man die Leerzeichen am Ende des Strings. Diese werden im Vergleich also mit berücksichtigt.

Leuchtet ein? Vielleicht, doch nutzt man Character-Felder, sieht die Sache gleich wieder anders aus. Ändern wir also die Variablendefinition zu char, erhalten wir ein anderes Ergebnis:

v_var1 char(20);
v_var2 char(30);
v_var3 char(30);

Ergibt als Ausgabe:
Eins ist ok
Zwei ist ok
Drei ist ok

Warum ist das so? Dazu muss man wissen, dass laut Definition des SQL Standards zwei zu vergleichende Strings immer gleich lang sein müssen. Ist ein String kürzer, wird dieser zur Länge des zu vergleichenden Strings mit Blanks aufgefüllt.

v_var2 := 'Test '; -- Wird mit Blanks aufgefüllt
v_var3 := 'Test ';

Somit erkennen wir, die beiden Variablen sind tatsächlich identisch. Das funktioniert natürlich nur mit Blanks am Ende.

Da der varchar2 Typ aber genau dem Zweck dient, immer nur die exakte Länge eines Strings zu speichern, wird hier nicht aufgefüllt, sondern beide Strings werden genau mit der Länge verglichen, die sie auch tatsächlich besitzen. Will man Strings unabhängig nachgelagerter Leerzeichen vergleichen, sollten die Variablen also als pure Character definiert sein.

Doch was, wenn in dem eigenen Skript varchar2 Felder aus welchem Grund auch immer praktischer sind? Dann müssen wir darauf nicht verzichten. Mittels der trim Funktion können wir beim Vergleich dafür sorgen, dass diese Zeichen entfernt werden. Wir erweitern den Vergleich aus dem ersten Beispiel ein wenig…

if trim(v_var1) = trim(v_var2) then dbms_output.put_line('Eins ist ok'); end if;
if trim(v_var1) = trim(v_var3) then dbms_output.put_line('Zwei ist ok'); end if;
if trim(v_var2) = trim(v_var3) then dbms_output.put_line('Drei ist ok'); end if;

…und schon haben wir auch mit varchar2 Variablen das gewünschte Ergebnis:
Eins ist ok
Zwei ist ok
Drei ist ok

Grundsätzlich hätte hier auch ein rtrim gereicht, doch mit trim gehen wir zudem noch sicher, dass selbst führende Leerzeichen nicht stören.





CSV Datei aus MySQL Datenbank generiern

12 11 2011

Ich wollte aus der MySQL Datenbank für das RamTatTa Fanzine drei Felder als CSV exportieren. Dafür gab es ein paar Bedingungen.
– Jedes Feld soll in Hochkommata („) eingeschlossen sein
– Felder sollen durch Komma (,) getrennt sein
– Das letzte Feld soll die aus der ID des Datensatzes zusammengebaute URL sein

Das erreiche ich mit folgendem Select:

select concat(
  '"', 
  ifnull(
    replace(band, '"', '""'),
    ""
  ), '","',
  replace(titel, '"', '""'), 
  '","http://www.ramtatta.de/reviews,id-', id, '.html"'
) as csv
from ramtatta_reviews
order by id asc;

 

Diese Befehle kurz erläutert:

concat – Füge alle Ergebnisse zu einer einzigen Zeile zusammen

ifnull – Concat gibt kein Ergebnis zurück, sobald ein Feld NULL enthält, also leer ist. Da das Feld „band“ leer sein kann, ich aber trotzdem alles Andere ausgegeben haben möchte, wandle ich hiermit NULL in Leer („“) um.

replace – Da die Felder mit Hochkommata getrennt sind, würde es zu Problemen führen, falls sich in den Feldern ebensolche befinden. Ein Feld
Sehr „gutes“ Album
würde in der CSV so aussehen:
„Sehr „gutes“ Album“
Damit würde das Feld in der CSV Datei also bei „Sehr “ aufhören. Damit dies nicht geschieht, müssen die Hochkommatas maskiert werden, indem diese verdoppelt werden. Im Endeffekt sähe das dann so aus:
„Sehr „“gutes““ Album“

Diese Datei kann nun in einer Tabellenkalkulation geladen werden. Die Einstellungen für LibreOffice Calc sehen so aus:

Und so sieht das Ergebnis aus:





INDEX command denied to user … for table …

31 08 2011

Eigentlich ist der Update-Prozess beim phpBB Board ganz gut gemacht. Bei meinem heutigen Versuch, ein solches Forum auf den neuesten Stand zu bringen erhielt ich doch ein paar Fehlermeldungen in dieser Form:
Fehler :: INDEX command denied to user 'zwiwwelsupp'@'localhost' for table 'phpbb3_login_attempts'
SQL :: CREATE INDEX att_ip ON phpbb3_login_attempts(attempt_ip, attempt_time)

Zwar heißt es noch, diese Fehler seien nicht kritisch, dies sehe ich allerdings gerade bei höher frequentierten Datenbanken anders. Ein guter Index kann die Zugriffszeiten auf die Tabellen enorm beschleunigen. Deshalb sollte man diesen Fehler nicht einfach so hinnehmen, sondern etwas dagegen tun.

Was ist hier passiert? Ganz einfach, der Hoster verbietet den CREATE INDEX Befehl auf seinen Datenbanken. Warum auch immer, Indexe sind doch eigentlich etwas Gutes. Selbst wenn man diese unsinnig einsetzt, außer seiner Performance kann man damit nichts kaputt machen. Bleibt mir also schleierhaft, weshalb man so etwas sperrt.

Sei es wie es ist, einen Index kann man auch ohne diesen Befehl erzeugen. Dazu nutzt man einfach den ALTER TABLE Befehl, d.h. man bearbeitet die Tabelle derart, dass ein neuer Index hinzugefügt wird. Um den Unterschied zu verdeutlichen:
CREATE INDEX <index_name> ON <tabelle> (<feldname 1>, ..., <feldname n>);
ALTER TABLE <tabelle> ADD INDEX <index_name> (<feldname 1>, ..., <feldname n>);

Für unser obiges Beispiel gäbe das dann also:
ALTER TABLE `phpbb3_login_attempts` ADD INDEX att_ip (`attempt_ip`, `attempt_time`);

Das Ergebnis ist das Selbe:
Index





Oracle: Gleichartige Daten aus zwei Tabellen abfragen

16 10 2009

Die Problemstellung war, gleichartige Daten, die über zwei verschiedene Tabellen verteilt sind in einer Ergebnismenge zu erhalten. Wir legen uns also zwei Test-Tabellen mit ein paar Daten an.

SQL> desc tab1
Name      Null?    Type
--------- -------- ---------------------------
FELD1              VARCHAR2(100 CHAR)
FELD2              VARCHAR2(100 CHAR)
FELD3              VARCHAR2(100 CHAR)

SQL> desc tab2
Name      Null?    Type
--------- -------- ---------------------------
FELD1              VARCHAR2(100 CHAR)
FELD2              VARCHAR2(100 CHAR)
FELD3              VARCHAR2(100 CHAR)
FELD4              VARCHAR2(100 CHAR)
FELD5              VARCHAR2(100 CHAR)

SQL> select * from tab1;

FELD1      FELD2      FELD3
---------- ---------- ----------
aaaaa      bbbbb      201001
ccccc      ddddd      201001
eeeee      fffff      201001
ggggg      hhhhh      201001
iiiii      jjjjj      201002

SQL> select * from tab2;

FELD1      FELD2      FELD3      FELD4      FELD5
---------- ---------- ---------- ---------- ----------
kkkkk      lllll      201001     uuuuu      vvvvv
mmmmm      nnnnn      201001     wwwww      xxxxx
ooooo      ppppp      201001     yyyyy      zzzzz
qqqqq      rrrrr      201002     11111      22222
sssss      ttttt      201002     33333      44444

So lange die abgefragten Spalten in beiden Tabellen identisch sind kein größeres Problem.

SQL> SELECT
feld1,
feld2,
feld3
FROM tab1
UNION
SELECT
feld1,
feld2,
feld3
FROM tab2
ORDER BY feld3 ASC;

FELD1      FELD2      FELD3
---------- ---------- ----------
aaaaa      bbbbb      201001
ccccc      ddddd      201001
eeeee      fffff      201001
ggggg      hhhhh      201001
kkkkk      lllll      201001
mmmmm      nnnnn      201001
ooooo      ppppp      201001
iiiii      jjjjj      201002
qqqqq      rrrrr      201002
sssss      ttttt      201002

10 rows selected.

Benötigen wir allerdings eine unterschiedliche Anzahl an Spalten je Tabelle, funktioniert dieses Vorgehen so nicht mehr:

SQL> SELECT *
FROM tab1
UNION
SELECT *
FROM tab2;

ERROR at line 1:
ORA-01789: query block has incorrect number of result columns

SAS bietet hierfür das OUTER UNION CORR.

SELECT * FROM (
SELECT * FROM tab1
OUTER UNION CORR
SELECT * FROM tab2
)
ORDER BY feld3 ASC;

Etwas vergleichbares gibt es in Oracle nicht. Wir müssen die Anzahl der Spalten in den Tabellen also faken.

SQL> SELECT
  feld1,
  feld2,
  feld3,
  null as feld4,
  null as feld5
FROM tab1
UNION
SELECT
  feld1,
  feld2,
  feld3,
  feld4,
  feld5
FROM tab2
ORDER BY feld3 ASC

FELD1      FELD2      FELD3      FELD4      FELD5
---------- ---------- ---------- ---------- ----------
aaaaa      bbbbb      201001
ccccc      ddddd      201001
eeeee      fffff      201001
ggggg      hhhhh      201001
kkkkk      lllll      201001     uuuuu      vvvvv
mmmmm      nnnnn      201001     wwwww      xxxxx
ooooo      ppppp      201001     yyyyy      zzzzz
iiiii      jjjjj      201002
qqqqq      rrrrr      201002     11111      22222
sssss      ttttt      201002     33333      44444

10 rows selected.




Oracle: Führende Leerzeichen bei to_char

21 11 2007

Es sollte ein numerisches Feld selektiert werden. Die enthaltenen Werte konnten maximal vierstellig sein. So weit so gut, mit to_char nicht wirklich ein Problem. Zur Illustrierung des Sachverhalts lege ich eine Tabelle mit ein paar Testdaten an.

SQL> CREATE TABLE testchar (nr number);
TABLE created.

SQL> INSERT INTO testchar VALUES (1);
1 row created.

SQL> INSERT INTO testchar VALUES (10);
1 row created.

SQL> INSERT INTO testchar VALUES (100);
1 row created.

SQL> INSERT INTO testchar VALUES (1000);
1 row created.

SQL> INSERT INTO testchar VALUES (-1);
1 row created.

SQL> SELECT to_char(nr, '0999') FROM testchar;

TO_CHAR(NR,'0999')
------------–
0001
0010
0100
1000
-0001

Wie in der Abfrage zu sehen ist, werden zu kleine Werte entsprechend mit führenden Nullen ausgegeben. Auch erkennt man allerdings ein Leerzeichen bei den positiven Werten. Dies ist ein Platzhalter für das Minuszeichen (-). Bei Abfragen wie der Folgenden, die zusammenhängend dargestellt werden sollen ist dies natürlich ein Problem.

SQL> SELECT '0000' || to_char(nr, '0999') FROM testchar;

'0000'||TO_CHAR(NR,'0999')
------------------------
0000 0001
0000 0010
0000 0100
0000 1000
0000-0001

Versteckt in den Tiefen der Oracle-Dokumentation findet sich glücklicherweise der Hinweis auf das Format “FM”, mit welchem ebendieses Leerzeichen verschwindet. Das Ergebnis sieht gleich sehr viel ansprechender aus.

SQL> SELECT '0000' || to_char(nr, 'FM0999') FROM testchar;

'0000'||TO_CHAR(NR,'FM0999')
------------------------
00000001
00000010
00000100
00001000
0000-0001