[前言]
[關於go get和go install的變動]
我目前Golang的版本如下:
我目前Golang的版本如下:
本篇內容將提供快速的指引,包含相關需安裝的套件,從無到有建立全新的 React 應用程式( single-page application, SPA)
Tracee 是一個用 於 Linux 的執行時安全和取證工具。它使用 Linux eBPF 技術在執行時跟蹤系統和應用程式,並分析收集的事件以檢測可疑的行為模式。本篇對於Tracee這open source project進行了編譯與初步測試,在此做個筆記以防忘記。後續將針對源碼進行分析。
Github 位置為: https://github.com/aquasecurity/tracee
網路上已經有不少的相關文件資源可以參考,在此不重覆贅述,如下所示:
我在O`REILLY出的一本書 "Go學習手冊"內有看到一個很有趣的段落: 指標傳遞性能 ( Pointer Performance )
我把這段的重點直接整理下來(因為很重要) 如下:
重溫DoS時期的遊戲: 殖民帝國 Colonization
這套遊戲盒裝內的說明書、磁碟片(3 1/2吋)等等的相關的東西都有很完整保存下來,不信的話請看下圖:
由於這遊戲是執行在DoS 作業系統上的,所以我們需要在Windows 10上安裝DOS模擬器,並用此模擬器玩遊戲,執行步驟如下:
透過變數宣告時,需要在型別前面加上 * 符號,代表是指標型態,用來告訴編譯器這變數是某種型別的指標變數。
給值時也要給值的位置,我們在值前面加上 & 符號(位址運算子)。請看下面例子:
使用命令 kubectl taint 可以給節點(Node)增加一個污點。
比如:
說明:
給節點 node1 增加一個污點,它的鍵名是 key1,鍵值是 value1,效果是 NoSchedule。這表示只有擁有和這個污點相匹配的容忍度的 Pod 才能夠被分配到 node1 這個節點。
若要移除上述命令所添加的污點,你可以執行:
最常用的例子就是把 Master Node 改成有 Worker的屬性
[更新]
在K8S v1.24之後默認kubeadm取消taint,之前版本使用node-role.kubernetes.io/master標籤,在Kubernetes 1.24版本中,label標籤已經修改為node-role.kubernetes.io/control-plane
查看node節點所有標籤
我們可以直接查看master節點污點情況
生成污點
取消污點
Reference:
kubectl 備忘單
https://kubernetes.io/zh/docs/reference/kubectl/cheatsheet/
How to use Informer to avoid frequently getting Pod and Service List via clientset.CoreV1()?
[情境]
之前開發Kubernetes相關的系統有遇過這種情況:
需要不斷的輪詢(Pooling) Kubernetes API 去獲得最新的 Pods 與 Services List,例如是每2秒。但輪詢是比較沒有效率的做法,因為很有極大的可能是,大部分的輪詢結果都是沒有變化的。
使用Informer來解決此問題。
[前言]
用Golang寫小遊戲教學這一系列的內容,將會以一個基於Golang語言的 2D Game Library: Ebiten,對於製作小遊戲來說,感覺簡單又易於使用 。Ebiten 套件原作者是日本人,少量遊戲作品可在 wiki 中找到: https://github.com/hajimehoshi/ebiten/wiki/Works
很多使用範例可以學習:
[轉貼&修改] https://blog.xuite.net/csiewap/cc/23626229-Using+GCC+to+create+static+and+shared+library+.so
Static 程式庫用於靜態連結,簡單講是把一堆object檔用ar(archiver)
包裝集合起來,檔名以 `.a' 結尾。優點是執行效能通常會比後兩者快,
而且因為是靜態連結,所以不易發生執行時找不到library或版本錯置而
無法執行的問題。缺點則是檔案較大,維護度較低;例如library如果發
現bug需要更新,那麼就必須重新連結執行檔。
編譯方式很簡單,先例用 `-c' 編出 object 檔,再用 ar 包起來即可。
#include
void hello(){ printf("Hello "); }
#include
void world(){ printf("world."); }
void hello();
void world();
$ gcc -c hello.c world.c /* 編出 hello.o 與 world.o */
$ ar rcs libmylib.a hello.o world.o /* 包成 limylib.a */
這樣就可以建出一個檔名為 libmylib.a 的檔。輸出的檔名其實沒有硬性規定,
但如果想要配合 gcc 的 '-l' 參數來連結,一定要以 `lib' 開頭,中間是你要
的library名稱,然後緊接著 `.a' 結尾。
#include "mylib.h"
int main() {
hello();
world();
}
使用上就像與一般的 object 檔連結沒有差別。
$ gcc main.c libmylib.a
也可以配合 gcc 的 `-l' 參數使用
$ gcc main.c -L. -lmylib
`-Ldir' 參數用來指定要搜尋程式庫的目錄,`.' 表示搜尋現在所在的目錄。
通常預設會搜 /usr/lib 或 /lib 等目錄。
`-llibrary' 參數用來指定要連結的程式庫 ,'mylib' 表示要與mylib進行連結
,他會搜尋library名稱前加`lib'後接`.a'的檔案來連結。
$ ./a.out
Hello world.
此時可以用 nm <exe filename> 來顯示symbols (functions, etc.)
(To see which symbols come from static libraries requires running nm against those libraries to get a list of the symbols (functions, etc.) in them, then comparing them to what your list of symbols from nm <exefilename>.)
Shared library 會在程式執行起始時才被自動載入。因為程式庫與執行檔
是分離的,所以維護彈性較好。有兩點要注意,shared library是在程式起始
時就要被載入,而不是執行中用到才載入,而且在連結階段需要有該程式庫
才能進行連結。
首先有一些名詞要弄懂,soname、real name與linker name。
soname 用來表示是一個特定 library 的名稱,像是 libmylib.so.1 。
前面以 `lib' 開頭,接著是該 library 的名稱,然後是 `.so' ,接著
是版號,用來表名他的介面;如果介面改變時,就會增加版號來維護相容度。
real name 是實際放有library程式的檔案名稱,後面會再加上 minor 版號與
release 版號,像是 libmylib.so.1.0.0 。
一般來說,版號的改變規則是(印象中在 APress-Difinitive Guide to GCC中有
提到,但目前手邊沒這本書),最尾碼的release版號用於程式內容的修正,
介面完全沒有改變。中間的minor用於有新增加介面,但相舊介面沒改變,所以
與舊版本相容。最前面的version版號用於原介面有移除或改變,與舊版不相容
時。
linker name是用於連結時的名稱,是不含版號的 soname ,如: libmylib.so。
通常 linker name與 real name是用 ln 指到對應的 real name ,用來提供
彈性與維護性。
shared library的製作過程較複雜。
$ gcc -c -fPIC hello.c world.c
編譯時要加上 -fPIC 用來產生 position-independent code。也可以用 -fpic
參數。 (不太清楚差異,只知道 -fPIC 較通用於不同平台,但產生的code較大
,而且編譯速度較慢)。
$ gcc -shared -Wl,-soname,libmylib.so.1 -o libmylib.so.1.0.0 \
hello.o world.o
-shared 表示要編譯成 shared library
-Wl 用於參遞參數給linker,因此-soname與libmylib.so.1會被傳給linker處理。
-soname用來指名 soname 為 limylib.so.1
library會被輸出成libmylib.so.1.0.0 (也就是real name)
若不指定 soname 的話,在編譯結連後的執行檔會以連時的library檔名為
soname,並載入他。否則是載入soname指定的library檔案。
可以利用 objdump 來看 library 的 soname。
$ objdump -p libmylib.so | grep SONAME
SONAME libmylib.so.1
若不指名-soname參數的話,則library不會有這個欄位資料。
在編譯後再用 ln 來建立 soname 與 linker name 兩個檔案。
$ ln -s libmylib.so.1.0.0 libmylib.so
$ ln -s libmylib.so.1.0.0 libmylib.so.1
與使用 static library 同。
$ gcc main.c libmylib.so
以上直接指定與 libmylib.so 連結。
或用
$ gcc main.c -L. -lmylib
linker會搜尋 libmylib.so 來進行連結。
如果目錄下同時有static與shared library的話,會以shared為主。
使用 -static 參數可以避免使用shared連結。
$ gcc main.c -static -L. -lmylib
此時可以用 ldd 看編譯出的執行檔與shared程式庫的相依性
$ldd a.out
linux-gate.so.1 => (0xffffe000)
libmylib.so.1 => not found
libc.so.6 => /lib/libc.so.6 (0xb7dd6000)
/lib/ld-linux.so.2 (0xb7f07000)
輸出結果顯示出該執行檔需要 libmylib.so.1 這個shared library。
會顯示 not found 因為沒指定該library所在的目錄,所找不到該library。
因為編譯時有指定-soname參數為 libmylib.so.1 的關係,所以該執行檔會
載入libmylib.so.1。否則以libmylib.so連結,執行檔則會變成要求載入
libmylib.so
$ ./a.out
./a.out: error while loading shared libraries: libmylib.so.1:
cannot open shared object file: No such file or directory
因為找不到 libmylib.so.1 所以無法執行程式。
有幾個方式可以處理。
a. 把 libmylib.so.1 安裝到系統的library目錄,如/usr/lib下
b. 設定 /etc/ld.so.conf ,加入一個新的library搜尋目錄,並執行ldconfig
更新快取
c. 設定 LD_LIBRARY_PATH 環境變數來搜尋library
這個例子是加入目前的目錄來搜尋要載作的library
$ LD_LIBRARY_PATH=. ./a.out
Hello world.
Dynamicaaly loaded libraries 才是像 windows 所用的 DLL ,在使用到
時才載入,編譯連結時不需要相關的library。動態載入庫常被用於像plug-ins
的應用。
動態載入是透過一套 dl function來處理。
#include
void *dlopen(const char *filename, int flag);
開啟載入 filename 指定的 library。
void *dlsym(void *handle, const char *symbol);
取得 symbol 指定的symbol name在library被載入的記憶體位址。
int dlclose(void *handle);
關閉dlopen開啟的handle。
char *dlerror(void);
傳回最近所發生的錯誤訊息。
#include
#include
#includeint main() {
void *handle;
void (*f)();
char *error;
/* 開啟之前所撰寫的 libmylib.so 程式庫 */
handle = dlopen("./libmylib.so", RTLD_LAZY);
if( !handle ) {
fputs( dlerror(), stderr);
exit(1);
}
/* 取得 hello function 的 address */
f = dlsym(handle, "hello");
if(( error=dlerror())!=NULL) {
fputs(error, stderr);
exit(1);
}
/* 呼叫該 function */
f();
dlclose(handle);
}
編譯時要加上 -ldl 參數來與 dl library 連結
$ gcc dltest.c -ldl
結果會印出 Hello 字串
$ ./a.out
Hello
關於dl的詳細內容請參閱 man dlopen
--
參考資料:
Creating a shared and static library with the gnu compiler [gcc]
Makefile
xgo is a great Go CGO cross compiler that can help users to build the application written in Golang to multi-platforms at the same time.
For more information in details, please check out these URLs:
https://github.com/karalabe/xgo
https://www.jianshu.com/p/a6047d3f976e
But, without any further study, we probably cannot understand how it works well. So here I just give some information about it. I will use my Github repository as the example:
So, we can directly run this Docker Image to cross-compile my application based on my case as follows:
Furthermore, we can directly run xgo's build.sh to cross-compile my application in the host instead of in in the container:
Reference:
Golang 交叉编译
Golang交叉编译各个平台的二进制文件
Fyne Cross Compile
Propably two years ago, I studied a ECCV 2018 paper "License Plate Detection and Recognition in Unconstrained Scenarios", and its GitHub (https://github.com/sergiomsilva/alpr-unconstrained) repository contains the author's implementation. During that time, I had an idea to leveraged its implementation for replacing the license plate with my image. After tryed a couple days, I successed and provided a Python script to detect and replace cars' license plate in the video with a specified image.
I recently commited my modification code and pushed it to my forked repository as follows:
https://github.com/teyenliu/alpr-unconstrained
In this repository, it contains 2 samples which are convenient for users to test.
The way to process a video which will replace any car license plate in the video with a given image content.
$ python license-plate-replacement.py --video cars_mountain_short.mov --replace src/hello.PNG --output output1.avi
$ python license-plate-replacement.py --video cars_mountain.mp4 --replace src/hello.PNG --output output2.avi
The result looks like this:
This post is focusd on how to do dynamic/static linking using Golang with cgo on Windows environment. If you want to see it on Linux environment, please check out another post:
[Golang] Golang with Cgo 動態連結(dynamic linking) 函式庫範例與筆記 in Linux environment
First of all, thanks to someone who had posted several useful articles describing how to do dynamic linking and static linking using Golang(Go) with Cgo in Windows environment as follows:
P.S: For using this example on Linux environment, you should deal with the build process for the static and dynamic libraries.
在 Windows 環境建置動態連結函式庫 (Dynamic-link library),使用 MinGW gcc/g++ 以及 CodeBlock
Go with Cgo 靜態連結 (static linking) 函式庫建置範例與筆記
Go with Cgo 動態連結 (dynamic linking) 函式庫建置範例與筆記
This post can help you quickly learn how to use tmux in just a few minutes.
Get tmux session ready to start (new session)
Split a tmux window into two panes
For instance: split a tmux window into two panes vertically
Adjust a splitted pane size
You also are able to ajust the splitted pane vertically or horizontally.
For instance: There are 5 panes in the window and I can adjust the currently focused pane.
Attach tmux session or detach it
Delete tmux session
I recently encountered a use case that I need to convert my struct or map value to the type of map[string]interface{}. After surveying and studying for a while, I figure out how to deal with this kind of task and the way to do it.
The following function ConvertStructToMap() is the example of converting Struct or Map data to Map[string]interface{} Type. It receives the argument as interface type and uses reflect function to check the receiver type is correct and what we want. But, it has a constrain, which if you give a map, and Map's key type must be string.
How to use it? Here we go! You can try it on the Go Playground:
https://play.golang.org/p/TLKBIbSxIQj
or just take a look at the sample as follows:
Run Result==>
map[JsonName:john smith MsgScore:30]
map[Score1:100 Score2:60]