toml
二萌當初在寫本章時,本來是打算給 edition 2022 準備的。
實際上,有部分內容已經下放給 edition 2021 了。
在之後的新版中,對於面向使用者的配置,toml 會出現得更加頻繁。
在天萌中,配置檔案分為兩種。
一種是隻能看的,另一種則是可以寫的。
| 只讀 | 可讀可寫 |
|---|---|
| 一般是軟體包發行資訊或資料索引資訊 | 真正意義上的程式配置檔案 |
1. 只讀配置
1.1. 概念解讀
天萌的“容器屬性資訊”就是隻讀配置。
此處所指的只讀配置並不是檔案許可權的 "read only",而是邏輯上的只讀。
實際上,您可以直接修改該檔案的內容,只是不應該手動去修改。
舉個例子:
假如您看到了版本號為"1.57.0"。
心想:“這版本號也忒低了吧!咱把它改成 114514.999.9 吧!”
於是,您很開心地修改了它本身的屬性。
從主觀的角度來看:您收穫了快樂。這很棒!因為快樂是一種積極的生活態度。
從客觀的角度來看:您修復了版本號過低的問題。這也不錯!
從原開發者的角度來看:啊這。。。
於是乎,只有原開發者受傷的世界達成了。(ó﹏ò。)
注:以上修改的內容不會生效。
對於只讀配置,如果修改真的生效了,那麼容器在安裝或使用過程中可能會出現問題。
我相信您能在下一小節中找到原因。
1.2. 分析
本節將對“容器屬性資訊”進行分析。
天萌每週構建容器輸出的只讀配置如下:
(之後可能會發生變更)
[main]
name = "rust"
tag = ["nightly", "unstable"]
os = "debian"
release = "sid"
arch = "arm64"
syntax_version = "0.0.1"
[file]
name = "rust-nightly-arm64_2021-09-17_20-39.tar.zst"
# 這個值可以用來校驗檔案的完整性
# 舉個例子:假設存在兩個同名檔案,它們都叫a.tar.zst,大小也相同,只是所在目錄不同: A/a.tar.zst, B/a.tar.zst
# 您可能無法直接判斷它們是否屬於同一個檔案
# 這時候可以透過對比兩者的 sha256 校驗值來檢測它們是否為同一個檔案,若 sha256 值相同,則檔案相同,反之不同。
# 注:此處忽略了雜湊碰撞等問題。
sha256 = "acc668db456e94053322f7049469995ba20e9fe6dcb297367226dca4553b633e"
[file.size]
# Installed size ≈ tar-size
# 安裝大小 約等於 tar檔案的大小
# tar大小就是容器映象打包後的大小,解包後佔用的空間可能會比tar本身略大一點
# 具體大小與檔案簇有關,而檔案簇又與 file system(檔案系統)有關。
tar = "1.6G"
tar-bytes = 1717986919
# Space occupied ≈ tar-size + zstd-size
# You will need to prepare a large enough space before installation.
# Download size: zstd-size
# 在tar打包完成後,開發者還對映象進行了壓縮。
# 您需要下載的檔案大小就是zstd的大小,準確來說是tar.zst檔案的大小
# 在安裝一個容器前,您需要考慮預留一定的空間:
# 1.壓縮包檔案的大小,2.壓縮包解壓後的大小, 3.容器的初始化過程也需要佔用一點空間。
zstd = "216M"
zstd-bytes = 226492416
# 對於2022版,使用者只需要看版本號就能知道映象的先後順序了,知道哪個比較新哪個比較舊。
# 開發者忽然想到了天萌存在一個自動判斷時間先後順序的功能,就算是舊版也有這個功能。
# 其實time(時間)是給開發者看的,普通使用者不需要了解伺服器在構建映象過程中的某個流程究竟花了多少時間。
# 如果您感興趣的話,那我可以說一下流程。
# 1. 伺服器構建完成映象後,需要對映象進行打包和壓縮。
# 2. start-zstd指的是開始進行zstd壓縮的時間點
# 3. 在壓縮完成後,需要將檔案傳輸到另一個節點。
# 3-1. 對於天萌的每週構建,並不是所有節點都從零開始構建,而是其中一個節點完成構建後,就把相關檔案同步到另一個節點。
[time]
begin = 2021-09-17T20:08:33.801113258Z
start-zstd = 20:14:20
start-sync_0 = 20:39:22
start-sync_1 = 20:41:33
end = 2021-09-17T20:44:32.392018144Z
[server]
name = "tmoe-us"
node = 2
available = [1, 2, 3, 4]
# Environment variables inside the container.
# 容器內部的環境變數會影響容器內的環境,~~聽君一席話,如聽一席話~~(●>ω<●)
[env]
PATH = "/usr/local/cargo/bin${PATH:+:${PATH}}"
RUSTUP_HOME= "/usr/local/rustup"
CARGO_HOME = "/usr/local/cargo"
[version]
rustup = 'rustup 1.24.3 (ce5817a94 2021-05-31)'
cargo = 'cargo 1.56.0-nightly (e515c3277 2021-09-08)'
rustc = 'rustc 1.57.0-nightly (e4828d5b7 2021-09-16)'
toml 是一種優秀的配置檔案格式。
接下來,我們將會介紹 toml 的理念以及常見用法。
最後,我們將簡單瞭解“可寫配置”的概念與用法。
2. toml
2.1. 什麼是 toml
Tom's Obvious, Minimal Language.
Tom 的(語義)明顯、(配置)最小化的語言。
TOML 旨在成為一個語義明顯且易於閱讀的最小化配置檔案格式。
TOML 被設計成可以無歧義地對映為雜湊表。
TOML 應該能很容易地被解析成各種語言中的資料結構。
以上說明來自於 toml 的官網,您可以在裡面找到一些詳細的說明。
2.2. toml 與 json
談到 toml,很多人都會提及到 json
為什麼不用json呢? 它跟json 比有什麼優勢嗎?
github 上 toml-lang/toml 的第 2 條 issue 就跟這個話題有關。
But I don't know why too.
2.3. toml 的簡單用法
本小節的內容將為(#4.3-可寫配置) 打下基礎。
在天萌容器的配置中,可能會涉及到以下知識點:
- 字串
- 整數
- 浮點數
- 布林值
- rfc3339
- 陣列
- 標準表
- 內聯表
其實這些也是 toml 本身的常見值型別。
很少涉及到的知識點是:
- 表陣列
2.3.1. 表陣列
表陣列的話,雖然很好用,但是天萌的開發者 (想要偷懶) 由於某種原因就不用這種型別了。
其實是表陣列解析起來稍微要麻煩一點。
舉個簡單的例子:
[[bin]]
name = "tmm"
[[bin]]
name = "value"
[[bin]]
name = "tmoe"
全刪[[bin]] 或者是追加寫入一個新的[[bin]] 都很簡單。
但是呢!要修改包含指定"value"的資料,還得要再處理一下。
不像標準表,直接鍵值對操作,多簡單啊!
2.3.2. 字串
字串可能是天萌容器的配置檔案裡最常見的型別了。
比如說
str = "value"
toml 的字串型別既可以用雙引號,也可以用單引號。
這跟 rust 不一樣,在 rust 中,如果您使用單引號,並且沒有指明型別,那麼編譯器預設會推斷該值為 char 型別(單個字元)。
#![allow(unused)] fn main() { let c = 'c'; }
回到 toml,你如果需要輸入多個引號的話,那就這樣子寫吧!
str = """我有'''''5個單引號,還有兩個""雙引號"""
前面和後面都有三個引號。
2.3.3. 整數
整數的話,就不需要引號了!
舉個字串的例子:
int1 = "233"
在上面的式子中,int 的值將被識別為字串, 而不是整數。
再舉個整數的例子:
int2 = 233
舉個負整數的例子:
int3 = -233
toml 可以接受的整數範圍是 i64 (從 −2^63 到 2^63−1)。
跟 rust 一樣,對於特別大的數字,您可以用 _ 來增強可讀性。
int4 = 114_514_233
上面那條式子等於下面那條
int4 = 114514233
舉個二進位制、八進位制和十六進位制整數的例子:
# 二進位制的0b11011111101010010等於十進位制的114514
bin = 0b11011111101010010
# 0o開頭的值是八進位制的數字,猜猜看這是哪個數
oct1 = 0o337522
# 0x開頭是十六進位制喔
hex1 = 0x1BF52
2.3.4. 浮點數
浮點數也不能加引號哦!
用小數和指數形式舉個幾個例子吧!
f1 = 3.14159265
f2 = -3.14159265
f3 = 314e-2
f4 = 0.1145e+4
2.3.5. 布林值
布林值只有兩個值: true 和 false
true 為真,false 為假
true ✓
false X
bool1 = true
bool2 = false
2.3.6. rfc3339
rfc3339 是一種時間格式。
# 您可以只寫時間
time1 = 01:25:57
time2 = 01:25:00.247810421
# 也可以只寫日期
date1 = 2021-09-29
# 也可以都寫
time3 = 2021-09-29T01:25:57Z
# 您可以把上面那個拆開來,並且無需加引號
time4 = 2021-09-29 01:25:57Z
# 末尾的Z代表的是UTC, 您可以換成+00:00
# 下面以納秒級別來輸出東八區的某一時間點。那麼問題來了,您知道為什麼是這個時間點嗎?
time5 = 2021-09-29 01:29:13.598811802+08:00
因為開發者寫文件寫到很晚,都寫到這個點啦!很辛苦的說。
2.3.7. 陣列
簡單來說,陣列就是一個方括號,然後裡面有 0 個或多個值。
# 您可以換行寫
array1 = [233,
22,
33]
# 也可以不換行寫
array2 = [ "你好", "世界" ]
2.3.8. 標準表
標準表也被稱為雜湊表。
舉個 Cargo 裡面的例子
[dependencies]
nom = "7.0.0"
您可以把上面的表寫成下面的格式
[dependencies.nom]
version = "7.0.0"
2.3.9. 內聯表
內聯表可以把多行寫成一行。
先舉個標準表的例子
[dependencies.tokio]
version = "1.11.0"
features = ["macros", "tcp", "dns", "io-util"]
再舉個內聯表的例子
[dependencies]
tokio = { version = "1.11.0", features = ["macros", "tcp", "dns", "io-util"] }
怎麼樣?您喜歡標準表還是內聯表呢?
3. 可寫配置
3.1. 概念解讀
咕咕咕,這個部分還沒有開始寫呢!