前几天io实验室的老师找我说让我研究一下这个设备,然后想要把之前张烟的系统部署到上面。
今天拿到设备了。
这边附图:
1

2

3

背面很整洁,没有usb口。借了一个拓展坞,然后升级完系统之后装了一个todesk就可以远程工作了。其实还有更有b格的连接方式,但是因为我不稳定使用,只是部署个系统,所以就用了最习惯的方式。
内置的系统是定制的ubuntu。arm64架构
因为这次可以联网,所以一些中间件打算直接上docker

第一步先是装docker

本来想安装v2rayN,然后科学上网之后再安装,但是实际操作之后,发现节点无法使用。
本来是直接安装的deb包,但是 hysteria 节点用不了,vless 跑不通。现在打算下zip版试一下。要是不行就用阿里云的源。

用zip版可以。

最后因为是桌面ubuntu,懒得折腾 就装了docker-desktop
好吧,犯不了懒,这个gui界面实际上还是得装docker依赖才能运行,不是独立的另外一套。
好像下载的只有amd64的版本,没有arm64的版本
原来是有的。但是官网找不到。直接改了下 amd64的下载链接,从他们仓库直接下载了

https://desktop.docker.com/linux/main/arm64/235549/docker-desktop-arm64.deb

第二步把源码找出来,一共是三个部分,一个统一的后端,一个react前端和一个unity后端。
后端是go,需要先安装下go。主要就是把go安装放到bin目录

sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.x.linux-arm64.tar.gz
echo 'export PATH="/usr/local/go/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
go version

前端react前端需要装一下nodejs
这个直接看官网,有很详细的bash脚本

需要的中间件就是 mysql,redis,etcd,ngnix
mysql和ngnix需要配置data路径
redis和etcd啥都不用配,暴露端口就行

### MySQL

docker run -d \
    --name mysql \
    -p 3306:3306 \
    -e MYSQL_ROOT_PASSWORD=your_password \
    -v /data/mysql:/var/lib/mysql \
    --restart unless-stopped \
    mysql:8.0

- -p 3306:3306:映射 MySQL 端口
- MYSQL_ROOT_PASSWORD:root 用户密码
- -v /data/mysql:/var/lib/mysql:配置 MySQL 数据目录
- --restart unless-stopped:Docker 重启后自动启动

### Redis

docker run -d \
    --name redis \
    -p 6379:6379 \
    --restart unless-stopped \
    redis:7

- -p 6379:6379:映射 Redis 端口

### Etcd

docker run -d \
    --name etcd \
    -p 2379:2379 \
    -p 2380:2380 \
    quay.io/coreos/etcd:v3.5.15 \
    /usr/local/bin/etcd \
    --name=etcd0 \
    --listen-client-urls=http://0.0.0.0:2379 \
    --advertise-client-urls=http://127.0.0.1:2379 \
    --listen-peer-urls=http://0.0.0.0:2380 \
    --initial-advertise-peer-urls=http://127.0.0.1:2380 \
    --initial-cluster=etcd0=http://127.0.0.1:2380

- 2379:Etcd 客户端访问端口
- 2380:Etcd 节点通信端口
- 不配置数据目录,数据随容器生命周期保存

### Nginx

docker run -d \
    --name nginx \
    -p 7654:80 \
    -v /opt/zyproject/data/nginx:/usr/share/nginx/html:ro \
    --restart unless-stopped \
    nginx:1.27

- -p 80:80:映射 Web 服务端口
- -v /data/nginx:/usr/share/nginx/html:ro:配置 Nginx 网站数据目录
- :ro:容器只读挂载;需要容器写入时可以去掉 :ro

在尝试运行react前端的时候遇到了权限问题。npm dev
sh: 1: next: Permission denied

前面加sudo就识别不出指令
sudo: npm:找不到命令

docker那边是网络连不上
Unable to find image 'hello-world:latest' locally
docker: Error response from daemon: Get "https://registry-1.docker.io/v2/": context deadline exceeded

Run 'docker run --help' for more information

直接跑也是没有权限
permission denied while trying to connect to the docker API at unix:///var/run/docker.sock

不加代理就是
Unable to find image 'hello-world:latest' locally
docker: Error response from daemon: Get "https://registry-1.docker.io/v2/": dial tcp 108.160.170.44:443: connect: connection refused

Run 'docker run --help' for more information

然后在docker desktop里面就是显示docker engine stoped难绷

感觉没有很简单,唉。

docker desktop先不管。
正常run 镜像出现的问题,我v2rayN开了tun模式之后解决了。

最后发现还是太慢了。于是配置了Docker 镜像源

编辑:

sudo vim /etc/docker/daemon.json

写入:

{
  "registry-mirrors": [
    "https://docker.1ms.run"
  ]
}
这是毫秒镜像

然后重启 Docker:

sudo systemctl daemon-reload
sudo systemctl restart docker
sudo docker run hello-world

https://github.com/dongyubin/DockerHub
这个github仓库记录了还能用的docker镜像

对于mysql需要导入数据
可以启动docker的加一个数据的挂载
如果备份文件是 .sql,可以挂载到容器的 /backup 目录。

docker run -d \
    --name mysql \
    -p 3306:3306 \
    -e MYSQL_ROOT_PASSWORD=admin123 \
    -v /opt/zyproject/data/mysql:/var/lib/mysql \
    -v /opt/zyproject/data/mysql-backup:/backup:ro \
    --restart unless-stopped \
    mysql:8.0

备份文件就放到mysql-backup文件夹里面,backup是容器内备份目录

或者是导入已有 MySQL 容器

docker exec -it mysql sh -c \
  'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" your_database < /backup/backup.sql'

也可以直接 docker 进入bash界面然后:

mysql -u root -p your_database < /backup/backup.sql

如果备份文件中已经包含 CREATE DATABASE 和 USE,可以直接执行:

docker exec -it mysql sh -c \
  'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" < /backup/backup.sql'
只有全新初始化、/var/lib/mysql 为空时,挂载到 /docker-entrypoint-initdb.d 的 SQL 文件才会自动执行;已有数据库需要手动导入。

对于 unity 的前端来说应该还需要改一下前端js里面拉取数据的地址,有点麻烦,明天看吧。
今天先把后端搭建起来,然后把react前端搭建起来

react前端的问题是next没有执行权限。因为前端其实是nextjs搭建的。
然后node_modules是直接外面复制过来的,所以会有权限问题

用的deepseek网页版好快的回复

给 node_modules/.bin/next 添加执行权限:

chmod +x node_modules/.bin/next

然后重新运行:

npm run dev

go mod tidy 也很慢,最后改了下镜像

go env -w GOPROXY=https://goproxy.cn,direct

好感慨。又是一年暑假。做的事情都是去年的延伸,但是今年的心气却是没有了,也没有了想要熬夜完成项目的想法,更多的是比较摆烂。实习也没找到hhh。
更多的还是感慨时间过的好快。好怀念去年。

go 后端运行发现

admin@cube-f89a:/opt/zyproject/zhangjiakou-tobacco-factory$ go run main.go
# github.com/bytedance/sonic/internal/rt
/home/admin/go/pkg/mod/github.com/bytedance/[email protected]/internal/rt/stubs.go:33:22: undefined: GoMapIterator
/home/admin/go/pkg/mod/github.com/bytedance/[email protected]/internal/rt/stubs.go:36:54: undefined: GoMapIterator

项目的是1.23 服务器上的是1.26
查了一下是项目的go版本和服务器上的不兼容。
具体是因为 github.com/bytedance/sonic v1.13.3 和服务器上的 Go 版本不兼容导致的编译错误。

在项目本地依赖里面,sonic/internal/rt 里定义 GoMapIterator 的文件有这些 build tag:

map_legacy.go !go1.24
map_nosiwss_go124.go go1.24 && !go1.25
map_siwss_go124.go go1.24 && !go1.25

也就是说 sonic v1.13.3 只覆盖到 Go 1.24,如果 Go版本在 1.25 或更新版本,这些文件都会被排除,结果 stubs.go 里还在引用 GoMapIterator,于是报:

undefined: GoMapIterator

最后使用

GOTOOLCHAIN=go1.23.6 go run main.go

用1.23.6的环境来运行

之后出现了

panic: open log/nms/nms.log_2026-08-06 11-10-04: permission denied

goroutine 1 [running]:
vis/pkg/logger.SetLogger({0x4000787f70?, 0x5?})
    /opt/zyproject/zhangjiakou-tobacco-factory/pkg/logger/logger.go:99 +0xfa8
main.main()
    /opt/zyproject/zhangjiakou-tobacco-factory/main.go:21 +0xc0
exit status 2

这个是因为程序没有权限在 log/nms/ 目录下创建日志文件。要给文件夹及其所有子文件夹和文件设置权限.

给文件夹及所有子内容添加写权限

sudo chmod -R 755 /opt/zyproject/zhangjiakou-tobacco-factory/log/

对于微服务也是

GOTOOLCHAIN=go1.23.6 go run ./microservices/visible/visible.go
GOTOOLCHAIN=go1.23.6 go run ./microservices/forecast/forecast.go

跑完报错 没有找到 vis (数据库名)
应该是原来的数据库备份sql文件里没有创建数据库这一步,难绷

docker进入一下bash

docker exec -it <容器名或ID> /bin/bash

进一下mysql命令行

mysql -u root -p

创建一下数据库

CREATE DATABASE vis CHARACTER SET utf8mb4;

下面就开始部署unity前端。其实就是把静态文件放到nginx的目录里面

# 将 source_folder 内的所有内容复制到目标目录
cp -r /path/to/source_folder/* /opt/zyproject/data/nginx/

# 如果需要包含隐藏文件(以 . 开头的文件)
cp -r /path/to/source_folder/. /opt/zyproject/data/nginx/

unity 的前端可以部署,部署完之后也有内容,数据应该是之前的缓存。
做的还挺顺利就打算把unity的一块搞了

感觉现在agent出来之后确实不一样。像是之前要是配置什么忘记了还得找下路径,现在直接让agent找了。唉

试运行部署成功

最后就是安装tmux然后常驻后台就行
tmux有一个问题,就是无法重启之后自动恢复。
有一个tpm插件可以保存快照,下次系统重启了,再启动一次tmux就可以了
但是我想要的效果是重启之后可以自动的恢复。tmux还需要手动做一步

后面还是用pm2来管理。主要是它是支持的重启之后自动恢复,另外一方面就是对于nextjs来说要是想要用system来做,大概只能打包之后放nginx?但是这个项目应该算是后端架构,我不知道怎么搞。最好还是直接pm2来启npm run dev。包括go也是不是很想打包,最后直接用pm2来管理最方便了。

安装pm2的时候根据脚本的指引有一个注销的操作。我点注销之后,应该是把todesk的进程杀掉了。难绷。现在实验室貌似没有人,没有办法帮我开机。我是远程todesk操作来着。现在只能等明天去弄了。

心里有点慌张,主要是怕会坏掉。采购价应该挺贵的。
最后还是去实验室了一下。
明天再把这些命令挂到pm2上面应该就可以完工了。

安装pm2

npm install pm2 -g

之后就是用pm2启动命令,然后保存列表

# 1. 启动应用
pm2 start "go run main.go" --name "my-go-app" --interpreter none
# 2. 保存当前进程列表
pm2 save
# 3. 设置开机自启
pm2 startup

--interpreter none 告诉 PM2 不要用 Node.js 来解释,直接执行原始命令
--name "my-go-app" 给进程起个名字,方便管理

ok完工。感觉是把半天的工作量分了三天来做,hhh。

7月快乐。
逐渐适应了实训生活。生活变得平静。偶尔还是会很难过。

可以把 LoadCurrentUser 分成两种状态来处理:

  1. 没有 cookie
    这是“匿名访问”,直接放行,不报错。
  2. 有 cookie,但 session 无效/过期/查不到用户
    在 context 里标记出来。

核心思路是:LoadCurrentUser 只负责“尝试加载”,不要默认把所有异常都 401 掉。
可以这样做:

func LoadCurrentUser(db *gorm.DB) gin.HandlerFunc {
    return func(c *gin.Context) {
        sessionID, err := c.Cookie("session_id")
        if err != nil {
            c.Next()
            return
        }

        if sessionID == "" {
            c.Next()
            return
        }

        var session models.Session
        if err := db.Where("session_id = ?", sessionID).First(&session).Error; err != nil {
            c.Set("authError", "invalid_session")
            c.Next()
            return
        }

        if session.RevokedAt != nil || (session.ExpiresAt != nil && session.ExpiresAt.Before(time.Now())) {
            c.Set("authError", "expired_session")
            c.Next()
            return
        }

        var user models.User
        if err := db.Preload("Roles.Permissions").First(&user, session.UserId).Error; err != nil {
            c.Set("authError", "user_not_found")
            c.Next()
            return
        }

        c.Set("currentUser", user)
        c.Set("sessionId", sessionID)
        c.Next()
    }
}

然后 RequireAuth 再决定怎么报错:

func RequireAuth() gin.HandlerFunc {
    return func(c *gin.Context) {
        if user, ok := c.Get("currentUser"); ok && user != nil {
            c.Next()
            return
        }

        if authErr, ok := c.Get("authError"); ok {
            c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"msg": authErr})
            return
        }

        c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"msg": "unauthorized"})
    }
}

这样效果就很清楚:

  • 公共接口:

    • 没 cookie,正常访问
    • 坏 cookie,也正常访问,但你可以选择是否在响应里提示前端重新登录
  • 私有接口:

    • 没 cookie,401 unauthorized
    • 坏 cookie,401 invalid_session / expired_session

本质其实就是把报错信息放到上下文,然后给需要经过auth中间件的路由去拦截,如果不会经过auth中间件就放行。

这个学期主要做了什么?

社团工作:

  1. 寒假的时候主持了蓝桥杯集训以及报名工作 一整个寒假-开学初
  2. 进行了天梯赛的选拔和报名工作 3月8日-3月15日
  3. 钉耙编程春季联赛报名 3月11日
  4. 参与了第一届津冀联合高校大学生程序设计竞赛的相关工作 4月26日
  5. 参与了研究生复试的相关工作3月25日 - 4月10日
  6. 负责邀请赛的报名工作 4月开始到5月下旬

比赛:

  1. 蓝桥杯省,国赛 4 月11 日、6月6日
  2. 天梯赛团体赛 4月18日
  3. 南昌ic 5月16-17日
  4. 广西cc 5月31号
  5. 贵州cc 6.7

保研:

  1. 大创结题答辩 5月14日
  2. 英语6级考试 6月13日

哪些第一次做?

  1. 健身
  2. 系统学了下javase和spring框架

获得什么成就?

  1. 蓝桥杯国三
  2. 天梯赛国三
  3. 广西cc邀请银牌
  4. 贵州cc邀请银牌

有哪些遗憾?

  1. 画画没有坚持下来
  2. 这学期go学习的比较少,大创项目为了赶时间大部分都是无审查的vibe coding,做的有点不好
  3. 6级花的时间比较少,大概率还是没过的
  4. 蓝桥杯没有花时间准备只有国三
  5. 社团的工作比想象中的要多,没有平衡好工作和学习,导致算法水平拉跨了

一开始的目标是什么?都达到了吗?

  1. 想要过6级,不过貌似是没过的
  2. cc邀请赛想要一个铜牌,算是超额完成任务
  3. 蓝桥杯想要一个国二,不过有点遗憾依旧国三

对这学期的想法?

依旧迷茫,处于保研和工作之间摇摆。其实主要是出于继续比赛和出去实习之间摇摆。可能是社团工作确实比较多,这学期一直想的是赶紧交接工作。好在虽然我看人眼光一直不怎么样,这次的运气似乎还挺不错。遇到了两个还算是挺负责的人,挺好。acm那边基本上是退休了,后面就跑到io去养老。不过这学期有本科生科研招募,io那边的老师招了一批人,准备搞一些机器狗机械臂相关的项目,我也不知道能不能接着待下去。虽然我是负责人,但是遇到对我来说比较陌生的领域还是有点打怵,我本来过去是打算做做软件开发的外包,现在的情况有点出乎我的意料。其实我一直喜欢io就是因为我的朋友都在那边。不过玩的特别好的其实也就几个。学长都毕业了,ylx和山东人大概也马上大四不在实验室。谢bro和广东人大概准备去做电子硬件方向的实验室,语语一直在工创中心。我有点害怕到时候io只剩我一个人,到时候就是面对的都是陌生面孔,可能也不想去了。其实我不是想去养老,我应该只是想呆在那一批人身边。不过每个人都有自己要做的事情,我也一样,如果这次有遇到合适的日常实习我大概率下学期也不在学校。时间过得好快。大一的时候还是跟在别人后面,对大学生活充满了陌生和不适应。现在也已经构筑好了自己的人际关系网,不会觉得太孤单,对自己的发展也有了笼统的想法和一点点的规划。不过刚刚有起色的时候就又要分别多少还是难受的。祝愿大家都有光明的未来。

对下学期的展望?

  1. 在学超级桂花糕的谱子,狠狠弹吉他
  2. 6级暑假的时候猛猛刷题,希望下学期过掉
  3. 保持健身的习惯,保持良好作息
  4. 希望可以找到一个日常实习,打算出去一个人住一学期

page1
在obsidian的第三方插件市场搜索 agent 。然后安装
这个插件主要用到了acp协议

ACP (Agent Client Protocol) 是由 Zed Industries 开发的开放协议,旨在标准化编辑器与 AI Agent 间的通信。它通过 JSON-RPC 消息传递,将编辑器(如 Obsidian)与 AI Agent(如 Claude Code)解耦。

看官方文档安装一下

https://rait-09.github.io/obsidian-agent-client/agent-setup/codex.html

npm install -g @zed-industries/codex-acp

page2

然后在设置里面第一步将default agent改为codex
然后第二步设置 node.js path 那边点一下 auto detect 会自己找到对应的cmd程序
之后就可以使用了