blog迁移完成
老blog架构说明 之前的blog是通过跑在ECS上的wordpress托管,需要定期更新 WP版本、PHP版本、更新证书,整体的管理复杂度过于复杂。 因此最近调研了一些轻量级的方案,利用AI工具直接把blog做了个完整的迁移和重新部署。 新架构说明 直接把blog文件存在到github 并自动构建静态页面,利用cloudflare pages托管网站,再也不需要去关心底层的各种配置问题了。 本地配置好了obsidian仓库,先试试发布效果。 ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ Obsidian │────▶│ Obsidian │────▶│ GitHub │────▶│ Cloudflare │ │ 编辑文章 │ │ Git │ │ 仓库 │ │ Pages │ │ │ │ 自动提交 │ │ 接收推送 │ │ 自动构建 │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ │ │ │ │ ▼ │ │ │ ┌─────────────┐ │ │ │ │ 网站上线 │ │ │ │ │ blog.gnuers │ │ │ │ │ .org │ │ │ │ └─────────────┘ │ │ │ └───────────────────┴───────────────────┘ 全程自动化,无需手动操作
横向对比cc和openclaw
📊 核心维度对比 维度 Claude Code (Anthropic 官方) OpenClaw (开源社区/Agent 框架) 定位 垂直型: 专为工程开发设计的 CLI 代理。 通用型: 能够连接万物的自主 Agent 平台。 工作流 会话制: 任务导向,随开随用,关闭即结束。 常驻制 (Daemon): 后台 24 小时运行。 交互环境 终端原生: 深入 Git、构建工具、测试框架。 通讯软件: 通过 Telegram/Discord/Slack 指挥。 安全性 高: 官方沙箱、SOC 2 合规、最小权限原则。 一般: 灵活性高但风险大,需自行配置 Docker 隔离。 记忆机制 Session 级别: 每次对话都是新开始(或依赖本地缓存)。 长期记忆: 拥有知识图谱和长期存储(MEMORY.md)。 扩展性 受限(依赖官方 Skills 和 MCP)。 无限: 可接入各类 API、硬件、甚至管理智能家居。 🔍 深度场景分析 1. Claude Code:纯粹的工程生产力 对于开发者,Claude Code 是为了“拿结果”而生的。 杀手锏: 它对代码仓库的理解极其深刻。它能自动分析依赖关系、运行测试用例,并在测试失败时自主修复代码。 适用场景: * 处理你提到的 WordPress 到 Markdown 的复杂迁移逻辑。 ...
测试一下
测试一下本地编写后能否自动发布。
nginx反向代理https网站配置
有老同事前段时间问我,为何最近几年都没怎么更新博客了。我说这两年实在是太忙了,虽然做的事情还是比较多,但是真的是很少有自己的时间静下来写一下blog。 回到主题,我们有时需要在一些特殊的内网环境访问多个https的网站,但是又没有集中的NAT网关。这个时候可以利用nginx做一个集中的代理。代理HTTP的时候是很简单的,简单配置一下proxy_pass到特定的HTTP地址或者是upstream就行,但是如果目标的网站是多个https的,则因为我们没有证书无法简单实现。 幸运的时随着各种客户端对https sni的支持,可以使用TCP模式的代理来支持这种场景,基于对SSL SNI的识别去选择upstream。一个简单的示例如下: map $ssl_preread_server_name $selected_upstream { dockerauth.dockerhub.com upstream_dockerauth; reg.dockerhub.com upstream_reg; dauth.dockerhub.com upstream_dauth; default upstream_dauth; } upstream upstream_dockerauth { dockerauth.dockerhub.com :443; } upstream upstream_reg { server reg.dockerhub.com:443; } upstream upstream_dauth { server dauth.dockerhub.com:443; } server { listen 0.0.0.0:443; proxy_pass $selected_upstream; # proxy_pass $ssl_preread_server_name:443; ssl_preread on; }
通过iptables做VXLAN的vni过滤
背景 有需要要对vxlan的流量做过滤,只允许特定vxlan id的流量访问。 方案调研 通过iptables支持各种策略过滤,但是并没原生的任何插件可以直接支持vxlan报文过滤。后来就想到了2个方案 U32模块本身支持取报文的特定字段做匹配,因此就想到了使用U32。 现在7U的服务器上的iptables是支持bpf的,可以支持使用’-m bpf –bytecode’ 添加编译好的字节码做过滤。 但实际上使用bpf需要单独弄一个工具去生成这个二进制的代码,长期的维护性不是太好,所以虽然最终2个方案都走通了 还是支持选了u32. 我们都知道一个IP报文 里 IP 头是20字节,TCP是20字节,UDP是8个字节,VXLAN是8字节。vxlan的包头如下 ,VXLAN报文本身是封装在UDP报文内,因此一个针对vxlan报文简单的U32匹配可以按下面的逻辑来生产 20 ip+ 8 UDP + 1 VXLAN flags +3 Reserved =32的位置就是VNID左边,因此下面的表达式就可刚好是VNID的区域 -p udp -m udp -m u32 –u32 “32»8=xxxx” 考虑到可能IP头有option,因此也有一个改进的版本 –u32 “0»22&0x3C@12»8=xxx” 详细的原因可以参考:https://netfi lter.org/documentation/HOWTO/netfi lter-extensions-HOWTO-3.html 2. https://ask.wireshark.org/question/10372/sniffi ng-vxlan-traffi c/ 3. https://support.huawei.com/enterprise/en/doc/EDOC1100004365/f95c6e68/vxlan-packet-format 4. https://man7.org/linux/man-pages/man8/iptables-extensions.8.html 5. https://netfi lter.org/documentation/HOWTO/netfi lter-extensions-HOWTO-3.html
GPS授时服务器DIY
国内外厂商制造的高精度时钟服务器实际都是基于x86服务器,加装铷钟和GPS接收模块构成。树莓派流行起来后,网上也有配套的模块,让大家可以制造一个小巧的时钟服务器。实际这淘宝上有很多USB接口的GPS接收模块,产品特性:GPS+GLONASS双模定位内置FLASH,USB供电自适应1200-921600波特率1Hz输出,NMEA-0183协议输出。NTPD是业内对各种GPS接受器支持的最好的,绝大部分GPS接受模块实际都是使用标准的NMEA协议从/dev/gps输出。 测试的配置如下: # For more information about this file, see the man pages # ntp.conf(5), ntp_acc(5), ntp_auth(5), ntp_clock(5), ntp_misc(5), ntp_mon(5). logfile /var/log/ntp.log driftfile /var/lib/ntp/drift Permit time synchronization with our time source, but do not permit the source to query or modify the service on this system. restrict default nomodify notrap nopeer noquery Permit all access over the loopback interface. This could be tightened as well, but to do so would effect some of the administrative functions. restrict 127.0.0.1 restrict ::1 ...
salt定义内核参数
salt的states语句支持直接定义内核参数,比较方便。需要注意的时对于7U的机器得指定config: /etc/sysctl.conf。 net.core.rmem_max: sysctl.present: - value: 67108864 - config: /etc/sysctl.conf net.core.rmem_default: sysctl.present: - value: 33554432 - config: /etc/sysctl.conf
GPS报文格式说明
格式如下 00225s +000000004 0599992.512TDC 0004990.716LST0004989.71FIS $GNGGA,060633.000,3119.3559,N,12135.9948,E,1,22,0.6,51.2,M,0.0,M,,*4A $GNRMC,060633.000,A,3119.3559,N,12135.9948,E,0.00,203.12,160419,,,A*71 $SYS,041619,060634,0,0,1,0,1,0,0,1,2,1,0, +000000004[root@centos1 dev]# cat /dev/gps1 |grep GNGGA$GNGGA,085318.00,3016.36039,N,12006.35748,E,1,12,0.99,37.4,M,7.1,M,,43$GNGGA,085319.00,3016.36042,N,12006.35743,E,1,12,1.04,37.4,M,7.1,M,,40$GNGGA,085320.00,3016.36044,N,12006.35739,E,1,11,1.14,37.4,M,7.1,M,,43$GNGGA,085321.00,3016.36051,N,12006.35748,E,1,11,1.07,37.6,M,7.1,M,,40$GNGGA,085322.00,3016.36057,N,12006.35755,E,1,12,1.06,37.7,M,7.1,M,,4A$GNGGA,085323.00,3016.36062,N,12006.35764,E,1,12,0.97,37.8,M,7.1,M,,49$GNGGA:GPGGA(时间、定位质量)UTC时间,纬度,纬半球,经度,经半球,定位质量标,卫星数量,水平精确度,天、地水准高度,差分GPS数据等, *, 校验和, 回车、换行$GPGGA,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,M,<10>,M,<11>,<12>xx$GPGGA:起始引导符及语句格式说明(本句为GPS定位数据);<1> UTC时间,格式为hhmmss.sss;<2> 纬度,格式为ddmm.mmmm(第一位是零也将传送);<3> 纬度半球,N或S(北纬或南纬)<4> 经度,格式为dddmm.mmmm(第一位零也将传送);<5> 经度半球,E或W(东经或西经)<6> GPS状态, 0初始化, 1单点定位, 2码差分, 3无效PPS, 4固定解, 5浮点解, 6正在估算 7,人工输入固定值, 8模拟模式, 9WAAS差分<7> 使用卫星数量,从00到12(第一个零也将传送)<8> HDOP-水平精度因子,0.5到99.9,一般认为HDOP越小,质量越好。<9> 海拔高度,-9999.9到9999.9米M 指单位米<10> 大地水准面高度异常差值,-9999.9到9999.9米M 指单位米<11> 差分GPS数据期限(RTCM SC-104),最后设立RTCM传送的秒数量,如不是差分定位则为空<12> 差分参考基站标号,从0000到1023(首位0也将传送)。* 语句结束标志符xx 从$开始到之间的所有ASCII码的异或校验维度: dd+mm/60+mmmm/600000维度: ddd+mm/60+mmmm/600000位置定位页面 http://www.gpsspg.com/maps.htm $GNRMC,091655.00,A,3016.36112,N,12006.35204,E,0.042,,200419,,,A6E$GNRMC,091656.00,A,3016.36112,N,12006.35203,E,0.038,,200419,,,A67 $GNRMC,095554.000,A,2318.1327,N,11319.7252,E,000.0,005.7,081215,,,A*73(1) UTC 时间, hhmmss(时分秒)【095554.000】(2) 定位状态, A=有效定位, V=无效定位【A】(3) 纬度 ddmm.mmmmm(度分)【2318.1327】(4) 纬度半球 N(北半球)或 S(南半球)【N】(5) 经度 dddmm.mmmmm(度分)【11319.7252】(6) 经度半球 E(东经)或 W(西经)【E】(7) 地面速率(000.0999.9 节)【000.0】(8) 地面航向(000.0359.9 度,以真北方为参考基准)【005.7】(9) UTC 日期, ddmmyy(日月年)【081215】(10) 磁偏角(000.0~180.0 度,前导位数不足则补 0)【】(11) 磁偏角方向, E(东)或 W(西)【】(12) 模式指示(A=自主定位, D=差分, E=估算, N=数据无效)【A】 ...
salt里定义账号和公钥
salt可以支持账号的增加以及ssh的公钥管理 user_add: user.present: - uid: 1000 - name: myuser - groups: - myuser group_add: group.present: - gid: 1000 - name: myuser - require_in: - user: user_add user_sshkey: ssh_auth.present: - user: myuser - names: - 'ssh-rsa XXXXXX' - 'ssh-rsa yyyyyy' - require: - user: user_add
你所不知道的GPS周数轮转
背景 GPS的时间是基于GPS时间起点(UTC 1980-01-06 00:00:00 ),用经历过一个周数和周内秒数定义的。表述这个周数使用的是一个10bit的字段,因此每过1024周就会出现一次翻转事件。GPS在1999年8月21日出现过周数翻转,今年是在2019年4月6日出现周数翻转。针对此类重点的事件,如果出现问题,会导致公司的整个授时体系的时间回退到1980年,存在所有业务受影响可能性。因此我在前期做了比较多的分析工作。一方面同多家GPS授时服务器的厂商确认是否会有影响,另外一方面自己从相关的文献和代码上确认实际受影响的概率。最终确认这个事件对现在的授时体系100%无影响。 技术原理分析 GPS授时服务器,俗称原子钟。实际的结构是由一个x86服务器(主板上接有铷原子钟或恒温晶振),外接一个可接收GPS/北斗/Galileo信号的天线组成。设备就放在机房的工机具区域,蘑菇头天线置于机房外(绝大部分是置于房顶)。设备上电后,一般几分钟就可以收到4个以上的卫星信号,完成位置锁定和时间同步。开机一段时间后内置的原子钟会被GPS信号驯服,最终趋于一个稳定频率,使得当GPS信号断掉后,还能保持非常高的授时精度。当前世面上设备的常用原子钟的主流精度是年偏差不超过±3ms。GPS的授时服务器内的天线模块,通过解析GPS的L1NAV报文,计算出对应的位置&时间等信息。GPS接收器把原始报文经过一系列的计算后,使用NMEA-0183协议把相应的信息通过串口输出。针对串口输出报文中的GAGGA和GARMC数据做解析,就可以计算出当前的时间和日期。具体的报文是如下格式: $GBGGA,105804.00,3016.36015,N,12006.34368,E,1,10,1.53,14.3,M,7.1,M,,*4A $GBRMC,105805.00,A,3016.36016,N,12006.34352,E,0.120,,210419,,,A,V*1D 其中GBGGA的第二列表示现在是10:58:04,GBRMC的210419表示现在是19年4月21日。整条链路实际上是GPS–(广播)–>接收天线模块—-(芯片处理输出NMEA-0183报文)—-> NTPD处理我们逐个分析可能出问题的环境:1. 接收天线不能正确处理周数轮转,这个只能找厂商确认。2. NTPD在根据报文做处理时,处理错误,这个可以自己从代码里去判断(实际上已经经历过一次周数轮转了,应该不会有问题)。 针对NTPD本身的时间处理,因为NMEA的报文里只有2位的年数和时间,那么当原子钟第一次启动时,其实是需要做判断才能知道这个时间到到底是2019年还是3019年的。NTPD在启动初始化NMEA设备时(也就是GPS接收天线在linux系统中注册的串口设备),会获取到软件编译的时间。而这个时间被NTPD作为额外一个参数传入做关键的判断(如果把编译的时间设置为1980年之前,则会使用1980)。具体的转换函数代码如下 int32_t ntpcal_periodic_extend( int32_t pivot, int32_t value, int32_t cycle ) { uint32_t diff; char cpl = 0; /* modulo complement flag */ char neg = 0; /* sign change flag */ /* make the cycle positive and adjust the flags */ if (cycle < 0) { cycle = - cycle; neg ^= 1; cpl ^= 1; } /* guard against div by zero or one */ if (cycle > 1) { /* * Get absolute difference as unsigned quantity and * the complement flag. This is done by always * subtracting the smaller value from the bigger * one. */ if (value >= pivot) { diff = int32_to_uint32_2cpl(value) - int32_to_uint32_2cpl(pivot); } else { diff = int32_to_uint32_2cpl(pivot) - int32_to_uint32_2cpl(value); cpl ^= 1; } diff %= (uint32_t)cycle; if (diff) { if (cpl) diff = (uint32_t)cycle - diff; if (neg) diff = ~diff + 1; pivot += uint32_2cpl_to_int32(diff); } } return pivot; } 比如如果软件的编译时间是2015年,从GPS报文获取到的时间是19,一个世纪100年,因此调用该函数的时候传入的参数如下:ntpcal_periodic_extend(2015,19,100),最终可以计算出准确的年份是2019年。 ...