diff --git a/README.md b/README.md index 32ccd5a..bccf584 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,38 @@ ## Debug Console - cfadmin debug console + 基于`cfadmin`实现的终端调试库. -## 使用介绍 +## 安装介绍 - 1. 将当前库克隆到`3rd`目录下. + 1. 将代码克隆到`3rd`目录下. - 2. 导入`local console = require "debug.console"`库. + 2. 使用`local console = require "debug.console"`导入. - 3. 使用`console.start('127.0.0.1', 6666)`代码启动. +## 启动方式 - 4. 使用在终端使用命令`nc localhost 6666`进行连接 + 内部支持以下两种连接方式: -## 内部演示 + 1. 监听端口 - `console.start("127.0.0.1", 6666)` - 以下内容仅做参考, 实际功能以后续版本迭代为主. + 2. 监听文件 - `console.start("loca.sock")` + 第`1`种只能支持单进程模式, 第`2`种可自行配置文件名后支持多进程模式. + +## 使用方法 + + 我们在`script/main.lua`内写入以下内容: ```lua --- main.lua -local console = require "debug.console" -console.start('127.0.0.1', 6666) --- Do anything you want to. +local console = require "debug.console" +console.startx("local.sock") ``` -```shell -[candy@MacBookPro:~] $ nc 127.0.0.1 6666 + 然后运行`./cfadmin -e script/main.lua`启动即可.(实际业务里只需要把代码写在最终启动之前即可) + + 最后我们在命令行运行`nc -U local.sock`, 如看到如下输出则代表连接成功. + +```bash +[candy@MacBookPro:~/Documents/cfadmin] $ nc -U local.sock Welcome! This is cfadmin Debug Console: @@ -33,7 +40,315 @@ Welcome! This is cfadmin Debug Console: run - Execute the lua script like `main` coroutine. - dump - Prints more information about the specified data structure. + dump - Prints more information about the specified data structure. ->>> + stat - Process usage data analysis report. + +>>> ``` + + * `stat` - 输出进程使用状态 + + * `run` - 启动指定文件名的脚本 + + * `dump` - 可以格式化输出一些指定数据结构 + + * `gc` - 允许用户手动操作`GC` + +### 1. 查看进程状态 + + 我们运行`stat`, 然后会输出一些使用帮助. + +```bash +>>> stat + +stat [command] : + + [cpu] - CPU kernel space and user space usage of the current process. + + [mem] - Memory usage report of the current process. + + [page] - `hard_page_fault` and `soft_page_fault` of the current process. + + [all] - Return all of the above information. + +>>> +``` + + 使用`stat all`则可以输出所有内容. 如下所示: + +```bash +>>> stat all + +CPU(User): 0.40% + +CPU(Kernel): 0.33% + +Lua Memory: 239.7256/KB + +Swap Memory: 0.0000/KB + +Total Memory: 2.1720/MB + +Hard Page Faults: 0 + +Soft Page Faults: 739 + +>>> +``` + + 其它命令参数只会输出指定内容. + +### 2. 查看内部数据 + + 有时候我们需要查看Lua内部的一些数据, 这时候可以使用`dump`来完成: + +```bash +>>> dump + +dump [command] [key1] [key1] [keyN] : + + [global] - dump global table (`_G`). + + [registery] - dump lua debug registery table. + + [filename] - dump already loaded package and its return table . + + -- + + `keyX` means we can get `deep value` like `table[key1][key2]..[keyN]` + + e.g : + 1. dump cf wait + 2. dump global string + +>>> +``` + + 比如我们要打印全局表`_G`,看下内部有`Key`存在. 那么我们可以这样: + +```bash +>>> dump g + +global{ + ['tonumber'] = function: 0x107b22ec0 + ['error'] = function: 0x107b22550 + ['setmetatable'] = function: 0x107b22e20 + ['string'] = table: 0x7ffd8b508120 + ['pcall'] = function: 0x107b229b0 + ['rawset'] = function: 0x107b22d10 + ['rawget'] = function: 0x107b22cc0 + ['print'] = function: 0x107b22a40 + ['os'] = table: 0x7ffd8b5070f0 + ['io'] = table: 0x7ffd8b507620 + ['loadfile'] = function: 0x107b22670 + ['require'] = function: 0x7ffd8b506bb0 + ['coroutine'] = table: 0x7ffd8b5071b0 + ['utf8'] = table: 0x7ffd8b506870 + ['assert'] = function: 0x107b22280 + ['pairs'] = function: 0x107b22920 + ['rawequal'] = function: 0x107b22c10 + ['collectgarbage'] = function: 0x107b22300 + ['warn'] = function: 0x107b22b50 + ['table'] = table: 0x7ffd8b507420 + ['NULL'] = userdata: 0x0 + ['null'] = userdata: 0x0 + ['debug'] = table: 0x7ffd8b5073c0 + ['tostring'] = function: 0x107b23110 + ['math'] = table: 0x7ffd8b508850 + ['load'] = function: 0x107b22750 + ['ipairs'] = function: 0x107b22620 + ['_G'] = table: 0x7ffd8b505c30 + ['rawlen'] = function: 0x107b22c60 + ['type'] = function: 0x107b23140 + ['next'] = function: 0x107b228c0 + ['_VERSION'] = 'Lua 5.4' + ['dofile'] = function: 0x107b224e0 + ['select'] = function: 0x107b22d70 + ['package'] = table: 0x7ffd8b506510 + ['getmetatable'] = function: 0x107b225d0 + ['xpcall'] = function: 0x107b231a0 +} + +counter: + total keys count: 37 + string value count: 1 + function value count: 24 + usedata value count: 2 + table value count: 10 + +Done. +>>> +``` + + 是的! 你没有看错. 如果打印的是一个`table`则会对内部进行统计完成数据化返回. + + 那么如果是一个函数呢? 如果函数是`lua`编写的, 那么`dump`可以定位到文件位置: + +```bash +>>> dump g package loaded debug.console + +debug.console{ + ['startx'] = function: 0x7ffd8b4118a0(3rd/debug/console.lua:86) + ['start'] = function: 0x7ffd8b415760(3rd/debug/console.lua:76) +} + +counter: + total keys count: 2 + function value count: 2 + +Done. +>>> +``` + + 那如果想看一下`注册表`呢? 可以把`g`改为`r`来查看注册表的内容: + +```bash +>>> dump r + +registery{ + [1] = thread: 0x7ffd8c009a08 + [2] = table: 0x7ffd8b505c30 + ['__Task__'] = table: 0x7ffd8b406620 + ['FILE*'] = table: 0x7ffd8b507920 + ['_IO_input'] = file (0x7fff975c5d90) + ['__G_UDP__'] = table: 0x7ffd8b510360 + ['_LOADED'] = table: 0x7ffd8b5062f0 + ['_UBOX*'] = table: 0x7ffd8b708c30 + ['_PRELOAD'] = table: 0x7ffd8b507090 + ['_IO_output'] = file (0x7fff975c5e28) + ['__G_TCP__'] = table: 0x7ffd8b413ca0 + ['__TCP__'] = table: 0x7ffd8b5145f0 + ['__TIMER__'] = table: 0x7ffd8b409880 + ['_CLIBS'] = table: 0x7ffd8b506b70 + ['__G_TIMER__'] = table: 0x7ffd8b40a0a0 + ['__UDP__'] = table: 0x7ffd8b5102e0 +} + +counter: + total keys count: 16 + usedata value count: 2 + thread value count: 1 + table value count: 13 + +Done. +>>> +``` + + 从这里可以看到, 语法就是`keyname` + `空格`的方式. + + 这样也方便使用者可以快速定位, 增加运行时定位问题的一些能力. + +### 3. 运行调试代码 + + 假设我们的代码有一个隐藏的`bug`, 但是每次重启后就无法定位了. + + 并且每次启动一段时间内也没问题, 而一旦**某个时间点**或**某个特殊条件成立**就出现了. + + 这时候我们就需要更多**运行时调试**的能力, 但是这时候我们并不`attach`来影响进程的执行能力. + + 所以我们的框架必须提供一种**任何时候都能安全执行代码**的能力! + + 现在让我们编写一个`script/demo.lua`的文件并写入如下的代码: + +```lua +local function f1() + print("f1") +end + +local function f2() + print("f2") +end + + +local function f() + f1() + f2() +end + +f() +``` + + 编写完成后, 我们就尝试在运行中的框架内执行这个脚本: + +```bash +>>> run script/demo.lua + +Total Running Time: 0.000 +Done. +>>> +``` + + 然后你会发现之前我们启动的框架那边输出了2行内容. + +```bash +[candy@MacBookPro:~/Documents/cfadmin] $ ./cfadmin +f1 +f2 +``` + + 这就说明我们的代码运行成功了! + + 但是这并不够! 因为有时候我们还需要运行的这段脚本只执行过程是什么. + + 这时候我们可以在最后加上一个参数, 则会补充输出运行的脚本调用栈. + +```bash +>>> run script/demo.lua true +callstack traceback: + └----> [OK] [NEXT LINE] [script/demo.lua:3] + └----> [OK] [NEXT LINE] [script/demo.lua:7] + └----> [OK] [NEXT LINE] [script/demo.lua:13] + └----> [OK] [NEXT LINE] [script/demo.lua:15] + └--------> [OK] [NEXT LINE] [script/demo.lua:11] + └------------> [OK] [NEXT LINE] [script/demo.lua:2] + └------------> [OK] [NEXT LINE] [script/demo.lua:3] + └------------> [OK] [GOTO BACK] [script/demo.lua:3] + └--------> [OK] [NEXT LINE] [script/demo.lua:12] + └------------> [OK] [NEXT LINE] [script/demo.lua:6] + └------------> [OK] [NEXT LINE] [script/demo.lua:7] + └------------> [OK] [GOTO BACK] [script/demo.lua:7] + └--------> [OK] [NEXT LINE] [script/demo.lua:13] + └--------> [OK] [GOTO BACK] [script/demo.lua:13] + └----> [OK] [GOTO BACK] [script/demo.lua:15] + └----> [OK] [NEXT LINE] [3rd/debug/run.lua:83] + └----> [OK] [NEXT LINE] [3rd/debug/run.lua:84] + +Total Running Time: 0.000 +Done. +>>> +``` + +### 4. 开始调试GC + + 一般情况下`GC`都会工作的很好, 而我们无需特意去干预它的执行. + + 但有时候我们想尝试对其进行一些特殊操作, 以借助这些修改来观察其运行差异. + + 这时候我们就需要利用到它的一些命令: + +```bash +>>> gc + +gc [command] [args]: + + [count] - Let the garbage collector report memory usage. + + [step] - Let the garbage collector do a step garbage collection. + + [collect] - Let the garbage collector do a full garbage collection. + + [start] - Let the garbage collector (re)start. + + [stop] - Let the garbage collector stop working. + + [mode] - Let the garbage change work mode(`incremental` or `generational`). + +>>> +``` + + 运行期间的垃圾收集器很敏感! 除非十分清除自己在干什么, 否则请不要随意干预它. + +## 获取帮助 + + 有其它任何疑问, 请到我们的框架交流群内咨询. \ No newline at end of file