Als je een Metin2-server beheert, moet je vroeg of laat de metin2 syserr-bestanden lezen. Wanneer de core crasht, een quest weigert te werken of spelers melden "ik crash telkens als ik teleporteer", zit het antwoord bijna altijd verstopt in deze logregels. Het probleem is dat de meeste mensen syserr openen, in paniek raken en lukraak bestanden gaan bewerken. Maar deze logs worden volgens een specifieke logica geschreven; zodra je die logica doorhebt, kun je de bron van een fout binnen enkele minuten lokaliseren.
Syserr, syslog en de andere logbestanden
Aan de Metin2-serverkant produceert elk core- en databaseproces zijn eigen logbestanden. Om ze niet door elkaar te halen, laten we eerst verduidelijken waar elk voor dient:
- syserr — Je belangrijkste focus. C++-fouten, quest-compile-/runtimefouten, ontbrekende proto-entries en de laatste waarschuwingen vóór een crash komen hier terecht.
- syslog — De normale stroom: spelers die in-/uitloggen, kanaalstarts, periodieke infoberichten. Je weet wanneer een crash plaatsvond aan de hand van waar de syslog stopt.
- de log aan db-kant — De syserr van de DB-core (auth/db); SQL-queryfouten en problemen met het opslaan van spelers verschijnen hier.
Elke core heeft zijn eigen map (meestal channel1/core1, core2, enz.). Om te weten welk kanaal het probleem heeft, moet je naar het bestand in de juiste map kijken. Om een crash live te betrappen, is de klassieke aanpak:
tail -f channel1/core1/syserr
grep -i "error" syserr | tail -n 50
De anatomie van een syserr-regel
Een typische regel ziet er zo uit:
SYSERR: Jun 27 21:14:03 :: pcg::Boot: cannot find proto file Data/object_proto
Laten we hem opsplitsen. De voorste tag SYSERR: vertelt je dat de regel een fout is. Daarna komt de datum en tijd — vergelijk die altijd met de syslog en met het crashtijdstip van de spelers. Vervolgens is er de bronmarkering gescheiden door ::: meestal in de vorm FunctieNaam: of KlasseNaam::Methode. Het laatste deel is het eigenlijke bericht: zaken als "cannot find", "null pointer", "no such", "syntax error". Orden het tijdens het lezen als: wanneer → waar → wat. Zodra je die drie scheidt, beperk je snel uit welk systeem de fout kwam (item, quest, netwerk, DB).
De meest voorkomende foutpatronen
In de loop der jaren zijn er een handvol patronen die je telkens weer in syserr ziet. Hier een paar met hun werkelijke oorzaak:
- QUEST-fouten —
QUEST ... attempt to index a nil valueofattempt to call a nil value. Dit betekent dat je een ongedefinieerde variabele of functie binnen een quest hebt benaderd. Het komt meestal door een verkeerd gespeldepc./npc.-functie of een verwijderde global. - QUEST compile-fout —
LoadStateUserData ... errorof een syntaxisfout in de quest_compile-output. Het Lua-bestand mist eenend, heeft een niet-afgeslotenwhen-blok of een slecht afgesloten string. - Proto / ontbrekende entry —
cannot find item ...ofVID ... mob proto not exist. Er is een mismatch tussen het item- of mob-proto en de DB; een nieuw vnum dat je toevoegde ontbreekt aan één kant. - SQL-fouten — in de DB-syserr:
AsyncSQL ... Unknown columnofDuplicate entry. De tabelstructuur komt niet overeen met het schema dat de core verwacht. - Crash-handtekeningen —
SEGV,signal 11, of de regel die abrupt wordt afgebroken. Dit is een null pointer of toegang tot een beschadigde datastructuur.
Het moment van de crash betrappen
Fixeer je bij crashes niet op één enkele regel. Wat telt zijn de laatste paar regels vlak vóór de crash. Wat deed het proces voordat het stierf? Spawnde het een mob, laadde het een quest, of liet het een speler inloggen? Heel vaak zit de bewerking die de crash veroorzaakte verstopt in de laatste SYSERR-regel of in de waarschuwing er net boven.
In de praktijk doe ik dit: ik neem het crashtijdstip uit de syslog en filter dan de syserr-regels van diezelfde minuut:
grep "Jun 27 21:14" syserr
tail -n 100 syserr
Als de core echt met SEGV sterft en de oorzaak onduidelijk is, is er mogelijk een core dump geproduceerd. Als ulimit -c unlimited is ingesteld, verschijnt er een core.PID-bestand in de crashmap en kun je met gdb een backtrace krijgen:
gdb ./game core.12345
bt full
De backtrace laat je precies zien in welke C++-functie de crash plaatsvond — iets wat syserr alleen je niet kan vertellen.
Het pad naar de grondoorzaak
Wanneer je een foutbericht ziet, volg dan deze volgorde in plaats van in paniek bestanden te bewerken:
- Zoek het bericht letterlijk. Neem de onderscheidende woorden uit de SYSERR-tekst (vnum, functienaam, tabelnaam) en zoek ze in je questbestanden en config met
grep -rn. - Denk aan de laatste wijziging. Is de fout net begonnen? Kijk dan naar wat je het laatst hebt toegevoegd (een nieuw item, een nieuwe quest, een nieuwe mob). Syserr zegt meestal "het zojuist toegevoegde ding is onvolledig gedefinieerd".
- Isoleer het. Schakel de verdachte quest tijdelijk uit, herstart de core en kijk of de syserr opklaart.
- Eén wijziging, één test. Als je vijf bestanden tegelijk bewerkt, weet je nooit welke het heeft opgelost.
Deze discipline verandert "repareren door geluk" in "repareren met methode". Bij het onderhoud van een Metin2-server is dat de waardevolste vaardigheid.
De logs schoon houden
Op een gezonde server is syserr stil. Een syserr die elke dag groeit en vol staat met herhaalde waarschuwingen is ruis die een echte fout verbergt. Repareer onschuldige herhaalde waarschuwingen bij de bron, want wanneer een echte crash komt, wil je hem niet kwijtraken tussen duizenden ruisregels. Archiveer of roteer oude logs regelmatig (logrotate), zodat de bestanden beheersbaar blijven en grep snel blijft.
Veelgestelde vragen
Syserr is leeg maar het spel crasht, wat moet ik doen?
Dit betekent meestal dat het proces abrupt is gestorven voordat het kon schrijven (een harde SEGV). Zorg er eerst voor dat je naar de juiste kanaal-/coremap kijkt, schakel dan core dumps in met ulimit -c unlimited en neem een gdb-backtrace. Op systeemniveau kan dmesg ook een out-of-memory- of segfault-registratie tonen.
Hoe vind ik een QUEST nil value-fout?
Het bericht bevat meestal de questnaam of een regelnummer. Open die quest, kijk welke variabele/functie op de aangegeven regel wordt aangeroepen; hoogstwaarschijnlijk is er een verkeerd gespelde functienaam of een ongedefinieerde global. Vergeet niet de quest opnieuw te compileren en de core te herstarten.
Dezelfde foutregel wordt honderden keren per seconde geschreven?
Dat is een aanhoudende fout binnen een lus — bijvoorbeeld een kapotte mob die blijft respawnen, of een foutieve timer-quest die bij elke tick wordt aangeroepen. Schakel eerst de trigger (mob/quest) uit zodat de log niet opzwelt, en repareer daarna rustig de grondoorzaak.
Syserr lezen betekent stoppen met gokken en naar het bewijs kijken. Als je worstelt met een lastige crash, een vastgelopen core of een questfout die je niet kunt oplossen, kunnen we de logs samen doornemen en het naar de bron herleiden — neem contact met me op.