文章目錄
- 1. 什麼是模闆?
- 2. Go模闆常用文法
- 3. 變量
- 3.1 系統變量 {{.}}
- 3.2 自定義變量
- 3.3 周遊(循環):range
- 4. index
- 5. 判斷:if … else … end
- 5.1 not
- 5.2 or
- 6. 判斷條件
- 7. 判斷的使用
- 8. 列印資訊
- 9. 管道
Docker --format 參數提供了基于 Go模闆 的日志格式化輸出輔助功能,并提供了一些内置的增強函數。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5SM4UTOxYWZ5kDZzUWZ5QTOyYzXxMTOzgTMwMzLcVDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
1. 什麼是模闆?
上圖是大家熟悉的 MVC 架構(Model View Controller):
Model(模型,通常在服務端)用于處理資料、View(視圖,用戶端代碼)用于展現結果、Controller(控制器)
用于控制資料流,確定 M 和 V 的同步,即一旦 M 改變,V 也應該同步更新。
而對于 View 端的處理,在很多動态語言中是通過在靜态 HTML 代碼中插入動态資料來實作的。例如 JSP 的 <%=…=%> 和 PHP 的 <?php.....?> 文法。
由于最終展示給使用者的資訊大部分是靜态不變的,隻有少部分資料會根據使用者的不同而動态生成。比如,對于 docker ls 的輸出資訊會根據附加參數的不同而不同,但其表頭資訊是固定的。是以,将靜态資訊固化為模闆可以複用代碼,提高展示效率。
2. Go模闆常用文法
格式: {{/注釋内容/}}
docker network inspect --format='{{/*檢視容器的預設網關*/}}{{range .IPAM.Config}}{{.Gateway}}{{end}}' $INSTANCE_ID
3. 變量
3.1 系統變量 {{.}}
點号表示目前對象及上下文,和 Java、C++ 中的 this 類似。可以直接通過{{.}}擷取目前對象。
另外,如果傳回結果也是一個 Struct 對象(Json 中以花括号/大括号包含),則可以直接通過點号級聯調用,擷取子對象的指定屬性值。
#可以通過級聯調用直接讀取子對象 State 的 Status 屬性,以擷取容器的狀态資訊:
docker inspect --format '{{/*讀取容器狀态*/}}{{.State.Status}}' $INSTANCE_ID
注意: 如果需要擷取的屬性名稱包含點号(比如下列示例資料)或者以數字開頭,則不能直接通過級聯調用擷取資訊。因為屬性名稱中的點号會被解析成級聯資訊,進而導緻傳回錯誤結果。即便使用引号将其包含也會提示文法格式錯誤。此時,需要通過 index 來讀取指定屬性資訊。
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
# 直接級聯調用會提示找不到資料:
docker inspect --format '{{.Options.com.docker.network.driver.mtu}}' bridge
# 用引号括起來會提示文法錯誤:
docker inspect --format '{{.Options."com.docker.network.driver.mtu"}}' bridge
Template parsing error: template: :1: bad character U+0022 '"'
# 正确的用法,必須用 index 讀取指定屬性名稱的屬性值:
docker inspect --format '{{/*讀取網絡在hosts上的名稱*/}}{{index .Options "com.docker.network.bridge.name"}}' bridge
docker0
執行個體:
[root@monitor1 ~]# docker inspect -f '{{.Id}}' prometheus
9094fdeb64edf75d52189e1b985d0926cf4e6d53880a8f09ab30fc2d6c8a0908
[root@monitor1 ~]# docker inspect -f '{{.State.Status}}' prometheus
running
[root@monitor1 ~]# docker inspect -f '{{"status:"}}{{.State.Status}}' prometheus
status:running
[root@monitor1 ~]# docker inspect -f '{{"status:"}}{{index .State.Status}}' prometheus
status:running
3.2 自定義變量
可以在處理過程中設定自定義變量,然後結合自定義變量做更複雜的處理。 如果自定義變量的傳回值是對象,則可以通過點号進一步級聯通路其屬性。比如
{{$Myvar.Field1}}
。
# 結合變量的使用,對輸出結果進行組裝展現,以輸出容器的所有綁定端口清單:
docker inspect --format '{{/*通過變量組合展示容器綁定端口清單*/}}已綁定端口清單:{{println}}{{range $p,$conf := .NetworkSettings.Ports}}{{$p}} -> {{(index $conf 0).HostPort}}{{println}}{{end}}' Web_web_1
# 示例輸出資訊
已綁定端口清單:
80/tcp -> 32770
8081/tcp -> 8081
3.3 周遊(循環):range
格式:
{{range pipeline}}{{.}}{{end}}
{{range pipeline}}{{.}}{{else}}{{.}}{{end}}
range 用于周遊結構内傳回值的所有資料。支援的類型包括 array, slice, map 和 channel。使用要點:
- 對應的值長度為 0 時,range 不會執行。
- 結構内部如要使用外部的變量,需要在前面加 引用,比如Var2。
- range 也支援 else 操作。效果是:當傳回值為空或長度為 0 時執行 else 内的内容。
檢視容器網絡下已挂載的所有容器名稱,如果沒有挂載任何容器,則輸出 “With No Containers”
"NetworkSettings": {
"Bridge": "",
"SandboxID": "a4ae52dfb055599b4b582d4c91f5a38d297bbed30f3e1d698f1c199be572c1e3",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {
"9090/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "9090"
}
]
},
"SandboxKey": "/var/run/docker/netns/a4ae52dfb055",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "16dbaea3aef149379a83673284c9adb843dab363246e6eb3255e40b149003580",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "2045baaf0ce3f404298a1a57035b6cc6c91ebd4ee05ce219b818f255c198b44b",
"EndpointID": "16dbaea3aef149379a83673284c9adb843dab363246e6eb3255e40b149003580",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02"
}
}
}
}
]
[root@monitor1 ~]# docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' prometheus
172.17.0.2
[root@monitor1 ~]# docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}} {{$p}} -> {{(index $conf 0).HostPort}} {{end}}' prometheus
9090/tcp -> 9090
4. index
如果傳回結果是一個 map, slice, array 或 string,則可以使用 index 加索引序号(從零開始計數)來讀取屬性值。
[root@monitor1 ~]# docker inspect --format='{{(index (index .NetworkSettings.Ports "9090/tcp") 0).HostPort}}' prometheus
9090
5. 判斷:if … else … end
基本判斷
5.1 not
傳回單一參數的布爾否定值,即傳回輸入參數的否定值。
示例:
# 如果容器的 restarting 設定為 false,則傳回資訊“容器沒有配置重新開機政策”
docker inspect --format '{{if not .State.Restarting}}容器沒有配置重新開機政策{{end}}' $(docker ps -q)
容器沒有配置重新開機政策
5.2 or
- {{or x y}}: 表示如果 x 為真傳回 x,否則傳回 y。
- {{or x y z}}:後面跟多個參數時會逐一判斷每個參數,并傳回第一個非空的參數。如果都為 false,則傳回最後一個參數。
- 除了 null(空)和 false 被識别為 false,其它值(字元串、數字、對象等)均被識别為 true。
示例:
[root@monitor1 ~]# docker inspect --format '{{or .State.Status .State.Restarting}}' $(docker ps -q)
running
6. 判斷條件
判斷語句通常需要結合判斷條件一起使用,使用格式基本相同:
{{if 判斷條件 .Var1 .Var2}}{{end}}
go模闆支援如下判斷方式:
- eq: 相等,即 arg1 == arg2。比較特殊的是,它支援多個參數進行與比較,此時,它會将第一個參數和其餘參數依次比較,傳回下式的結果:
{{if eq true .Var1 .Var2 .Var3}}{{end}}
效果等同于:
arg1==arg2 || arg1==arg3 || arg1==arg4 ...
2) ne: 不等,即 arg1 != arg2。
3) lt: 小于,即 arg1 < arg2。
4) le: 小于等于,即 arg1 <= arg2。
5) gt: 大于,即 arg1 > arg2。
6) ge: 大于等于,即 arg1 >= arg2。
7. 判斷的使用
{{if pipeline}}{{end}}
{{if pipeline}}{{else}}{{if pipeline}}{{end}}{{end}}
{{if pipeline}}{{else if pipeline}}{{else}}{{end}}
# 輸出所有已停止的容器名稱:
docker inspect --format '{{if ne 0.0 .State.ExitCode}}{{.Name}}{{end}}' $(docker ps -aq)
docker inspect --format '{{if ne 0.0 .State.ExitCode}}{{.Name}}{{else}}該容器還在運作{{end}}' $(docker ps -aq)
docker inspect --format '{{if ne 0.0 .State.ExitCode}}{{.Name}}{{else if .}}該容器還在運作{{end}}' $(docker ps -aq)
# 輸出所有已停止或配置了 Restarting 政策的容器名稱
docker inspect --format '{{if ne 0.0 .State.ExitCode}}{{.Name}}{{else if eq .State.Restarting true}}容器{{.Name}}配置了Restarting政策.{{else}}{{end}}' $(docker ps -aq)
8. 列印資訊
docker inspect --format '{{.State.Pid}}{{.State.ExitCode}}' $INSTANCE_ID
240390
docker inspect --format '{{print .State.Pid .State.ExitCode}}' $INSTANCE_ID
24039 0
docker inspect --format '{{.State.Pid}}{{println " 從這換行"}}{{.State.ExitCode}}' $INSTANCE_ID
24039 從這換行
0
docker inspect --format '{{printf "Pid:%d ExitCode:%d" .State.Pid .State.ExitCode}}' $INSTANCE_ID
Pid:24039 ExitCode:0
9. 管道
{{.Con | markdown | addlinks}}
{{.Name | printf "%s"}}
[root@monitor1 ~]# docker inspect --format '{{len .Name}}' prometheus
11
root@test1:~# docker inspect nginx -f '{{json .State}}' | jq
{
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 23773,
"ExitCode": 0,
"Error": "",
"StartedAt": "2021-08-04T09:27:06.018089509Z",
"FinishedAt": "0001-01-01T00:00:00Z"
}