Linux commando: grep
Vroeg of laat moet je iets vinden in een hooiberg van tekst. Een enkele fout verstopt zich in een logbestand van een miljoen regels. Een instelling staat ergens in een map met honderden configuratiebestanden. Een woord komt voor in een hele broncodemap en je hebt geen idee waar. Voor al die gevallen doet een klein commando het werk in een fractie van een seconde: grep.
1. De basis
De taak van grep is om tekst regel voor regel te lezen en elke regel te tonen die een patroon bevat dat je opgeeft. Dat is het hele idee. Je geeft het een patroon en wat tekst, en het laat je de bijpassende regels zien en verbergt de rest.
De basisvorm van het commando verandert nooit: het woord grep, een patroon, en waar het moet zoeken.
$ grep "error" /var/log/syslog
Jul 7 14:03:11 web1 kernel: [12] EXT4-fs error on device sda1
Het bestand kan een miljoen regels bevatten; grep toont alleen de regels die error bevatten. Al het andere blijft uit je zicht.
Twee dingen maken grep bijzonder. Ten eerste is het veilig: het leest alleen, het verandert nooit een bestand. Je kunt het richten op een logbestand op een productieserver of een systeemconfiguratie zonder iets te kunnen beschadigen. Ten tweede is het snel bij elke omvang van invoer. grep werkt met een regel tegelijk en laadt nooit het hele bestand in het geheugen, dus het doorzoekt een logbestand van tien gigabyte op een kleine server zonder moeite.
grep beantwoordt een duidelijke vraag, "welke regels bevatten dit?", en het beantwoordt die sneller dan welke bestandsbeheerder of teksteditor dan ook.
Naar bovenHet juiste mentale model:
grepis een filter. Tekst stroomt erin, en alleen de regels die bij je patroon passen stromen eruit. Al het andere eromheen, de tientallen opties en de reguliere expressies, is slechts een manier om te beschrijven wat "passen" betekent.
2. Waar komt de naam vandaan?
De naam ziet eruit als willekeurige letters, maar het is een acroniem met een precieze betekenis. Hij komt van een commando in de oude regeleditor ed:
g/re/p = Global / Regular Expression / Print
In ed kon je g/re/p typen om te zeggen: globaal, door het hele bestand, vind elke regel die past bij deze reguliere expressie, en print die. Dat ene editorcommando was zo nuttig dat het uitgroeide tot een programma op zichzelf, en het programma hield de naam.
grep is dus geen verzonnen woord. Elke keer dat je het typt, spel je precies uit wat het doet: zoek overal naar een patroon en print wat je vindt.
Naar bovenDe naam begrijpen geeft je het mentale model cadeau: global (alle regels), regular expression (een patroon, niet zomaar een woord), print (toon de treffers). Dat is het hele commando in drie letters.
3. Een korte geschiedenis
Het verhaal van grep is een van de beroemde anekdotes uit de begintijd van Unix. Begin jaren 70 bij Bell Labs had de editor ed van Ken Thompson al het commando g/re/p. Een collega, Doug McIlroy, moest voor zijn werk tekst op patronen doorzoeken en vroeg Thompson om hulp.
Thompson haalde de code voor reguliere expressies uit ed, verpakte die in een nacht tot een zelfstandig programma en leverde grep de volgende ochtend af. Het verscheen voor het eerst in Version 4 Unix rond 1973. Een gereedschap dat als snelle gunst werd gebouwd, werd een van de meestgebruikte commando's in de informatica.
Naarmate Unix groeide, groeide ook de grep-familie. Twee verwanten arriveerden in Version 7 Unix in 1979: egrep voor een rijkere "extended" patroonsyntaxis, en fgrep voor snel zoeken naar gewone vaste tekst. Later herschreef het GNU-project grep helemaal opnieuw, en GNU grep werd beroemd om zijn snelheid, door slimme algoritmen te gebruiken die over tekst heen springen in plaats van elke afzonderlijke byte te controleren.
| Tijdperk | Mijlpaal |
|---|---|
| ~1973 | Ken Thompson schrijft grep voor Version 4 Unix, uit ed's g/re/p |
| 1979 | egrep (extended) en fgrep (vaste tekst) verschijnen in Version 7 Unix |
| ~1988 | GNU grep arriveert, herschreven voor snelheid door Mike Haertel |
| jaren 90 | POSIX voegt de varianten samen tot een commando: grep -E en grep -F |
| Nu | GNU grep is de standaard op Linux; egrep/fgrep zijn verouderd |
Omdat POSIX de extra gereedschappen in opties samenvoegde, toont modern GNU grep nu een waarschuwing als je egrep of fgrep rechtstreeks draait. De aanbevolen vormen zijn grep -E en grep -F, die precies hetzelfde doen.
4. Eenvoudige toepassingen
4.1 Het eenvoudigst mogelijke gebruik
Geef grep een patroon en een bestand. Het toont elke regel die het patroon bevat.
$ grep "root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
Zet het patroon standaard tussen dubbele aanhalingstekens. Het is niet altijd verplicht, maar het beschermt patronen met spaties of speciale tekens tegen de shell, die anders zou proberen ze te interpreteren voordat grep ze ooit ziet.
4.2 Hoofdletters en kleine letters negeren
Standaard maakt grep onderscheid tussen hoofdletters en kleine letters, dus Error en error zijn verschillend. De optie -i (kort voor ignore-case) laat de zoekopdracht beide vinden:
$ grep -i "warning" application.log
WARNING: disk almost full
Warning: retrying connection
4.3 Regelnummers tonen
De optie -n (kort voor line-number) zet het regelnummer voor elke treffer. Dit wil je bij het doorzoeken van broncode, want dan kun je in een editor meteen naar die regel springen:
$ grep -n "TODO" main.c
42: // TODO: handle the empty case
87: // TODO: free this buffer
4.4 De treffers tellen
Soms wil je het aantal, niet de regels. De optie -c (kort voor count) toont hoeveel regels er passen:
$ grep -c "404" access.log
128
Dit zegt dat 128 regels 404 bevatten, zonder ze alle 128 te printen. Let op: het telt bijpassende regels, niet het totaal aantal treffers, dus twee treffers op een regel tellen nog steeds als een.
4.5 De treffer omkeren
De optie -v (kort voor invert-match) draait de vraag om: het toont de regels die niet passen. Een klassiek gebruik is een configuratiebestand lezen zonder commentaar en lege regels:
$ grep -v "^#" /etc/ssh/sshd_config | grep -v "^$"
Port 22
PermitRootLogin no
PasswordAuthentication no
De eerste grep laat regels weg die met # beginnen, de tweede laat lege regels weg, en je houdt alleen de instellingen over die daadwerkelijk actief zijn.
5. Gemiddelde toepassingen
5.1 Een hele mappenboom doorzoeken
De optie die alles verandert is -r (kort voor recursive, recursief). Die vertelt grep om af te dalen door een map en elke map daarin, en elk bestand te doorzoeken. Als er meer dan een bestand bij betrokken is, zet grep de bestandsnaam voor elke treffer, zodat je weet waar die vandaan komt:
$ grep -rn "database_url" /etc/myapp/
/etc/myapp/config.yml:12:database_url: postgres://localhost/app
/etc/myapp/staging.yml:9:database_url: postgres://localhost/staging
De combinatie van -r en -n samen is wat je het vaakst zult typen als je in code werkt.
Er is een tweede recursieve optie, -R (kort voor dereference-recursive). Die werkt als -r maar volgt ook symbolische links naar andere mappen. Geef de voorkeur aan gewone -r, tenzij je bewust symlinks wilt volgen, want -R kan afdwalen naar plekken die je niet wilde doorzoeken.
5.2 Beperken welke bestanden worden doorzocht
Een heel project doorzoeken graaft ook door afbeeldingen, build-uitvoer en de map .git, wat traag en rommelig is. Twee opties houden de zoekopdracht gericht:
| Optie | Wat het doet |
|---|---|
--include="*.php" |
Doorzoek alleen bestanden waarvan de naam bij het patroon past |
--exclude="*.min.js" |
Sla bestanden over waarvan de naam bij het patroon past |
--exclude-dir=".git" |
Sla een hele map op naam over |
$ grep -rn --include="*.py" --exclude-dir=".git" "import requests" .
./api/client.py:3:import requests
./tests/test_api.py:5:import requests
Je kunt deze opties zo vaak herhalen als je nodig hebt. Deze gerichte vorm is hoe mensen echte projecten snel doorzoeken.
5.3 Alleen de bestandsnamen tonen
Als de bijpassende regel je niet interesseert, alleen welke bestanden het patroon bevatten, gebruik dan -l (kort voor files-with-matches, denk aan "list"). Het toont elke bestandsnaam een keer en stopt met het lezen van dat bestand na de eerste treffer, dus het is snel:
$ grep -rl "api_key" .
./config/secrets.yml
./scripts/deploy.sh
Het tegenovergestelde is -L (kort voor files-without-match), dat de bestanden opsomt die het patroon niet bevatten. Dat is handig om bestanden te vinden waar een verwachte regel ontbreekt, zoals een licentiekop.
5.4 Omringende regels tonen
Een enkele bijpassende regel vertelt vaak niet het hele verhaal. Drie opties voegen context rond elke treffer toe:
| Optie | Betekenis |
|---|---|
-A 3 |
Toon 3 regels erna (after) |
-B 2 |
Toon 2 regels ervoor (before) |
-C 2 |
Toon 2 regels context aan beide kanten (context) |
$ grep -A 4 "Traceback" app.log
Traceback (most recent call last):
File "app.py", line 88, in handle
result = process(data)
File "app.py", line 60, in process
return data["key"]
KeyError: 'key'
Hier verandert -A 4 een enkele "Traceback"-regel in de hele fout, zodat je ziet wat er echt misging.
5.5 Hele woorden en hele regels
Zoeken naar id vindt ook video, hidden en width, omdat die letters binnen die woorden voorkomen. De optie -w (kort voor word-regexp) geeft alleen een treffer wanneer het patroon als heel woord op zichzelf staat:
$ grep -w "id" schema.sql
id INTEGER PRIMARY KEY,
De optie -x (kort voor line-regexp) is nog strenger: de hele regel, van begin tot eind, moet gelijk zijn aan het patroon. Zo vind je een exacte waarde in plaats van een regel die die waarde slechts bevat:
$ grep -x "PermitRootLogin no" /etc/ssh/sshd_config
PermitRootLogin no
Een regel met # PermitRootLogin no zou wel met -w passen maar niet met -x, omdat het commentaar aan het begin de hele regel anders maakt.
6. Gevorderde toepassingen
6.1 Reguliere expressies: de vorm van tekst beschrijven
De "re" in de naam is de echte kracht. In plaats van een vast woord beschrijft een reguliere expressie de vorm van de tekst die je wilt. Een paar bouwstenen dekken de meeste behoeften:
| Patroon | Past op |
|---|---|
^ |
Het begin van een regel |
$ |
Het einde van een regel |
. |
Elk enkel teken |
* |
Nul of meer van het item ervoor |
[abc] |
Een van a, b of c |
[^abc] |
Elk teken behalve a, b of c |
[0-9] |
Elk cijfer |
$ grep "^root" /etc/passwd # regels die met root BEGINNEN
root:x:0:0:root:/root:/bin/bash
6.2 Basic versus extended reguliere expressies
grep heeft twee regex-dialecten. In de standaard basic syntaxis zijn de tekens +, ?, {, |, ( en ) gewone tekst, en moet je er een backslash voor zetten om ze speciaal te maken. De extended syntaxis, ingeschakeld met de optie -E (kort voor extended-regexp), maakt ze speciaal zonder de backslash, wat veel leesbaarder is.
$ grep "colou\?r" file.txt # basic: de ? moet worden ge-escaped
$ grep -E "colou?r" file.txt # extended: geen backslash nodig
Beide vinden color en colour. De meeste mensen grijpen naar -E zodra een patroon meer wordt dan een gewoon woord. Het teken |, dat "of" betekent, is de meest voorkomende reden:
$ grep -E "error|warning|critical" app.log
Dit vindt in een keer elke regel die een van de drie woorden bevat.
Er is een tweede, draagbaardere manier om naar meerdere patronen te zoeken die helemaal geen regex nodig heeft. Met de optie -e (kort voor regexp) geef je elk patroon apart op, en je mag die herhalen:
$ grep -e "error" -e "warning" -e "critical" app.log
Als de lijst met patronen lang wordt, zet ze dan in een bestand, een per regel, en lees ze in met de optie -f (kort voor file, bestand). Zo controleer je een logbestand in een keer tegen een hele lijst bekende slechte IP-adressen of termen:
$ grep -f blocklist.txt access.log
6.3 Kwantoren en echte patronen
Kwantoren zeggen hoe vaak iets mag herhalen: + betekent een of meer, ? betekent nul of een, en {2,4} betekent tussen twee en vier keer. Samengevoegd beschrijven ze echte dingen zoals een IP-adres:
$ grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" access.log
Lees het als: een tot drie cijfers gevolgd door een punt, drie keer, en dan nog een tot drie cijfers.
6.4 Perl-compatibele reguliere expressies
GNU grep biedt een derde, krachtigere engine met de optie -P (kort voor perl-regexp). Die voegt afkortingen toe zoals \d voor een cijfer en \w voor een woordteken, plus geavanceerde functies zoals look-ahead:
$ grep -P "\d{4}-\d{2}-\d{2}" app.log # vind een ISO-datum zoals 2026-07-07
Dit is een GNU-functie en zit niet in de BSD-grep die met macOS wordt geleverd, dus houd het buiten scripts die overal moeten draaien.
6.5 grep in pijplijnen
Als je grep geen bestandsnaam geeft, leest het wat er ook maar in wordt gepijpt. Zo wordt het een universeel filter voor de uitvoer van elk ander commando. Het pijpsymbool | stuurt de uitvoer van het ene commando naar het volgende:
$ ps aux | grep "nginx"
www-data 1243 0.0 0.5 nginx: worker process
www-data 1244 0.0 0.5 nginx: worker process
Je kunt meerdere stappen aan elkaar rijgen, waarbij elke stap versmalt wat de vorige overhield:
$ grep "Googlebot" access.log | grep " 404 "
De eerste stap houdt verzoeken van Google's crawler over, de tweede houdt alleen de verzoeken over die een 404 teruggaven. En gecombineerd met sort en uniq wordt grep een klein rapportagegereedschap:
$ grep -o "GET [^ ]*" access.log | sort | uniq -c | sort -rn | head
842 GET /index.html
317 GET /style.css
96 GET /favicon.ico
De optie -o (kort voor only-matching) print alleen de bijpassende tekst in plaats van de hele regel, zodat sort en uniq -c kunnen tellen hoe vaak elke URL voorkomt.
6.6 Stille modus voor scripts
De optie -q (kort voor quiet, stil) print helemaal niets. Het meldt alleen, via zijn afsluitstatus, of er een treffer is gevonden. Zo stelt een shellscript een ja/nee-vraag:
if grep -q "PermitRootLogin no" /etc/ssh/sshd_config; then
echo "Root login is disabled."
fi
grep stopt bij de eerste treffer met -q, dus dit is ook de snelste manier om te testen of iets bestaat.
7. Iets wat de meeste gebruikers niet weten
7.1 grep spreekt via zijn afsluitcode
Elk commando geeft een getal terug als het klaar is, en scripts lezen dat om te beslissen wat er daarna gebeurt. De meeste gebruikers merken het nooit, maar grep gebruikt drie verschillende waarden, en die kennen verklaart veel "waarom deed mijn script dat"-momenten:
| Afsluitcode | Betekenis |
|---|---|
0 |
Ten minste een regel paste (succes) |
1 |
Geen regel paste (geen fout, gewoon niets gevonden) |
2 |
Een echte fout, bijvoorbeeld een bestand dat niet bestaat |
$ echo hello | grep hi; echo "exit: $?"
exit: 1
De belangrijkste verrassing is dat niets vinden afsluitcode 1 is, niet 0. Een pijplijn die eindigt op een grep die toevallig niets vindt, meldt een mislukking, ook al ging er niets mis. Hier struikelen veel shellscripts over.
7.2 Waarom GNU grep zo snel is
Je zou verwachten dat grep elke byte van een bestand leest. Meestal doet het dat niet. GNU grep gebruikt een familie van algoritmen, waarvan Boyer-Moore de bekendste is, waarmee het vooruit kan springen: het kijkt naar het patroon, berekent hoe ver het veilig kan springen als een teken niet kan passen, en slaat grote stukken tekst over zonder ze te bekijken. Voor een set vaste tekenreeksen gebruikt het Aho-Corasick, en reguliere expressies compileert het tot een snelle toestandsmachine. Het vermijdt ook om de invoer in regels op te splitsen totdat het een waarschijnlijke treffer heeft gevonden. Het resultaat is een gereedschap dat vaak sneller zoekt dan de schijf de gegevens kan aanleveren. Dit is de reden dat een grep door een enorme boom klaar is in de tijd waarin je een laadicoon verwachtte.
De snelste manier om tekst te verwerken is om er het meeste niet naar te kijken. De snelheid van GNU
grepkomt doordat het slim beslist welke bytes het mag negeren.
7.3 Weten waar grep ophoudt
Een deel van vakmanschap is weten wanneer een ander gereedschap beter past. grep vindt regels; wanneer je ze wilt omzetten of er iets mee wilt doen, nemen zijn buren het over:
| Behoefte | Gebruik | Waarom |
|---|---|---|
| Bestanden vinden op naam, grootte of ouderdom | find |
grep doorzoekt inhoud, niet de mappenboom zelf |
| Bijpassende tekst bewerken of vervangen | sed |
grep leest alleen; sed herschrijft |
| Met kolommen werken en rekenen | awk |
Begrijpt velden, niet alleen hele regels |
| Een codebase nog sneller doorzoeken | ripgrep (rg) |
Respecteert .gitignore en is standaard recursief |
Er zijn ook gerichte verwanten die het waard zijn om te kennen: zgrep doorzoekt gzip-gecomprimeerde logbestanden zonder ze uit te pakken (met bzgrep en xzgrep die hetzelfde doen voor .bz2- en .xz-bestanden), en git grep doorzoekt alleen de bestanden die een Git-repository volgt, wat erg snel is en build-uitvoer automatisch overslaat.
7.4 grep en binaire bestanden
Wanneer grep een bestand tegenkomt dat er binair uitziet, zoals een afbeelding of een gecompileerd programma, print het niet de bijpassende bytes, wat je terminal zou kunnen verminken. In plaats daarvan print het een enkele melding:
$ grep "libc" /bin/ls
Binary file /bin/ls matches
Twee opties bepalen dit. De optie -a (kort voor text, tekst) vertelt grep om een binair bestand als gewone tekst te behandelen en de bijpassende regel toch te printen. De optie -I (een hoofdletter i, kort voor ignore binary) doet het tegenovergestelde: het slaat binaire bestanden helemaal over, wat een recursieve zoekopdracht over een gemengde map schoon en rustig houdt:
$ grep -rI "TODO" . # doorzoek de boom, maar open nooit binaire bestanden
Naar boven8. Best practices
- Zet het patroon altijd tussen aanhalingstekens. Dubbele aanhalingstekens, of enkele als het patroon een
$bevat, voorkomen dat de shell je patroon verandert voordatgrephet ziet. - Grijp naar
-rnsamen in code. Recursief zoeken met regelnummers is de dagelijkse combinatie om dingen in een project te vinden. - Versmal grote zoekopdrachten. Gebruik
--includeen--exclude-dirzodat een recursieve zoekopdracht snel blijft en.git, caches en binaire bestanden overslaat. - Gebruik
-ials hoofdlettergebruik onzeker is en-wals je een heel woord wilt. Ze nemen de meeste "waarom paste het daarop"-verrassingen weg. - Gebruik
-Fvoor letterlijke tekst. Als het patroon punten, schuine strepen of een versienummer bevat, voorkomt-F(fixed strings, vaste tekst) dat ze als regex worden behandeld. - Schakel over naar
-Evoor alles met|,+of groepering. Het houdt patronen leesbaar in plaats van een muur van backslashes. - Onthoud de afsluitcode in scripts. Gebruik
-qvoor tests, en onthoud dat "geen treffer" afsluitcode 1 is, geen crash.
Als je de volledige details nodig hebt, is de documentatie een commando ver weg:
$ man grep # de volledige handleiding
$ grep --help # een snel overzicht van elke optie
Naar boven9. Veelgemaakte fouten
9.1 Vier veelvoorkomende mythes
| Mythe | Werkelijkheid |
|---|---|
"grep zoekt naar een gewoon woord." |
Standaard is het patroon een reguliere expressie; ., * en [ zijn speciaal. |
| "Niets vinden betekent een fout." | Geen treffer is afsluitcode 1, wat normaal is, geen mislukking. |
"-c telt elke treffer." |
Het telt bijpassende regels; twee treffers op een regel tellen als een. |
"egrep is de manier om extended regex te doen." |
egrep is verouderd; gebruik in plaats daarvan grep -E. |
9.2 Andere valkuilen om te vermijden
- Patronen zonder aanhalingstekens. Een patroon met een spatie of een
*kan door de shell worden verminkt. Zet het altijd tussen aanhalingstekens. - Speciale tekens die te veel vinden. Zoeken naar
1.5.0vindt ook1x5y0, omdat."elk teken" betekent. Gebruikgrep -F "1.5.0"voor een letterlijke zoekopdracht. -rvergeten bij een map. Richtgrepop een map zonder-ren het klaagt dat het doel een map is en doorzoekt niets.- Extended syntaxis zonder
-E. Een patroon met|of+werkt in basic-modus stilletjes niet zoals bedoeld. Voeg-Etoe, of escape de tekens. - Een deel van een woord vinden. Zoeken naar
idgeeftvideoenwidth. Voeg-wtoe voor hele woorden. - Geheimen op het scherm greppen. Een bestand doorzoeken op een wachtwoord print dat in platte tekst, en het kan in je shell-geschiedenis blijven hangen. Doe het alleen als het moet.
10. Samenvatting
Het commando grep is hoe je dingen vindt in tekst op een Linux-systeem, van een enkele fout in een gigantisch logbestand tot een instelling verborgen in een boom van configuratiebestanden.
grepis een filter: tekst stroomt erin, en alleen de regels die bij je patroon passen stromen eruit.- De naam is een acroniem voor het
ed-commandog/re/p: global, regular expression, print. Ken Thompson schreef het rond 1973 voor Unix. - Het is alleen-lezen en veilig, en het doorzoekt bestanden van elke omvang omdat het met een regel tegelijk werkt.
- Dagelijkse opties:
-i(negeer hoofdletters),-n(regelnummers),-c(tellen),-v(omkeren),-w(heel woord),-x(hele regel). -rdoorzoekt een hele boom;--includeen--exclude-dirhouden het snel en gericht.- Het patroon is een reguliere expressie. Gebruik
-Evoor de makkelijkere extended syntaxis en-Fvoor een letterlijke tekenreeks. - Zonder bestand leest
grepeen pijp, wat het het centrale filter maakt in Linux-commandoketens. - Het meldt via afsluitcodes 0, 1 en 2, en verwanten zoals
zgrep,git grepenripgrepbreiden hetzelfde idee uit. - Bij twijfel typ je
man grepofgrep --help.
Dit is de handige naslag om te bewaren:
grep "text" file toon regels die text bevatten
grep -i "text" file negeer hoofd-/kleine letters
grep -n "text" file toon regelnummers
grep -c "text" file tel bijpassende regels
grep -v "text" file toon regels die NIET passen
grep -rn "text" dir/ doorzoek een hele boom, met regelnummers
grep -rl "text" dir/ toon alleen de bijpassende bestandsnamen
grep -w "word" file vind alleen hele woorden
grep -x "line" file vind alleen hele regels
grep -A3 -B2 "text" f toon 3 regels erna, 2 ervoor bij elke treffer
grep -o "text" file print alleen het bijpassende deel
grep -E "a|b|c" file extended regex (alternatie, +, ?)
grep -e a -e b file meerdere patronen tegelijk
grep -f pats.txt file lees patronen uit een bestand
grep -F "1.5.0" file letterlijke tekst, geen regex
grep -I "text" dir/ sla binaire bestanden over bij het zoeken
grep -q "text" file stil: afsluitcode 0 bij treffer, voor scripts
ps aux | grep name filter de uitvoer van een ander commando
zgrep "text" file.gz zoek in een gecomprimeerd logbestand
Zodra grep vanzelf gaat, houdt een Linux-server op een zwarte doos te zijn. Je kunt een verborgen instelling vinden, een fout door een enorm logbestand traceren en een enkele regel in een woud van code aanwijzen, allemaal binnen enkele seconden. Als jouw systemen logbestanden en bestanden produceren die iemand moet doorzoeken, begrijpen en waarop iemand moet reageren, dan is dat precies het soort werk waar ik graag bij help.


Peter is Joomla specialist en Linux admin voor snelle, veilige en schaalbare websites.


