进程执行追踪命令strace的详细参数及使用及曾经用于开发测试调试的一些 Lua 代码包括Lua显示table、table转string、动态加载模块等

一、进程执行追踪命令strace的详细参数及使用

    strace常用来跟踪进程执行时的系统调用和所接收的信号。Linux看进程不能直接访问硬件设备,当需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式,通过系统调用访问硬件设备。strace可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间。

1. strace命令的各参数备注如下:

-c 统计每一系统调用的所执行的时间,次数和出错的次数等. 
-d 输出strace关于标准错误的调试信息. 
-f 跟踪由fork调用所产生的子进程. 
-ff 如果提供-o filename,则所有进程的跟踪结果输出到相应的filename.pid中,pid是各进程的进程号. 
-F 尝试跟踪vfork调用.在-f时,vfork不被跟踪. 
-h 输出简要的帮助信息. 
-i 输出系统调用的入口指针. 
-q 禁止输出关于脱离的消息. 
-r 打印出相对时间关于,,每一个系统调用. 
-t 在输出中的每一行前加上时间信息. 
-tt 在输出中的每一行前加上时间信息,微秒级. 
-ttt 微秒级输出,以秒了表示时间. 
-T 显示每一调用所耗的时间. 
-v 输出所有的系统调用.一些调用关于环境变量,状态,输入输出等调用由于使用频繁,默认不输出. 
-V 输出strace的版本信息. 
-x 以十六进制形式输出非标准字符串 
-xx 所有字符串以十六进制形式输出.
-a column   设置返回值的输出位置.默认 为40. 
-e expr   指定一个表达式,用来控制如何跟踪
-o filename   将strace的输出写入文件filename 
-p pid 跟踪指定的进程pid. 一般用于跟踪后台程序
-s strsize 指定输出的字符串的最大长度.默认为32. 
-u username  以username 的UID和GID执行被跟踪的命令

2. strace命令执行示例:

[on@B4471 ~]$ ps -ef | grep php
root     10984     1  0 19:13 ?        00:00:00 php-fpm: master process (/opt/soft/php7/etc/php-fpm.conf)
www      10985 10984  0 19:13 ?        00:00:00 php-fpm: pool www              
www      10986 10984  0 19:13 ?        00:00:00 php-fpm: pool www
#追踪线程 10985,如下会列出执行过程中的系统调用函数
[on@B4471 ~]$ strace -p 10985 
fstat(10, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
lseek(10, 0, SEEK_CUR)                  = 0
write(10, "{\"url\":\"http:\\/\\/newapi.shouji.b"..., 3790) = 3790
close(10)                               = 0
chdir("/home/onlinedev")                = -1 EACCES (Permission denied)
times({tms_utime=3, tms_stime=0, tms_cutime=0, tms_cstime=0}) = 3013530754
setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={0, 0}}, NULL) = 0
fcntl(3, F_SETLK, {type=F_UNLCK, whence=SEEK_SET, start=0, len=0}) = 0
write(4, "\1\6\0\1\0\6\2\0000\"}}]}\0\0\1\3\0\1\0\10\0\0\0\0\0\0\0.10", 32) = 32
shutdown(4, SHUT_WR)                    = 0
recvfrom(4, "\1\5\0\1\0\0\0\0", 8, 0, NULL, NULL) = 8
recvfrom(4, "", 8, 0, NULL, NULL)       = 0
close(4)                                = 0
munmap(0x7f7838000000, 2097152)         = 0
setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={0, 0}}, NULL) = 0
accept(0,

上面显示的就是php线程执行时执行的系统函数。

3. 常见系统调用函数列表如下:

fork        创建一个新进程  
clone       按指定条件创建子进程  
execve      运行可执行文件  
exit        中止进程 
nanosleep   使进程睡眠指定的时间 
pause       挂起进程,等待信号 
wait        等待子进程终止   
waitpid     等待指定子进程终止  
socket      建立socket  
bind        绑定socket到端口  
connect     连接远程主机  
accept      响应socket连接请求  
send        通过socket发送信息  
recv        通过socket接收信息  
mmap        映射虚拟内存页
munmap      去除内存页映射  
mremap      重新映射虚拟内存地址   
msync       将映射内存中的数据写回磁盘   
listen      监听socket端口  
select      对多路同步I/O进行轮询  
shutdown    关闭socket上的连接  
readv       从文件读入数据到缓冲数组中  
writev      将缓冲数组里的数据写入文件  
pread       对文件随机读  
pwrite      对文件随机写  
lseek       移动文件指针    
dup         复制已打开的文件描述字    
flock       文件加/解锁   
poll        I/O多路转换   
truncate    截断文件 

另外strace的-e trace选项详细
-e trace=file     跟踪和文件访问相关的调用(参数中有文件名)
-e trace=process  和进程管理相关的调用,比如fork/exec/exit_group
-e trace=network  和网络通信相关的调用,比如socket/sendto/connect
-e trace=signal    信号发送和处理相关,比如kill/sigaction
-e trace=desc  和文件描述符相关,比如write/read/select/epoll等
-e trace=ipc 进程见同学相关,比如shmget等

4. strace其它应用示例

1.跟踪nginx, 看其启动时都访问了哪些文件    strace -tt -T -f -e trace=file -o /data/log/strace.log -s 1024 2>&1 ./nginx
2. 定位程序异常退出    strace -ttf -T -p 10893 -o tmp -e trace=process 2>&1
3.程序启动加载文件    strace -e open,acces ./sh 2>&1 | grep fileName
4. 查选程序耗时    strace -c -p 11084
5.链接服务器失败    strace -e poll,select,connect,recvfrom,sendto nc www.baidu.com 80 

二、曾经用于开发测试调试的一些 Lua 代码包括Lua显示table、table转string、动态加载模块等

1. 显示数据的函数,包括显示table,  显示table时递归调用的函数

-----------------------------------
--Note  :工具函数类
--Author:linge
--Time  :2016-06-15
-----------------------------------

--1,显示数据的函数,包括显示table,
function show(t)
    if(type(t) ~= 'table') then
        print(t)
    else
        print(_show_table(t, 1))
    end
end

--2,显示table时递归调用的函数
function _show_table(t, level)
    local show = ''
    local temp = ''
    local space = string.rep(' ', (level-1)*4)
    local sapce4 = string.rep(' ', 4)
    if(type(t) ~= 'table') then
        return 'error: params t is not a table.'
    else
        --取得表名
        show = show .. tostring(t) .. "{\n" .. space
        for k,v in pairs(t) do
            if type(v) == 'table' then
                temp = _show_table(v, level+1)
            elseif(type(v) == 'string') then
                temp = '\"' .. tostring(v) .. '\"'
            else
                temp = tostring(v)
            end
            show = show .. sapce4 .. tostring(k) .. " = " .. temp .. ",\n" .. space
        end
        show = show .. "}"
    end
    return show
end




local config = require "4requiredata"
local config ={10,20,30}

function unpacks(t, i)
    i = i or 1
    if t[i] then
        return t[i], unpacks(t, i+1)
    end
end
print(unpacks(config))

2. 把table转换成string字符串的方法

function table_tostring(tb)
    if type(tb) ~= "table" then
        error("Sorry, it's not table, it is " .. type(tb) .. ".")
    end

    local ret = " = {\n"
    local table_list = {}
    table_list[tb] = "root table"
    ret = ret .. _list_table(tb, table_list, 1)
    ret = ret .. "}"
    return ret
end

function _list_table(tb, table_list, level)
    local ret = ""
    local indent = string.rep(" ", level*4)

    for k, v in pairs(tb) do
        local quo = type(k) == "string" and "\"" or ""
        ret = ret .. indent .. "[" .. quo .. tostring(k) .. quo .. "] = "

        if type(v) == "table" then
            local t_name = table_list[v]
            if t_name then
                ret = ret .. tostring(v) .. " -- > [\"" .. t_name .. "\"]\n"
            else
                table_list[v] = tostring(k)
                ret = ret .. "{\n"
                ret = ret .. _list_table(v, table_list, level+1)
                ret = ret .. indent .. "}\n"
            end
        elseif type(v) == "string" then
            ret = ret .. "\"" .. tostring(v) .. "\"\n"
        else
            ret = ret .. tostring(v) .. "\n"
        end
    end

    local mt = getmetatable(tb)
    print(mt)
    if mt then
        ret = ret .. "\n"
        local t_name = table_list[mt]
        ret = ret .. indent .. "<metatable> = "

        if t_name then
            ret = ret .. tostring(mt) .. " -- > [\"" .. t_name .. "\"]\n"
        else
            ret = ret .. "{\n"
            ret = ret .. _list_table(mt, table_list, level+1)
            ret = ret .. indent .. "}\n"
        end

    end

   return ret
end

local con = require "4requiredata"
print(tostring(con) .. table_tostring(con))

3. 工具函数类-动态加载模块函数 加载一些核心table、辅助table等

-----------------------------------
--Note  :工具函数类-开发
--Author:linge
--Time  :2016-06-15
-----------------------------------

package.path = 'E:/Lnmp/www/Default/danmu/danmu_lyl/?.lua;'
--1.2,加载模块函数
function load_module(module_name)
    local m = nil
    local _, err = pcall(function(mod)
            m = require(mod)
    end, module_name)
    return m, err
end

--1.3,加载一些核心table、辅助table等
_,err = load_module("library/json")
if err then
    print(err)
end

local data = {
    message1 = {
        text = 'hello',
        showtime = '12000',
    },
    message2 = {
        text = 'test',
        showtime = '15000',
        message3 = {
            name = 'kermit',
            age = 1234,
            message4 = {
                level4 = 'ddd'
            }
        },
        bool = true
    }
}

print(json.encode(data))

4. lua直接向redis插入数据

-----------------------------------
--Note  :弹幕添加测试数据:直接向redis插入数据
--Author:linge
--Time  :2016-06-16
-----------------------------------
package.path = '/opt/data/danmu/branches/danmu_lyl/?.lua;'
local help = require "library/help"

--设4个影片,ID如下
local video_ids  = { 2300, 2301, 2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309 }
math.randomseed(tostring(os.time()):reverse():sub(1, 6))

--弹幕要有顺序,同时要在一个集合中, 取值时能按键取值
--在redis里,hash,list,sortset可考虑。目前来看有序集合适合。

--zset
--键前五位为秒值:预留86400五位做秒值
--键后二位为帧值:目前不超过30帧,2位可保证99帧的视频
--键最后二位为随机数:11-99之间,
--如此要取视频第1秒到第3秒的弹幕,只要取  10000 < 键值 <   30000的值出来。
--要取1小时0分0秒到1小时0分3秒,只要取 36010000 < 键值 <36030000的值出来。
--

function utfstrlen(str)

    local len = #str;
    local left = len;
    local cnt = 0;
    local arr={0,0xc0,0xe0,0xf0,0xf8,0xfc};
    while left ~= 0 do
        local tmp=string.byte(str,-left);
        local i=#arr;
        while arr[i] do
            if tmp>=arr[i] then left=left-i;break;end
            i=i-1;
        end
        cnt=cnt+1;
    end
    return cnt;

end

--随机取一段中文
text = '如你所见主节点对命令的复制工作发生在返回命令回复之后因为如果每次处理命令请求都需要等待复制操作完成的话那么主节点处理命令请求的速度将极大地降低我们必须在性能和一致性之间做出权衡'
length = utfstrlen(text)

--随机取几个汉字出来当做评论
function get_chinese_char(num)
    local chars = ''
    for i = 1,num do
        local index = math.random(1, length)
        local start = (index-1) * 3 + 1
        chars =  chars .. text:sub(start, start + 2)
    end
    return chars
end

--连接redis
local redis = require 'library.redis'
local config = require 'config.config'
local msgpack = require 'cmsgpack'
local queue = redis:new()
queue:set_timeout(config.storage.queue_redis.connect_timeout)
local ok, err = queue:connect(config.storage.queue_redis.host, config.storage.queue_redis.port)
if not ok then
    return ngx.say(err)
end


ngx.say('<h2>向redis插入1000条测试数据,分布wid:13,aid:160000,vid:2300~2309随机 弹幕帧:0-3600内</h2>')
ngx.say('<h3>-------------first 2 records:</h3>')
--随机生成多条弹幕
for i =1,1000 do
    local index = math.random(1,10)
    local time = math.random(0,3600)  --预留5位给秒值,范围缩小点,不写86400
    local frame = math.random(11,30)
    local text_num = math.random(5,15)
    local params = {
        uid = '{2D58D7B0-A49C-907F-39AE-9C70CBEB8F3B}',
        movieid = 111111,           --暂时无movieid
        aid = 160000,
        vid = video_ids[index],
        wid = 13,
        time = time,
        text = get_chinese_char(text_num),
        font = 2,
        color = 16711813,
        mod = 1,
        nt = os.time()
    }

    --添加测试数据进入redis
    local list_key = 'dm_' .. params.wid ..'_'.. params.aid ..'_'.. params.vid
    local list_score = tonumber(params.time .. math.random(10,99))
    queue:zadd(list_key, list_score, msgpack.pack(params))

    --加入的前2条数据格式
    if i <=2 then
        ngx.say(help.html(params) .. "<br>")
    end
end

--读取统计数据:
local dm_keys = queue:keys('dm_*')
ngx.say('<h3>-------------插入后当前Redis中弹幕存储量:</h3>')
local all_dm = 0
for i,dmkey in pairs(dm_keys) do
    local tempnum = queue:zcard(dmkey)
    ngx.say('sortedset key:' .. dmkey .. " ,弹幕量:" .. tempnum .."<br>" )
    all_dm = all_dm + tempnum
end
ngx.say('<br><b>弹幕总量:' .. all_dm .. "</b>")

queue:set_keepalive(config.storage.queue_redis.keepalive_timeout, config.storage.queue_redis.pool_size)

5. lua向redis 添加 弹幕测试数据

    新的弹幕服务器端区别于4的内容,设4个影片,ID如下。随机取一段中文,随机取几个汉字出来当做评论,随机生成多条弹幕,预留5位给秒值,范围缩小点,不写86400,向redis注入几十万条弹幕。读取统计数据。

-----------------------------------
--Note  :弹幕添加测试数据:
--Author:linge
--Time  :2016-06-18
-----------------------------------
package.path = '/opt/baofeng-data/danmu/branches/danmu_lyl/?.lua;'
local help = require "library/help"

--设4个影片,ID如下
local video_ids  = { 2300, 2301, 2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309 }
math.randomseed(tostring(os.time()):reverse():sub(1, 6))

function utfstrlen(str)

    local len = #str;
    local left = len;
    local cnt = 0;
    local arr={0,0xc0,0xe0,0xf0,0xf8,0xfc};
    while left ~= 0 do
        local tmp=string.byte(str,-left);
        local i=#arr;
        while arr[i] do
            if tmp>=arr[i] then left=left-i;break;end
            i=i-1;
        end
        cnt=cnt+1;
    end
    return cnt;

end

--随机取一段中文
text = '如你所见主节点对命令的复制工作发生在返回命令回复之后因为如果每次处理命令请求都需要等待复制操作完成的话那么主节点处理命令请求的速度将极大地降低我们必须在性能和一致性之间做出权衡'
length = utfstrlen(text)

--随机取几个汉字出来当做评论
function get_chinese_char(num)
    local chars = ''
    for i = 1,num do
        local index = math.random(1, length)
        local start = (index-1) * 3 + 1
        chars =  chars .. text:sub(start, start + 2)
    end
    return chars
end

--连接redis
local redis = require 'library.redis'
local config = require 'config.config'
local msgpack = require 'cmsgpack'
local queue = redis:new()
queue:set_timeout(config.storage.queue_redis.connect_timeout)
local ok, err = queue:connect(config.storage.queue_redis.host, config.storage.queue_redis.port)
if not ok then
    return ngx.say(err)
end

ngx.say('<h2>向redis插入1000条测试数据,分布wid:13,aid:160000,vid:2300~2309随机 弹幕帧:0-3600内</h2>')
ngx.say('<h3>-------前10条请求:</h3><h5 style="font-weight:normal;">')
local success,fail = 0, 0
--随机生成多条弹幕
for i =1,10 do
    --随机vid
    local index = math.random(1,10)
    local vid = video_ids[index]
    --随机帧值
    local time = math.random(0,3600)  --预留5位给秒值,范围缩小点,不写86400
    --随机内容
    local text_num = math.random(5,15)
    local text = i .. "--" .. get_chinese_char(text_num)     --内容前加数值好判断谁在前谁在后

    --URL拼接
    local url = 'http://danmul.linge.com/up?uid={2D58D7B0-A49C-907F-39AE-9C70CBEB8F3B}&movieid=11111&aid=160000&font=2&color=16711813&mod=1&wid=13'..'&vid='.. vid ..'&time='.. time ..'&text='.. text
    --加入的前2条数据格式
    if i <= 10 then
        ngx.say(help.html(url) .. "<br>" .. string.rep('-', 200) .. "<br>")
    end

    --请求URL
    os.execute('curl "'.. url ..'"')
    --[[if exec_rs == '0' then
        success = success +1
    else
        fail = fail +1
    end]]


end
    ngx.say("curl url success:" .. success ..", fail:" .. fail)

ngx.say('</h5>')



--读取统计数据:
local dm_keys = queue:keys('dm_*')
ngx.say('<h3>-------插入后当前Redis中弹幕存储量:</h3>')
local all_dm = 0
if next(dm_keys) ~= nil then
    for i,list_key in pairs(dm_keys) do
        local dm_data = queue:zrangebyscore(list_key, 0, 100000000)
        local frame_num = #dm_data
        local tempnum = 0
        for i,data in pairs(dm_data) do
            data = msgpack.unpack(data)
            tempnum = tempnum + #data
        end

        ngx.say('sortedset key:' .. list_key .. ",帧量:" ..frame_num .." ,弹幕量:" .. tempnum .."<br>" )
        all_dm = all_dm + tempnum
    end
end
ngx.say('<br><b>弹幕总量:' .. all_dm .. "</b>")

queue:set_keepalive(config.storage.queue_redis.keepalive_timeout, config.storage.queue_redis.pool_size)
  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林戈的IT生涯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值