main.go 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. // agent-mounter:资料库挂载服务(docs/design/21-knowledge-sources.md §4)。
  2. // 以部署用户运行,把本机目录(以后还有远程存储)只读挂到 knowledge/mnt/<id>,隐藏以 . 开头的文件。
  3. package main
  4. import (
  5. "flag"
  6. "log"
  7. "net"
  8. "os"
  9. "os/signal"
  10. "path/filepath"
  11. "syscall"
  12. "golang.org/x/sys/unix"
  13. )
  14. const version = "1.0.0"
  15. func main() {
  16. dir := flag.String("dir", "/srv/agent-server/mounter", "挂载服务目录(socket、密钥、state.json)")
  17. mnt := flag.String("mnt", "/srv/agent-server/knowledge/mnt", "挂载点所在目录")
  18. showVersion := flag.Bool("version", false, "显示版本")
  19. flag.Parse()
  20. if *showVersion {
  21. println(version)
  22. return
  23. }
  24. log.SetFlags(0)
  25. log.SetOutput(os.Stderr)
  26. var st unix.Stat_t
  27. if err := unix.Stat(*dir, &st); err != nil {
  28. log.Fatalf("挂载服务目录不存在:%s(先执行 deploy/deploy.sh)", *dir)
  29. }
  30. gid := int(st.Gid)
  31. if err := unix.Stat(*mnt, &st); err != nil {
  32. log.Fatalf("挂载点目录不存在:%s", *mnt)
  33. }
  34. unix.Umask(0o027)
  35. mgr := newManager(realSystem{}, allowedRoots, filepath.Clean(*mnt), filepath.Join(*dir, "state.json"))
  36. mgr.cleanupStale()
  37. if specs := mgr.loadState(); len(specs) > 0 {
  38. if _, err := mgr.sync(specs, false); err != nil {
  39. log.Printf("按 state.json 恢复挂载失败:%v", err)
  40. } else {
  41. log.Printf("已按 state.json 恢复 %d 个挂载", len(specs))
  42. }
  43. }
  44. stop := make(chan struct{})
  45. go mgr.watchMountinfo(stop)
  46. srv := &server{token: newToken(), mgr: mgr, version: version}
  47. sock := filepath.Join(*dir, "mounter.sock")
  48. _ = os.Remove(sock)
  49. l, err := net.Listen("unix", sock)
  50. if err != nil {
  51. log.Fatalf("监听 %s 失败:%v", sock, err)
  52. }
  53. if err := os.Chown(sock, -1, gid); err != nil {
  54. log.Fatalf("设置 socket 的组失败:%v", err)
  55. }
  56. if err := os.Chmod(sock, 0o660); err != nil {
  57. log.Fatalf("设置 socket 权限失败:%v", err)
  58. }
  59. if err := writeGroupFile(filepath.Join(*dir, "token"), []byte(srv.token+"\n"), 0o640, gid); err != nil {
  60. log.Fatalf("写入密钥失败:%v", err)
  61. }
  62. go srv.serve(l)
  63. log.Printf("agent-mounter %s 已启动:%s", version, sock)
  64. sig := make(chan os.Signal, 1)
  65. signal.Notify(sig, syscall.SIGTERM, syscall.SIGINT)
  66. <-sig
  67. close(stop)
  68. l.Close()
  69. mgr.unmountAll()
  70. log.Printf("已停止")
  71. }