Das Problem bei der Benutzung von Variablen im Dialplan ist, dass der Wert dieser und überhaupt aller zur Laufzeit definierten Variablen bei einem Systemabsturz oder einem Neustart von Asterisk gelöscht bzw. auf ihre Anfangswerte zurückgesetzt werden. Dadurch sind bestimmte Einsatzszenarien gar nicht denkbar. Wenn man beispielweise eine Call-Forwarding-Funktion[108] oder ein Calling-Card-System implementieren möchte, dann sollten diese natürlich z.B. das Restguthaben in einer Datenbank speichern, damit diese Daten bei einem Neustart des Systems wieder korrekt zur Verfügung stehen.
Bezüglich der Asterisk-Datenbank wird immer wieder die Frage nach der Performance derselben gestellt. Das lässt sich nicht so pauschal beantworten. Falls Sie nur kleine Datenbestände (wie unser Wahlwiederholungsbeispiel) benötigen, so ist die Asterisk-Datenbank sicherlich eine sinnvolle Wahl. Bei größeren und komplexen Datenbeständen sollten Sie aber überlegen, ob das Verwenden einer externen SQL-Datenbank geeigneter ist. Allerdings ist diese Diskussion bei dem überwiegenden Teil aller Anwendungen rein theoretischer Natur, da es sich bei der Asterisk-Datenbank um eine Berkley DB handelt und diese ausreichend performant ist. Tatsächlich ist die Berkley DB, wenn es sich um reine "Key => Value"-Datenpaare handelt, mit die schnellste ihrer Zunft. Sie sollten sich daher diese Frage erst stellen, wenn die Geschwindigkeit der Datenbank nachweislich zu Problemen führt oder Sie eine größere Installation mit umfangreicher Funktionalität aufsetzen wollen.
Asterisk bringt standardmäßig eine Datenbank mit, die die Berkeley DB (BDB)[109] als Datenbank-Engine einsetzt. In dieser Datenbank-Engine wird immer einem Schlüssel (key) ein Wert (value) zugeordnet, wobei Schlüssel in Familien (family) zusammengefasst werden.
Warnung | |
---|---|
Bis einschließlich Asterisk Version 1.2 wurden die folgenden Befehle eingesetzt:
Diese Befehle werden ab der Version 1.4 nicht mehr unterstützt.
Aus diesem Grund wird hier nur die neue Variante über die Funktion
|
Auf diese Datenbank kann mit der Funktion DB()
zugegriffen werden (siehe „DB()
“).
Die Funktion DB()
kann innerhalb der Applikation
Set()
aufgerufen werden. Soll in der Family
obst
der Eintrag apfel
den Wert
20
bekommen, so geschieht das mit folgendem
Aufruf:
exten => 1234,1,Set(DB(obst/apfel)=20)
Die Werte in der Datenbank können mit der Funktion
DB()
in der Form ${DB(family/key)}
abgerufen
werden. Um den Inhalt des Eintrags apfel
in der Family
obst
auf dem Command Line Interface auszugeben, kann man
folgenden Aufruf ausführen:
exten => 1234,1,NoOp(obst/apfel hat den Wert ${DB(obst/apfel)})
Soll der Inhalt dieses Datenbankfeldes in der Variablen
apfelmenge
gespeichert werden, so kann dies mit
Set()
erfolgen:
exten => 1234,1,Set(apfelmenge=${DB(obst/apfel)})
Die beiden Applikationen DBdel()
und
DBdeltree()
können zum Löschen von Datenbankeinträgen
genutzt werden.
In der Asterisk Version 1.2 löscht DBdel()
einen
einzelnen Eintrag in der Datenbank. Soll der Key apfel
in
der Family obst
gelöscht werden, so geschieht das wie
folgt:
exten => 1234,1,DBdel(obst/apfel)
In der Asterisk Version 1.4 ist DBdel() deprecated und man soll die Funktion ${DB_DELETE()} benutzen. Der Aufruf kann wie folgt erfolgen:
exten => 1234,1,NoOp(${DB_DELETE(obst/apfel)})
Siehe
auch „DBdel()
“ und „DB_DELETE()
“.
Soll eine ganze Family gelöscht werden, so verwendet man
DBdeltree()
. Die Family obst
kann mit
exten => 1234,1,DBdeltree(obst)
gelöscht werden.
Siehe auch: „DBdeltree()
“
Vom Command Line Interface (CLI) kann der Administrator ebenfalls auf die Datenbank zugreifen.
Tipp | |
---|---|
Sollte man den entsprechenden Befehl oder die genaue Syntax
vergessen haben, so kann man jederzeit big-island*CLI> help database database del Removes database key/value database deltree Removes database keytree/values database get Gets database value database put Adds/updates database value database show Shows database contents database showkey Shows database contents |
Wichtig | |
---|---|
Denken Sie bei den folgenden Beschreibungen daran, dass Sie, wenn
die Family, der Schlüssel oder der Wert Leerzeichen enthält,
Anführungszeichen ( |
Mit database put
können Werte in die Datenbank geschrieben werden:family
key
value
big-island*CLI> database put obst apfel 20 Updated database successfully
Mit database get
lesen Sie Werte aus der Datenbank
aus:family
key
big-island*CLI> database get obst apfel Value: 20d*CLI>
database del
und family
key
database deltree
löschen Werte aus der
Datenbank.family
Um den Key apfel
aus der Family obst
zu löschen, kann man database del
aufrufen:
big-island*CLI> database del obst apfel Database entry removed.
Mit den Befehlen database show
und database
showkey
kann der Administrator den Inhalt der Datenbank auf dem
CLI ausgeben lassen. Ein Beispiel:
big-island*CLI> database put einkaufsliste eier 2 Updated database successfully big-island*CLI> database put einkaufsliste butter 250 Updated database successfully big-island*CLI> database put einkaufsliste zucker 500 Updated database successfully big-island*CLI> database show /einkaufsliste/butter : 250 /einkaufsliste/eier : 2 /einkaufsliste/zucker : 500 big-island*CLI> database showkey butter /einkaufsliste/butter : 250 big-island*CLI> database deltree einkaufsliste Database entries removed.
Über den Befehl asterisk -rx
'command
' können natürlich alle
CLI-Kommandos auch von einem Shell-Skript ausgeführt werden. Das folgende
Beispiel zeigt, wie man von der Shell aus die Datenbank erst mit Werten
füllt, diese dann ausliest und zum Schluss wieder löscht:
big-island:~# asterisk -rx 'database put test var1 23' Updated database successfully big-island:~# asterisk -rx 'database put test var2 42' Updated database successfully big-island:~# asterisk -rx 'database show test' /test/var1 : 23 /test/var2 : 42 big-island:~# asterisk -rx 'database get test var2' Value: 42 big-island:~# asterisk -rx 'database deltree test' Database entries removed.
Wichtig | |
---|---|
Denken Sie wieder daran, dass Sie, wenn die Family, der
Schlüssel oder der Wert Leerzeichen enthält, Anführungszeichen
( big-island:~# asterisk -rx 'database put test eintrag "Hallo Welt"' |
Die Asterisk-Datenbank wird standardmäßig im Verzeichnis
/var/lib/asterisk/astdb/
gespeichert. Sobald Asterisk
gestoppt ist ist, kann man das Verzeichnis sichern.
Ein Backup im laufenden Betrieb kann auch von der Shell durch folgenden Befehl
asterisk -rx "database show" > /tmp/backup-asterisk-database.txt
durchgeführt werden. Allerdings ist das Restore dann etwas aufwendiger.
Wer bei Abwesenheit alle Gespräche an seine Durchwahl z.B. an sein Handy weiterleiten will, benötigt eine CallForwarding-Funktionalität. Diese kann entweder vom Endgerät (also dem SIP-Telefon) oder zentral von der Telefonanlage realisiert werden. Letztere Variante ist in der Praxis vorzuziehen, da man dadurch unabhängig von den Endgeräten ist (diese also im Zweifelsfall auch austauschen kann) und zusätzlich die gesamte Kontrolle auf dem Server behält. Außerdem ist im Falle eines Stromausfalls die Konfiguration nicht verloren und wird beim nächsten Start der Telefonanlage automatisch wiederhergestellt.
Bei der Apfelmus GmbH soll jeder Mitarbeiter die Möglichkeit bekommen, Gespräche zu seinem Telefon an eine beliebige andere Nummer weiterzuleiten. Um diese Weiterleitung zu aktivieren, muss die interne Rufnummer 44 gefolgt von der Zielrufnummer angerufen werden. Zum Deaktivieren der Weiterleitung muss wieder die 44 (aber diesmal ohne eine weitere Nummer) angerufen werden. Dies wird mit folgendem Wählplan realisiert:
[from-intern] ; Call Forwarding für einen einzelnen Anschluss ; ; aktivieren exten => _44X.,1,Answer() exten => _44X.,n,Set(DB(CF/${CALLERID(num)})=${EXTEN:2}) exten => _44X.,n,SayDigits(${EXTEN:2}) exten => _44X.,n,NoOp(Weiterleitung fuer ${CALLERID(num)} auf ${EXTEN:2} aktiviert.) exten => _44X.,n,Hangup() ; deaktivieren exten => 44,1,Answer() exten => 44,n,DBdel(CF/${CALLERID(num)}) exten => 44,n,Playback(auth-thankyou) exten => 44,n,NoOp(Weiterleitung fuer ${CALLERID(num)} deaktiviert.) exten => 44,n,Hangup() [from-extern] exten => _X.,1,NoOp(Anruf von ${CALLERID(num)} fuer ${EXTEN}) exten => _X.,n,GotoIf($[foo${DB(CF/${EXTEN})} != foo]?normal:forward) exten => _X.,n(normal),Dial(SIP/${EXTEN}) exten => _X.,n(forward),NoOp(Anruf fuer ${EXTEN} wird verbunden zu ${DB(CF/${EXTEN})}) exten => _X.,n,Dial(local/${DB(CF/${EXTEN})})
Diesmal soll in der Apfelmus GmbH jeder Mitarbeiter ein CallForwarding aktivieren können, allerdings soll es ein weiteres CallForwarding für die gesamte Firma geben, damit bei einem Betriebsausflug alle Gespräche an eine andere Niederlassung geleitet werden können. Diese Weiterleitung wird über die Funktionsnummer 55 aktiviert (gefolgt von der Zielrufnummer). Die große Weiterleitung für die gesamte Anlage hat dabei eine höhere Priorität als die einzelnen Regeln. Eine Realisierung kann wie folgt aussehen:
[from-intern] ; CallForwarding für einen einzelnen Anschluss ; ; aktivieren exten => _44X.,1,Answer() exten => _44X.,n,Set(DB(CF/${CALLERID(num)})=${EXTEN:2}) exten => _44X.,n,SayDigits(${EXTEN:2}) exten => _44X.,n,NoOp(Weiterleitung fuer ${CALLERID(num)} auf ${EXTEN:2} aktiviert.) exten => _44X.,n,Hangup() ; deaktivieren exten => 44,1,Answer() exten => 44,n,DBdel(CF/${CALLERID(num)}) exten => 44,n,Playback(auth-thankyou) exten => 44,n,NoOp(Weiterleitung fuer ${CALLERID(num)} deaktiviert.) exten => 44,n,Hangup() ; CallForwarding für die gesamte Telefonanlage ; ; aktivieren exten => _55X.,1,Answer() exten => _55X.,n,Set(DB(CF/anlage)=${EXTEN:2}) exten => _55X.,n,SayDigits(${EXTEN:2}) exten => _55X.,n,NoOp(Weiterleitung der Anlage auf ${EXTEN:2} aktiviert.) exten => _55X.,n,Hangup() ; deaktivieren exten => 55,1,Answer() exten => 55,n,DBdel(CF/anlage) exten => 55,n,Playback(auth-thankyou) exten => 55,n,NoOp(Weiterleitung der Anlage deaktiviert.) exten => 55,n,Hangup() [from-extern] exten => _X.,1,NoOp(Anruf von ${CALLERID(num)} fuer ${EXTEN}) exten => _X.,n,GotoIf($[foo${DB(CF/anlage)} != foo]?cfanlage:zweiteregel) exten => _X.,n(zweiteregel),GotoIf($[foo${DB(CF/${EXTEN})} != foo]?cfnormal:normal) exten => _X.,n(normal),Dial(SIP/${EXTEN}) exten => _X.,n(cfnormal),NoOp(Anruf fuer ${EXTEN} wird verbunden zu ${DB(CF/${EXTEN})}) exten => _X.,n,Dial(local/${DB(CF/${EXTEN})}) exten => _X.,n(cfanlage),NoOp(Anruf fuer ${EXTEN} wird verbunden zu ${DB(CF/anlage)}) exten => _X.,n,Dial(local/${DB(CF/anlage)})
In der Apfelmus GmbH sollen private Gespräche über eine CallingCard abgerechnet werden. Diese wird vom Hausmeister über sein Telefon virtuell aufgeladen (durch Anwahl der internen Servicenummer 88 gefolgt von der 3-stelligen Durchwahl und vom gewünschten Geldbetrag in Euro).[110] Die Gespräche werden zu einem Pauschalpreis von 1 Euro pro Gespräch abgerechnet. Diese privaten Gespräche werden über die interne Servicenummer 99 gefolgt von der Zielrufnummer geführt. Dabei ist zu beachten, dass bei einem Besetzt (busy) kein Geldbetrag vom Konto abgebucht wird. Die interne Rufnummer 98 kann dazu benutzt werden, den aktuellen Betrag auf dem CallingCard-Konto abzurufen.
[from-hausmeister] ; Aufladen der virtuellen CallingCard ; exten => _88XXX.,1,Answer() exten => _88XXX.,2,Set(DB(CallingCard/${EXTEN:2:3})=${EXTEN:5}) exten => _88XXX.,3,SayNumber(${EXTEN:5}) exten => _88XXX.,4,NoOp(CallingCard fuer ${EXTEN:2:3} mit ${EXTEN:5} aufgeladen.) exten => _88XXX.,5,Hangup() [from-intern] ; private Gespraeche ; exten => _99.,1,GotoIf($[${DB(CallingCard/${CALLERID(num)} > 0]?2:200) exten => _99.,2,Set(DB(CallingCard/${CALLERID(num)})=$[DB(CallingCard/${CALLERID(num)}) - 1]) exten => _99.,3,Dial(local/${EXTEN:2}) exten => _99.,104,Set(DB(CallingCard/${CALLERID(num)})=$[DB(CallingCard/${CALLERID(num)}) + 1]) exten => _99.,200,NoOp(CallingCard Konto ${CALLERID(num) ist leer.) exten => _99.,201,Answer() exten => _99.,202,SayNumber(0) exten => _99.,203,Hangup() ; Mit der 98 kann der aktuelle Kontostand abgefragt werden. ; exten => 98,1,Answer() exten => 98,2,SayNumber(${DB(CallingCard/${CALLERID(num)})}) exten => 98,3,Hangup()
[108] CallForwarding-Funktionalität: Jeder Teilnehmer kann durch Wahl einer bestimmten Nummer alle Gespräche an einen anderen Apparat weiterleiten lassen. Durch Wahl einer anderen Nummer wird diese Funktion wieder deaktiviert.
[109] Die Berkeley-Datenbank (Berkeley DB) ist eine hochperformante, eingebettete Datenbank-Bibliothek mit Programmierschnittstellen zu C, C++, Java, Perl, Python, Tcl und vielen weiteren Programmiersprachen. Die DB speichert beliebige Schlüssel- oder Datenpaare und unterstützt mehrere Datenelemente für einen einzelnen Schlüssel. Die DB ermöglicht tausende von simultanen Threads zum Manipulieren der Datenbanken, die bis zu 256 Terabyte groß sein können, und läuft auf einer großen Anzahl von Systemen, unter anderem auf den meisten UNIX-artigen und Windows-Systemen und auch auf Echtzeitbetriebssystemen. [Zitiert aus http://de.wikipedia.org/wiki/Berkeley_DB]
[110] Um das Beispiel möglichst einfach zu halten, wird der Fall, dass auf ein bereits bestehendes CallingCard-Konto ein weiterer Betrag eingezahlt wird (also eine Addition vollzogen werden muss) nicht besprochen. Ebenfalls nicht behandelt wird die Möglichkeit, dass ein Mitarbeiter von einem anderen Telefon ein privates Gespräch führen könnte.
Version 1.2, November 2002
Neue Version verfügbar
Sie betrachten gerade die alte Version des Buches (Version 1.0). Wir empfehlen Ihnen für Asterisk 1.4 und 1.6 die neue Version des Buches.
Asterisk-Tag 2008
Lernen Sie Mark Spencer (den Erfinder von Asterisk) kennen! Viele Vorträge, Case-Studies und Workshops rund um das Thema VoIP. Asterisk-Tag.org