mender 把更新分成幾個 state (9個?)。
然後給個 state 一個 run script 的機會 (兩個?. enter , leave)
但是說明很少。
transient error: update commit failed: statescript: The statescript version file is missing. This file needs to be present and contain a single number representing which version of the statescript support the client is using in order to successfully run statescripts on the client只好去找 source..
versionFilePath := filepath.Join(l.RootfsScriptsPath, "version") f, err := os.Open(versionFilePath) if err != nil && os.IsNotExist(err) { errmsg := "statescript: The statescript version file is missing. This file needs to be " + "present and contain a single number representing which version of the statescript " + "support the client is using in order to successfully run statescripts on the client" return errors.New(errmsg) } else if err != nil { return errors.Wrap(err, "statescript") } ver, err := readVersion(f) if _, ok := err.(readVersionParseError); ok { errmsg := "statescript: Failed to parse the version file in the statescript directory (%s). " + "The file needs to contain a single integer signifying which version of the statescript " + "support which this client is using" return fmt.Errorf(errmsg, err) }所以是需要一個叫 version 的 file,裡面是數字。
然後這個 RootfsScriptsPath 就是
conf/paths.go: DefaultRootfsScriptsPath = path.Join(GetConfDirPath(), "scripts")應該就是 /etc/mender/scripts
version 裡面只有一個 0,然後 Error 變成
transient error: update commit failed: statescript: unsupported scripts version: 0找到:
func NewStateScriptExecutor(config *conf.MenderConfig) statescript.Launcher { ret := statescript.Launcher{ ArtScriptsPath: config.ArtifactScriptsPath, RootfsScriptsPath: config.RootfsScriptsPath, SupportedScriptVersions: []int{2, 3}, ..把version內容由 0 改為 3 之後,果然就 ota OK 了,沒有 Error,但是 state script 以=也沒有執行....
execute.go 有 l.get( )
func (l Launcher) get(state, action string) ([]os.FileInfo, string, error) { sDir := l.ArtScriptsPath if state == "Idle" || state == "Sync" || state == "Download" { sDir = l.RootfsScriptsPath } ...先看script 位置,依照 state 而有不同。
path.go
DefaultArtScriptsPath = path.Join(GetStateDirPath(), "scripts") DefaultRootfsScriptsPath = path.Join(GetConfDirPath(), "scripts") DefaultDataStore = "/var/lib/mender" func GetStateDirPath() string { return DefaultDataStore } func GetConfDirPath() string { return "/etc/mender" }所以 Idle, Sync, Download 是在 /etc/mender。
其他state 是 /var/lib/mender
查實際的機器, 把 state script 放到 update OS (ext4) 的 /etc/mender/scripts/ 下後。包進 ota file (mender),然後 更新到機器上。
script folder 好像會被 copy 到 /data/mender/script (就是 /var/lib/mender 的 symbolic link)。(不是全部 copy)。
而 /etc/mender/script 跟 /var/lib/mender 剛好就是上面的 RootfsScriptsPath 跟 ArtScriptsPath。
但是... RootfsScriptPath 是在ota file 的 ext4 裡, /var/lib/mender 是working 的 os..不一樣。
把一些 example 的 script copy 到 update image 的 /etc/mender/scripts 下
# ls /etc/mender/scripts/ ArtifactCommit_Enter_00 Download_Enter_00 Sync_Enter_00 ArtifactInstall_Enter_00 Download_Leave_01 version ArtifactReboot_Enter_00 Download_Leave_02每一個 script 都是在 /data/ 下 touch 自己的 filename.
用 mender ota 成功,到 /data 下只有看到 Sync_Enter_00
符合上面的code,, idle,sync,download 都看 /etc/mender/script
所以把 一樣的 script 都 copy 到 /var/lib/mender/scripts ...
測試,每個 script 都是
date > /data/$(basename "$0")然後從 /data 就可以知道有哪些 script 有正確執行。
mender 的 yocto recipes 也是用一樣的 script。
-- 裡面 script 都 copy 到一樣的地方喔。
最後:
state scripts 分成兩種,一種是預先要再系統的。一種是放在 artifacr (*.mender) 。
因為 Artifact(mender) 要 download 完會有,所以download 之後的 state ,script 都可以放在 artifacr (*.mender) 中。
其他沒有 download,或是還沒download 的 state,script 就要在系統力。
系統的位置是 /etc/mender/scripts
裡面要有一個 "version" 檔,內容是一個數字,例如 3。代表 script 的版本。
放在 artifact (*.mender) 的,就要在 create mender file 時給定。
用 -s 選項就可以。
這格選項家的 state script,一定要用 Artifact 開頭,例如 ArtifactCommit_Enter_00,ArtifactInstall_Enter_00
把 scripts 都放到 state_script foldler,用 shell scipt 找出來就是...
#!/bin/bash LIST="" for f in state_scripts/Artifact* do LIST="${LIST} -s ${f}" done echo ${LIST}
沒有留言:
張貼留言