Sysdig chisels 開發(fā)

Chisels

Sysdig 的 chisels 是通過分析sysdig 事件數(shù)據(jù)流去完成特定動(dòng)作的小腳本。在Sysdig中,系統(tǒng)事件events 被高效地呈現(xiàn)在了用戶空間,所以腳本能夠直接被應(yīng)用到處理事件上。好處如下:

  • 能使用普遍被使用的而不是定制的語言。sysdig的chisels 使用 Lua 腳本語言。
  • Chisels 能很方便地使用眾多的Lua庫
  • Chisels 在實(shí)時(shí)系統(tǒng)上工作情況良好,但也能和捕獲的文件一起來完成離線的分析工作。

使用

  • 列出可所有使用的chisels
    $ sysdig -cl
  • 輸出某個(gè)chisel 的詳細(xì)描述和參數(shù)列表,使用 -i 命令行選項(xiàng)
    $ sysdig -i spy_ip
  • 運(yùn)行某個(gè)chisel 工具,使用 -c 選項(xiàng)
    $ sysdig -c topfiles_bytes
  • chisel工具需要參數(shù)時(shí),直接在后面補(bǔ)充
    $ sysdig -c spy_ip 192.168.1.157
  • 能夠同時(shí)運(yùn)行多個(gè)chisel工具
    $ sysdig -c stding -c stdout proc.name=cat
  • chisels 可以和過濾器filters 結(jié)合使用
# 不需要對(duì) /dev 的訪問
$ sysdig -c topfiles_bytes "not fd.name contains /dev"
# 只包含 /root 路徑的訪問
$ sysdig -c topfiles_bytes "fd.name contains /root"
# 進(jìn)程 vi 訪問的文件
$ sysdig -c topfiles_bytes "proc.name=vi"
# 用戶 loris 訪問的文件
$ sysdig -c topfiles_bytes "user.name=loris"

注意:
使用filters時(shí),我們需要注意它是作為sysdig的還是chisels的參數(shù)傳入

$ sysdig -i lsof
...
Args:
[filter] filter - A sysdig-like filter expression that allows r
                estricting the FD list. E.g. 'proc.name=foo and fd.name contain
                s /etc'.

當(dāng)作為chisels參數(shù)傳入時(shí),如上面的lsof,當(dāng)有多個(gè)篩選條件,如sysdig -c lsof "'user.name=phil or proc.name=sshd'",這里是需要雙重引號(hào)的。
當(dāng)作為sysdig參數(shù)傳入,當(dāng)有多個(gè)篩選條件,如:sysdig "fd.rip=54.165.81.189 and fd.port=6666",這時(shí)候是可加雙引號(hào)的
更多規(guī)則使用可參考https://sysdig.com/blog/linux-troubleshooting-cheatsheet/#lsof

開發(fā)自定義Chisel

Sysdig chisels 使用Lua 語言編寫,如果不熟悉,可以參考Programming in LuLua reference manual

Chisels 腳本結(jié)構(gòu)
--[[
Lua 腳本如果要想被sysdig 識(shí)別,必須要定義以下幾個(gè)全局變量
description
short_description
category
args:包含參數(shù)的列表,可為空
以上這些參數(shù)都會(huì)被sysdig識(shí)別并添加在chisels信息中(使用 sysdig -cl / sysdig -i chisels_name)
--]]
-- Chisel description
description = "counts how many times the specified system call has been called"
short_description = "syscall count"
category = "misc"

-- Chisel argument list
args =
{
    {
        name = "syscall_name",
        description = "the name of the system call to count",
        argtype = "string"
    },
}

--[[
當(dāng)需要給chisels傳遞參數(shù)時(shí),用參數(shù)信息補(bǔ)充arg 表和增加 on_set_arg()函數(shù)。sysdig收集到命令行參數(shù)時(shí),接著傳入并調(diào)用 on_set_arg函數(shù)。當(dāng)有多個(gè)參數(shù)時(shí),可使用不同的name來區(qū)分開來。
--]]
-- Argument notification callback
function on_set_arg(name, val)
    syscallname = val
    return true
end

--[[
chisel 初始化函數(shù),在收到第一個(gè)事件前執(zhí)行。
以下代碼使用了chisel.request_field去提取需要的ftype和fdir字段的地址,方便后面根據(jù)這兩個(gè)字段去篩選事件
--]]
-- Initialization callback
function on_init()

    -- Request the fields that we need
  -- 以下變量為userdata類型,猜測(cè)存儲(chǔ)了c/c++中指針類型數(shù)據(jù)
    ftype = chisel.request_field("evt.type")
    fdir = chisel.request_field("evt.dir")

  -- set the filter
  -- 通過chisels使用sysdig引擎來優(yōu)化篩選事件
    chisel.set_filter("evt.type=" .. syscallname .. " and evt.dir = >")

  --[[
  可以通過print()自定義事件通知,可以使用以下定義通知格式
  ""相當(dāng)于"default"
  chisel.set_event_formatter("")
  --]]

    return true
end

count = 0

-- Event parsing callback
-- 每當(dāng)一個(gè)事件到來都會(huì)觸發(fā)該函數(shù)的執(zhí)行
function on_event()
  count = count + 1
    return true
end

--[[
捕獲結(jié)束時(shí)的動(dòng)作,一般用于通知操作
結(jié)束的情況:
離線捕獲中收到最后一個(gè)數(shù)據(jù)包
實(shí)時(shí)捕獲中按下CTRL+C
--]]
-- End of capture callback
function on_capture_end()
    print(syscallname .. " has been called " .. count .. " times")
    return true
end

Chisels API

Chisels 通過以下三種獨(dú)立的接口與sysdig 交流

  • Callbacks 回調(diào)函數(shù)的集合
  • sysdig library 與主程交互的函數(shù)庫
  • evt library 用來從捕獲的事件中提取信息
強(qiáng)制的變量

為了能被識(shí)別為Chisels,Lua 腳本中必須包含以下全局變量:

  • description: 對(duì)該chisel 詳細(xì)的描述 字符串類型
  • short_description: 簡(jiǎn)略描述,字符串類型
  • category: chisel 所屬的目錄,如 IO,net,security,字符串類型
  • args: 描述每一個(gè)chisel參數(shù),table表格類型
args =
{
    {
        name = "name1",
        description = "description1",
        argtype = "ipv4"
        optional = false
    },
    {
        name = "name2",
        description = "description2",
        argtype = "string"
        optional = true
    },
}

注意:

  • args 中 optional設(shè)為"false",sysdig 命令行的chisel 名字后面必須指定這個(gè)參數(shù),否則執(zhí)行失敗
  • args 中的每一個(gè)參數(shù)都會(huì)生成一個(gè)對(duì)on_set_arg() 的調(diào)用
  • args 可為空
  • 參數(shù)列表中有不止一個(gè)參數(shù)時(shí),可用 "" 概括。如 sysdig -c chisel_name "arg1 arg2 arg3"
Callbacks

Callbacks 是sysdig 用來通知chisel 事情發(fā)生時(shí)的方式。除了on_interval() 需要使用sysdig.set_interval_s() 或者 sysdig.set_interval_ns()注冊(cè),大多數(shù)callbacks 不需要注冊(cè)。Callbacks 是可選的,不需要?jiǎng)t不用加上。

on_set_arg(name, val)
args 表中的每一個(gè)參數(shù)都會(huì)調(diào)用該函數(shù)。name 是參數(shù)設(shè)置的名字,val 是用戶在命令行給出的值。
參數(shù)無效時(shí)會(huì)返回false并導(dǎo)致sysdig退出。

on_init()
在所有參數(shù)的on_set_arg()都調(diào)用后但capture被配置前被調(diào)用。通常,用來初始化chisel工具。
chisel 初始化失敗返回false并導(dǎo)致sysdig退出

on_capture_start()
在capture配置后、on_set_arg被調(diào)用后,但在事件的數(shù)據(jù)包被捕獲之前調(diào)用。能在需要詢問capture狀態(tài)時(shí)的最終初始化chisel步驟中使用
chisel 初始化失敗返回false并導(dǎo)致sysdig退出

on_event()
在沒有設(shè)置set_filter() 或者通過set_filter()篩選后,每個(gè)被捕獲的事件到達(dá)都會(huì)激活該函數(shù)。這個(gè)函數(shù)常用來寫核心的chisel邏輯,需要保證代碼是高效可用的。在這個(gè)回調(diào)函數(shù)中,開發(fā)者可以對(duì)evt library訪問,從而從正在處理的事件中提取信息。
在指定了格式工具(set_event_formatter)的情況下,返回false會(huì)讓工具忽略該次事件。

on_capture_end(ts_s,ts_ns,delta)
捕獲結(jié)束時(shí)的動(dòng)作,一般用于通知操作。結(jié)束的情況如下:

  • 離線捕獲中收到最后一個(gè)數(shù)據(jù)包
  • 實(shí)時(shí)捕獲中按下CTRL+C
    參數(shù)含義如下:
  • ts_s,ts_ns: 最后收到事件的時(shí)間戳的秒(以秒的單位表示當(dāng)前時(shí)間)和納秒部分
  • delta:捕獲的第一個(gè)包到最后一個(gè)包的間隔時(shí)間,納秒表示

on_interval(ts_s,ts_ns,delta)
周期性的超時(shí)的回調(diào)函數(shù)??梢杂脕硪砸欢l率如每秒一次報(bào)告信息。使用chisel.set_interval_s() 或者 chisel.set_interval_ns()配置。參數(shù)含義如下:

  • ts_s, ts_ns:函數(shù)被調(diào)用的時(shí)間,秒+納秒表示
  • delta:被調(diào)用的間隔時(shí)間
sysdig library

這個(gè)庫里面的函數(shù)可以用來設(shè)置全局的sysdig配置

sysdig.end_capture()
這個(gè)調(diào)用會(huì)讓sysdig停止接受事件,然后‘makes it initiate the end of capture cleanup’(不太理解),感覺就是準(zhǔn)備結(jié)束sysdig,開始清理捕獲動(dòng)作的相關(guān)環(huán)境。

sysdig.get_machine_info()
返回一個(gè)帶有產(chǎn)生事件的機(jī)器的信息的表(table類型),表有以下字段:

  • num_cpus: 機(jī)器上的CPU核心的編號(hào)
  • memory_size_bytes:機(jī)器RAM的大小
  • max_pid:機(jī)器允許的最大PID數(shù)值
  • hostname:機(jī)器主機(jī)名
    注意:這個(gè)調(diào)用對(duì)文件捕獲也同樣有效,因?yàn)闄C(jī)器信息存儲(chǔ)在跟蹤文件(sysdig -w output.scap)上。這種情況下,返回的機(jī)器信息是捕獲發(fā)生的其中一個(gè)機(jī)器。

sysdig.get_filter()

返回在命令行傳遞給sysdig的包含filter的字符串
sysdig.get_evtsource_name()
返回包含事件源名字的字符串。跟蹤文件名(如果事件來源于一份跟蹤文件)或者""(如果是實(shí)時(shí)捕獲)

sysdig.get_output_format()
返回用戶在命令行規(guī)定的輸出格式,返回值可以是"normal"或者"json"

sysdig.is_print()_container_data
返回Boolean類型,表示是否使用了-pc 或者 -pcontainer 選項(xiàng)。

sysdig.get_container_table(filter)
返回sysdig container table
filter可以選擇性地作為輸入?yún)?shù)傳遞,用來限制返回的元素。語法與常規(guī)sysdig filters相同,但僅限于fd,proc,user和group filter類型。
返回以下值:

  • id:容器id,唯一標(biāo)識(shí)符
  • name:容器名字
  • images:容器鏡像
  • type:容器類型(docker,lxc,& libvirt_lxc)
    注意:
    container.id==host 且/或者 container.name == host 表示是主機(jī)而不是容器

sysdig.get_thread_table(filter)
返回sysdig process table。filter使用與get_container_table 相同。
返回值過多,建議參考官網(wǎng)資料。

sysdig.is_tty()
返回是否sysdig運(yùn)行在有ANSI功能的交互終端,能被chisel用來決定是否有可能在屏幕上顯示顏色

sysdig.islive()
返回當(dāng)前的捕獲是否實(shí)時(shí)的,即事件是來自系統(tǒng)還是個(gè)跟蹤文件

sysdig.run_sysdig(args)
從目前執(zhí)行的sysdig退出,然后再啟動(dòng)一個(gè)新的,參數(shù)由args傳遞。chisel 能用它來運(yùn)行另一個(gè)不同的捕獲或者再一次啟動(dòng)sysdig去完成不同的任務(wù)(如 保存特定事件到文件中)

sysdig.set_fatfile_dump_mode(mode)
開啟/禁用 fatfile 模式。mode 參數(shù)是個(gè)Boolean值。

sysdig.set_filter(filter)
在解析事件前,將filter過濾器配置到sysdig引擎中。和在命令行中設(shè)置filter的作用是一樣的,且會(huì)覆蓋命令行的參數(shù)。

sysdig.set_snaplen(snaplen)
設(shè)置I/O類型的系統(tǒng)調(diào)用(如 read,write,sendto,recvform)的buffers的字節(jié)數(shù)。

chisel library

這個(gè)庫里面的函數(shù)與設(shè)置chisel環(huán)境最相關(guān),經(jīng)常在初始化的時(shí)候被調(diào)用,例如 on_init()

chisel.exec(chiselname, arg1, arg2, ...)
這個(gè)函數(shù)能被用來停止正在調(diào)用的chisel的執(zhí)行,轉(zhuǎn)而去運(yùn)行一個(gè)不同的chisel

chisel.request_field(fld_name)
這個(gè)函數(shù)用來在事件被捕獲的時(shí)候提取一個(gè)filter字段。fld_name 是將要去提取的sysdig filter 字段(sysdig 教程或者sysdig -l 可看所有可用的字段)。函數(shù)返回字段的句柄,該句柄能用在 evt.field() 以在on_event()回調(diào)函數(shù)中獲得字段的值。

chisel.set_filter(filter)
設(shè)置sysdig 引擎,在chisel的on_event()調(diào)用處理事件前使用給出的filter過濾事件。
注意:

  • set_filter 設(shè)置的filter 只對(duì)當(dāng)前的chisel有效
  • 每個(gè)chisel 只能設(shè)置一個(gè),調(diào)用兩次將會(huì)導(dǎo)致第一次被覆蓋
  • 應(yīng)該盡可能地使用filters。sysdig 引擎做了大量?jī)?yōu)化,所以盡可能地減少到達(dá)chisel 的on_event()前的事件能使chisels更高效

chisel.set_event_formatter(format)
配置事件的格式工具。format 變量是一個(gè)包含將要打印的字段列表的字符串,符號(hào)使用和命令行選項(xiàng) -p 一致。
默認(rèn)情況下,chisel 沒有事件格式工具,它們可以使用Lua 的print() 函數(shù)任意輸出。設(shè)置了格式工具,可以利用sysdig 的過濾字段系統(tǒng)(filter fields system)去替你格式化地輸出信息。"default"或"", sysdig 添加它的默認(rèn)格式到chisel。on_event() 返回true 的時(shí)候才會(huì)打印信息,且chisel 的輸出不會(huì)被命令行-p 選項(xiàng)覆蓋。

chisel.set_interval_s(interval)
為當(dāng)前chisel 設(shè)置一個(gè)周期性的調(diào)用。使用這個(gè)函數(shù),需要chisel 包含on_interval()函數(shù),sysdig 引擎會(huì)以interval 秒的間隔循環(huán)調(diào)用

chisel.set_interval_ns(interval)
和set_interval_s 類似,不過更精細(xì)的時(shí)間設(shè)置

evt library

這個(gè)庫的函數(shù)有關(guān)于正在被處理的事件,所以只能被 on_event() 函數(shù)調(diào)用

evt.get_cpuid()
返回捕獲到事件的CPU的編號(hào)

evt.field(fld)
從事件中提取特定特定字段的值。參數(shù)fld是從上一個(gè)requet_field()調(diào)用中獲得的字段句柄。函數(shù)返回字段的值,可能是個(gè)數(shù)字或者字符串。sysdig -lv 命令可以查看每個(gè)導(dǎo)出字段的類型。
注意:

  • 如果請(qǐng)求的字段沒有被事件導(dǎo)出(例如非I/O事件不會(huì)導(dǎo)出fd.name 字段),返回值為 nil (Lua 中表示只有一個(gè)值的一種類型)
  • evt.rawarg 字段需要注意。它能用來提取任意系統(tǒng)調(diào)用的參數(shù),如 evt.rawarg.res,所以它的類型取決于你詢問的字段

evt.get_num()
返回遞增的事件編號(hào)

evt.get_ts()
返回兩個(gè)分別代表事件原始時(shí)間戳的秒和納秒部分的時(shí)間戳

evt.get_type()
以數(shù)字形式返回事件類型。能用來事件過濾。事件類型編碼可以在driver/ppm_event_events_public.h的ppm_event_type 枚舉中查看
參考資料:
https://github.com/draios/sysdig/wiki/Chisels-User-Guide
https://github.com/draios/sysdig/wiki/Writing-a-Sysdig-Chisel%2C-a-Tutorial
https://github.com/draios/sysdig/wiki/Sysdig-Chisel-API-Reference-Manual

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容