atomicfile

package
v1.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 22, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package atomicfile 以「同目录临时文件 + fsync + rename」替换文件, 让并发读者只会看到旧内容或新内容之一,进程中途被杀也不会留下半截文件。

替代的是 os.WriteFile:它的顺序是 O_TRUNC、写入、关闭,于是这两件事都会发生—— 读者在这中间读到空文件或半截内容(config.yaml 读空时 yaml.Unmarshal 并不报错, 界面上会短暂出现「一个 Runner 都没有」),以及进程在截断之后、写完之前退出时, 盘上永久留下一个坏掉的文件。rename 是同一文件系统内的原子操作,两者一并解决: 目标这个名字要么指向旧 inode,要么指向新 inode,没有中间态。

有一处行为与 os.WriteFile 不同,属主:rename 挂上的是新建的 inode,属主是 Manager 的 UID, 而就地写入保留原属主。按文档推荐的部署方式,config/ 与 runners/ 本来就 chown 给 1001, 所以没有影响;属主是其他 UID、而目录对 Manager 可写的少见情况下,写完属主会变成 Manager 的。

另一处是新建文件的权限:本包显式 chmod 到 perm,不经 umask,而 os.WriteFile 的 perm 要过 umask。 这是有意的——config.yaml 该是 0644 就该是 0644,不应随容器的 umask 变。

internal/runner/agenttoken.go 的 EnsureAgentToken 不走这里:那里要的是「只允许第一个 写者」(os.Link 不覆盖已有的名字),这里要的是「最后一个写者覆盖」,语义相反。

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func WriteFile

func WriteFile(path string, data []byte, perm os.FileMode) error

WriteFile 把 data 写入 path,语义对齐 os.WriteFile:

  • 目标已存在时沿用其权限位(os.WriteFile 对已存在文件不改权限,这里保持一致);
  • 目标不存在时使用 perm。

两种环境下拿不到原子替换,此时回退为就地写入(即旧行为)并按路径告警一次, 而不是让一次本该成功的保存失败——升级不该把已经在跑的部署弄停:

  • 目录不可写但文件可写,例如只 chown 了 config.yaml、没 chown config/, 此时同目录建不出临时文件;
  • 目标是单文件 bind mount(-v ./config.yaml:/app/config/config.yaml), 此时 rename 报 EBUSY;临时文件与目标跨文件系统时报 EXDEV。

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL