- 重构 sysconf 为文档模型 INI Parser 与 Config Framework - 强化 hosts 解析、插入校验、写回与异常输入处理 - 完善 StarCmd 生命周期、等待 API、流式输出与 IO 重定向 - 扩展跨平台文件时间、文件锁、内存、进程与网络能力 - 将 Windows 进程适配更新到 b612.me/wincmd v0.1.0 - 移除本地 wincmd/win32api replace,改用发布版依赖 - 将最低 Go 版本提升到 1.18 - 补充 hosts、sysconf、FileLock、StarCmd 与平台适配回归测试
staros
staros is a cgo-free Go package for small cross-platform OS utilities.
The package keeps compatibility with existing APIs, but platform-dependent functions should prefer explicit error-returning variants where available. Unsupported platform implementations return ERR_UNSUPPORTED instead of silently pretending to work.
Go Version
go.mod declares go 1.18. This release targets Go 1.18 or newer and no longer promises Go 1.16/1.17 compatibility. The release gate includes the current local Go toolchain plus cross-platform compile checks.
Platform Support
| Area | Linux | Windows | Darwin |
|---|---|---|---|
Basic path checks: Exists, IsFile, IsFolder |
Supported | Supported | Supported |
File locks: FileLock |
flock |
Win32 lock API | flock |
File timestamps: GetFileCreationTime, GetFileAccessTime, SetFileTimesE |
ctime/access/modtime via x/sys/unix |
creation/access/modtime via x/sys/windows |
birth/access/modtime via stdlib/syscall |
Memory: Memory |
/proc and syscall.Sysinfo |
Win32 GlobalMemoryStatusEx |
vm_stat and sysctl |
Disk: DiskUsageE |
Statfs |
GetDiskFreeSpaceExW |
Statfs |
OS identity: IsRoot, Whoami |
Supported | IsRoot supported, Whoami returns ERR_UNSUPPORTED |
Supported |
CPU usage: CpuUsage, CpuUsageByPid |
/proc/stat and /proc/<pid>/stat |
Stub returns 0 |
Stub returns 0 |
Process query: FindProcess* |
/proc backed |
wincmd backed basic fields |
Returns ERR_UNSUPPORTED |
Process launch: Command, CommandContext, Start |
Supported | Supported | Supported |
Process lifecycle: ReleaseE |
Starts through normal lifecycle with Setsid |
Starts through normal lifecycle | Returns ERR_UNSUPPORTED |
Process detach: DetachE |
Start-before-Start only, then Process.Release |
Start-before-Start only, then Process.Release |
Returns ERR_UNSUPPORTED |
Run as user: SetRunUserE, DaemonWithUser |
Supported | Returns ERR_UNSUPPORTED |
Returns ERR_UNSUPPORTED |
Keep capabilities: SetKeepCaps, StarCmd.SetKeepCaps |
Package helper uses Linux prctl; command helper preserves current caps via AmbientCaps |
Returns ERR_UNSUPPORTED |
Returns ERR_UNSUPPORTED |
| Network adapters/speeds/connections | /proc/net backed |
IP Helper adapter counters and TCP/UDP owner-pid tables; no Unix socket/inode fields | Returns ERR_UNSUPPORTED |
| Beep | PC speaker or terminal bell fallback | Win32 Beep |
osascript or terminal bell fallback |
API Semantics
ERR_UNSUPPORTEDmeans the symbol exists for build compatibility but the current OS implementation is intentionally unavailable.ReleaseEpreservesStarCmdlifecycle observation:Stopped()still closes after the process exits andExitCode()is populated when available. The historical misspelledStoped()method remains as a deprecated compatibility alias.DetachEis a true detached start path and must be called beforeStart; calling it afterStartreturns an already-started error to avoid racingProcess.Release()with the internalWait().Wait,WaitContext, andWaitTimeoutprovide explicit lifecycle wait helpers that return the final process wait error.Stopped()remains available when callers only need a close signal.- On Linux, the package-level
SetKeepCaps()helper appliesprctl(PR_SET_KEEPCAPS)to the current process.StarCmd.SetKeepCaps()is different: it snapshots the current capability set and configures the child command'sSysProcAttr.AmbientCapsbeforeStart. StdoutChan,StderrChan, andOutputChanprovide best-effort streaming observation for future output chunks. They close withStopped()and do not replace the existing full-output capture methods.RedirectStdout,RedirectStderr,RedirectOutput, andRedirectStdinconfigure process IO beforeStart. File helpers such asRedirectStdoutFileandRedirectStdinFileopen the file and close it after the process reaches its final state.WriteStdinEandWriteStdinStringEwrite raw stdin data without appending a newline.WriteStdinLineEand the legacyWriteCmdEappend one newline.- Legacy methods that do not return errors are kept for compatibility; prefer the
*Evariants for new code.
sysconf Migration
The sysconf package now uses a document-backed INI model instead of the old SysConf struct shape. This is a breaking API change: callers should migrate to NewIni, NewLinuxConf, Document, Section, and Entry directly instead of relying on a field-compatible wrapper.
Minimal migration rules:
- Replace parser setup through
SysConffields with constructors: usesysconf.NewIni()for sectioned INI files, orsysconf.NewLinuxConf(equal)for flat Linux-style config files. - Replace direct segment/key data mutation with section methods:
ini.Section(name),ini.Set(section, key, value),sec.Set,sec.SetAll,sec.AddValue,sec.Delete, andini.DeleteSection. - Replace single-value assumptions with duplicate-aware reads where needed:
ini.Get/sec.Getreturns the first value, whileini.GetAll/sec.GetAllreturns all repeated keys. - Replace manual struct binding with
ini.Unmarshal(&dst)andini.Marshal(src)usingsegandkeytags. - Use
ini.Build()orini.Save(path)for write-back. Unchanged parsed lines keep their original formatting, while changed entries are rebuilt from the new model.
Example:
ini := sysconf.NewIni()
if err := ini.Parse(data); err != nil {
return err
}
app := ini.Section("app")
if app == nil {
app = ini.AddSection("app")
}
_ = app.SetInt("port", 9090, "")
_ = app.SetAll("feature", []string{"stable", "audit"}, "")
out := ini.Build()
INI parser capabilities:
NewIni()parses common sectioned INI files with=and:key/value delimiters,#and;comments, section header comments, quoted values, no-value keys, duplicate keys, duplicate sections, and backslash line continuation.- Inline comments require whitespace before the comment marker, so values such as URLs or fragments containing
#are not truncated accidentally. NewIniWithProfiles(...),StrictINIProfile(), andLinuxConfProfile(equal)let callers pin parser behavior for strict sectioned INI or flat Linux-style config files without mutating parser fields ad hoc.Document.Strictcan be enabled when callers want malformed input to return aParseErrorwith line and column information instead of preserving unknown lines as raw content.- Write-back is lossless for unchanged parsed lines. Changed values that would otherwise be misread as comments, leading/trailing whitespace, tabs, or newlines are emitted as quoted values.
Config framework capabilities:
sysconf.NewConfig(),sysconf.LoadConfig(&dst, files, ...), andsysconf.LoadConfigSources(&dst, sources, ...)load one or more INI sources in order; later sources override earlier values for the same section/key.sysconf.RequiredFile(path)andsysconf.OptionalFile(path)declare whether a missing file should fail loading or be skipped.sysconf.BytesSource(name, data)andsysconf.StringSource(name, data)support in-memory overlays for tests, generated defaults, and embedded configs.Configexposes direct access and write-back helpers:Get,GetAll, error-returning typed getters such asGetIntE/GetBoolE/GetDurationE,Has,Set,SetAll,Delete,Build,Save, andSaveAtomic.- Struct binding uses
seg,key,default,env,split, andrequiredtags. Nested structs inherit their parentsegtag, whileenv:"-"disables environment overrides for a field. - Environment overrides are opt-in through
WithEnvPrefix/WithEnvLookup; generated names normalize section and key names to uppercase underscore form, such asAPP_SERVER_PORT. - Binding supports strings, bools, signed/unsigned integers, floats,
time.Duration,encoding.TextUnmarshaler, slices, arrays, andmap[string]Tfor scalarT. - Repeated INI keys bind naturally to slices. When a single value should expand into multiple collection items, add an explicit
splittag such assplit:",",split:"|", orsplit:"csv". Config.SetStruct(src)writes a config struct back into the current document, using repeated keys for slices/arrays and sortedkey=valuerepeated entries for maps.sysconf.DescribeConfig(src)exports struct tag metadata asConfigFieldInforecords, andsysconf.SampleConfig(src)builds a sample INI from defaults, current struct values, required placeholders, or type zero values without mutating the source struct.Config.SectionNames(),Config.Keys(section),Config.Flatten(), andConfig.FlattenEntries()expose sorted section/key discovery, duplicate-aware flattened values, and structured section/key/value entries for diagnostics, tests, and lightweight config export.ConfigErrorandConfigSourceErrorinclude structured metadata and unwrap their underlying parse, file, or conversion errors forerrors.Is/errors.As.- A config struct can implement
Validate() error; validation runs after defaults, file values, env overrides, required checks, and type binding.
Example:
type AppConfig struct {
App struct {
Name string `key:"name" required:"true"`
Port int `key:"port" default:"8080"`
Timeout time.Duration `key:"timeout" default:"5s"`
Tags []string `key:"tag" env:"APP_TAGS"`
} `seg:"app"`
}
var cfg AppConfig
_, err := sysconf.LoadConfigSources(&cfg, []sysconf.ConfigSource{
sysconf.RequiredFile("/etc/app.ini"),
sysconf.OptionalFile("/etc/app.local.ini"),
}, sysconf.WithEnvPrefix("APP"))
The current framework is intentionally local-file focused. It does not include hot reload, remote configuration centers, secret managers, or a schema DSL.
Scope
This package is intentionally small and cgo-free. Functionality that duplicates broad system inventory packages should stay frozen unless it improves cross-platform semantics, error observability, or compatibility for existing callers.