本来这台 HP Chromebook 11A G6 EE( 加了一张 128G 的 TF 卡 ),我安装好了 Arch Linux(Xfce),都弄好了的,但最近在知乎上老被安利说装 Debian 的 testing 版,于是我又开始折腾,把 Debian 13 testing(trixie) 安装到这台 Chromebook 上。
安装时,使用 lvm 分区不成功,系统报错:
partman-lvm: pvcreate: error while loading shared libraries: libaio.so.1: cannot open shared object file: no such file or directory
现在想想可能还有其他办法,比如想办法把这个需要的包注入进去,但当时选择了先用 ext4 分区安装系统自带的 16G 的卡里,装完以后再想办法转成 lvm 并把 TF 卡的空间加进来。
自带存储的设备号是:/dev/mmcblk1,容量只有 16G
这一步基本上没什么问题,我只讲一下最后自带存储的分区:
这一步应该是重中之重,难度、复杂度都在这里。
TF 卡的设备号是:/dev/mmcblk0,容量 128G
1 | apt-get install lvm |
1 | mkdir /mnt/new_root |
接着还要修改新根区下 etc/fstab 的内容,将挂载在 / 的设备改成 /dev/vg_root/lv_root
1 | vi /mnt/new_root/etc/fstab |
1 | mount --bind /dev /mnt/new_root/dev |
最后的收尾工作:
最后,重启系统迁移这一步应该就好了
1 | shutdown -r now |
自带的存储的设备是:/dev/mmcblk1,老根区的设备号是:/dev/mmcblk1p2
电脑重新起来后,登录进去
1 | wipefa -fa /dev/mmcblk1p2 |
如此,便完成了。
]]>监控在云资源管理中占据了核心地位,它可以帮助我们实时追踪资源状态,从而快速发现并处理潜在的问题。本文将介绍如何利用 AWS CloudWatch 监控云数据库服务RDS,并通过企业微信发送报警通知,以达到高效运维的目的。
本文所述的监控方案包含以下几个关键步骤:
这里有个知识点需要了解,否则就会有困惑:RDS 的 event 是怎么到 CloudWatch 里去的呢?是这样的,RDS 基础的 Metrics 是会自动打到 CloudWatch 里去的。所以我们如果只是监控这些基础的 Metrics 的话是不用在 EventBridge 里再建规则把 RDS 的 event 打到 CloudWatch 里了。
在设置 AWS CloudWatch 监控和报警之前,我们需要先在企业微信中创建一个机器人,并获取它的 Webhook Token,后续步骤中将会用到。以下是创建机器人的操作步骤:
配置完成后,记得将获取到的 Token 添加到 AWS Lambda 的环境变量 WX_TOKEN 中。
在获取了企业微信机器人的 Webhook Token 后,就可以开始设置我们的监控和报警系统了。该系统分为以下几个步骤:
首先,我们需要在 CloudWatch 中为 RDS 创建告警规则。具体步骤(以 Metric: CPUUtilization 为例)如下:
接下来,按照 AWS 官方关于监控的最佳实践 的说法,我们还需要继续监控如下几个 Metrics: DatabaseConnections
, EBSByteBalance%
, EBSIOBalance%
, FreeableMemory
, FreeLocalStorage
, FreeStorageSpace
, MaximumUsedTransactionIDs
, ReadLatency
, ReplicaLag
, WriteLatency
, DBLoad
, AuroraVolumeBytesLeftTotal
, AuroraBinlogReplicaLag
, BlockedTransactions
, BufferCacheHitRatio
, EngineUptime
, RollbackSegmentHistoryListLength
和 StorageNetworkThroughput
,注意:这些 Metrics 不一定都同时都有的,没有的自然就跳过就好了。
接下来,我们需要创建一个 SNS 主题,用于接收 CloudWatch 的告警消息。具体步骤如下:
现在,我们来编写一个 Lambda 函数,用于解析 SNS 消息并发送到企业微信。以下是 Python 代码示例:
1 | import json |
在代码中,我们首先解析 SNS 消息,提取报警的各种细节,如报警名称、描述、账号 ID、区域、指标名称等。然后构建一个 Markdown 格式的消息内容,并通过企业微信的 Webhook 接口发送出去。
注意,你需要将代码中的 WX_TOKEN 替换为你自己的企业微信机器人 Token。
Lambda 函数的核心逻辑就是解析 SNS 消息,提取关键信息,然后构建企业微信消息并发送。通过使用 Markdown 格式,我们可以让消息内容更加美观和易读。
还有,为什么这里用 http.client 而不是更常用的 requests,那是因为前者是 Python 3.x 自带的模块而后者不是,所以用后者的话还需要单独再安装,这在 lambda 里就不能用直接在 web console 直接写代码这种方便明了的方式了,而是还需要在本地找个环境,把需要的包(requests)安装好,打成包,再上传上去。相对这要麻烦太多了。
最后一步,我们需要将 SNS topic 与 Lambda function 关联起来。这样,当 CloudWatch 触发告警时,就会自动通过 SNS 的 topic 内容驱动调用 Lambda fuction,进而发送消息到企业微信。
通过本文,我们学习了如何使用 AWS CloudWatch 监控 RDS,并通过 SNS、Lambda 和企业微信实现报警功能。这个方案可以帮助我们及时发现和解决 RDS 的各种问题,提高系统的可用性和稳定性。
]]>大家好,我是老杨。在这篇文章中,我将带大家深入了解如何利用 GitHub Action 自动化部署 Chalice 应用到 AWS Lambda。这不仅是一个技术实践,也是对 CI/CD 流程优化的一次探索。
在现代软件开发中,快速迭代和持续部署是提高开发效率的关键。Chalice 是一个用于部署 Python 应用到 AWS Lambda 的框架,而 GitHub Action 提供了一个强大的自动化平台。结合这两者,我们可以创建一个无缝的部署流程。
Chalice 是一个 Python 框架,它使得在 AWS Lambda 和 API Gateway 上部署无服务器应用变得简单。它允许开发者使用熟悉的 Python 语法来定义 Lambda 函数和 RESTful API,同时提供了丰富的配置选项来满足不同的部署需求。
让我们来看一下这个工作流的核心内容。以下是一个简化的工作流文件示例,它展示了如何配置和执行部署任务。
1 | name: Deploy xxxxx-indexer manually using Chalice |
在这个工作流中,我们定义了两个输入参数:branch
和 environment
。这允许我们在启动工作流时指定要部署的分支和环境。我们还设置了环境变量,这些变量在部署过程中会被用来配置应用。
接下来,工作流会检出指定分支的代码,删除现有的 Chalice 配置文件,并从 CI/CD 仓库中检出新的配置。然后,我们设置 Python 环境,安装依赖,准备配置文件,并配置 AWS 凭证。最后,我们执行 Chalice 部署命令,将应用部署到 AWS Lambda。
在我们的工作流中,actions/cache
用于缓存 Python 的 pip 依赖。这可以显著提高后续部署的效率,因为依赖项不需要每次都重新下载。缓存的键是基于操作系统和依赖文件的哈希值,这确保了缓存的一致性和可恢复性。
在部署完成后,Chalice 生成的 JSON 文件包含了部署的详细信息。将这个文件推送回 CI/CD 仓库有助于我们跟踪部署历史,管理配置,并在必要时进行回滚。这是一种确保部署过程透明和可审计的重要实践。
通过这个详细的 GitHub Action 工作流,我们实现了 Chalice 应用的自动化部署。这个过程不仅简化了部署步骤,还提高了部署的可靠性。我希望这篇文章能够帮助你更好地理解如何利用 GitHub Action 来优化你的 CI/CD 流程。
如果你有任何问题,或者想要了解更多关于这个话题的信息,欢迎留言讨论。别忘了点赞和分享哦!
]]>最近相当长一段时间,都在调 GitHub action 的 workflow 比较多,而 GitHub 官网时不时抽风,于是就有了在命令行看 GitHub action jobs 的执行情况的需求。
1 | brew install gh |
下载链接:https://github.com/cli/cli/releases/download/v2.40.0/gh_2.40.0_macOS_amd64.zip
1 | gh auth login |
然后按照提示一步一步走就行了。
但是我建议的还是下面这种:
1 | gh auth login --with-token < mytoken.txt |
这里的 mytoken.txt 里的内容来自于:GitHub 官网右上角依次点击 个人头像->Settings,再点左边栏下方 “Developer Settings”,然后再在左边栏点击 “Personal access tokens” 下的 “Tokens(classic)”,在这个页面里创建一个 “PAT(personal access token)”,这个放在 mytoken.txt 文件里就好了。
能用的场景很多,我只讲下我用的场景
1 | cd xxxxxxxxxxx |
因为数据库放 VPC 私网网段里了,然后研发有各种直连数据库的需求,其实也有 VPN 方案,但有的研发认为先拨 VPN 不太方便,而我正好认识到 ssm,觉得挺有意思,所以就有了这篇文章的出炉。
其实实际上,都有了 EC2 了,直接上面建账号,几乎所有的 MySQL 的 GUI 客户端,都支持 ssh tunnel 来连数据库,这样就不需要手工命令自己打洞了,MySQL 的 GUI 客户端就一起给你搞定了,这部分还会再水一篇文章。可是,真的值得吗?后话再说。但 ssm plugin 方案比 ssh tunnel 方案更牛逼的一点是:ssm plugin 方案里,EC2 不需要有公网地址!
1 | # 我的本地环境是 Macbook Air (m1), |
如果是Windows环境,可从以下网址下载session-manager-plugin并安装
1 | aws \ |
最后成功后显示:
Note: 这种“登录” EC2 服务器跟 ssh 登录 EC2 服务器相比,缺点就是不能上传下载数据。
1 | aws \ |
成功后显示:
这时候,再开一个控制台,测试如下:
发现本地的 5555 端口是开着的,如果用 MySQL 客户端来连的话,会发现连上的正好是 MySQL。
]]>在 AWS 的一个 VPC 内部的一台 EC2 上搭了一个 OpenVPN 服务器,对,就是 从 Client VPN endpoint 迁移到 EC2 上的 OpenVPN 提到的这件事。然后我有台 PC 通过 OpenVPN 客户端软件连了过来。以下是基本信息。
NOTE: IP 地址都不是实际真实情况
1.1.1.1
(本地并没有,这个是防火墙或其他设备给做的一对一 map)10.0.0.2/24
10.0.0.1
172.16.0.1/24
172.16.0.2/24
问题的核心是:B 无法 ping 通 A 的私网 IP。换句话说,当我在 B 上执行 ping 10.0.0.2
命令时,无法得到响应。俗话就是 ping 不通 10.0.0.2。
我对 AWS EC2 的网络问题进行了深入的排查,包括各种路由表、安全组、网络 ACL,甚至本地的防火墙配置等等。然而,我并没有找到问题的所在。我可以访问 VPC 内部的私网里的 RDS 资源,也可以在 A 上明显看到有接收到数据包。
我继续深入,发现在 A 上可以接收到 B 发送的 icmp 包,而且 A 也确实有回包,但是奇怪的是,回包并没有通过 tun0 设备,而是直接从 enX0 设备发送出去!
马上怀疑本地路由有问题,直接在 A 上执行
1 | ip r get 172.16.0.2 |
发现没问题呀,是从设备 tun0 走的呀?这下就完全把我给整不会了。再此之后,我还做了好些努力,比如:
ping 172.16.0.2
,当然是通的ping -I 10.0.0.2 172.16.0.2
,这种指定源 IP 的方式 ping,当然是不通的,同样问题,听包发现包没往 tun0 设备上走,而是往 enX0 上走了多番努力,虽然没有结果,但是慢慢还是明白了问题所在就是为什么从 10.0.0.2 出去按路由表应该往 tun0 上走的包却走到了 enX0 上?“这还是路由的问题“,我盖棺定论。
老想想不出为什么,于是就上网找了找 Linux 高级路由的资料看了看,突然想起来:Linux 系统里,路由选择上比路由表级别更高的还有一个:路由策略!柳暗花明呀。
我立马起来,登录上 EC2,
1 | ip rule s |
果然有一条记录:
10000: from 10.0.0.2 lookup 10000 proto static
果然有货,再接着看这条 id 是 10000 的路由表里有什么:
1 | ip r s table 10000 |
系统显示:
default via 10.0.0.1 dev enX0 proto dhcp metric 512
10.0.0.0/24 dev enX0 proto static scope link
这一下子逻辑就清晰了,源地址是 10.0.0.2、目标地址是 172.16.0.2 的数据包之所以会往 enX0 上走是因为路由策略 10000: from 10.0.0.2 lookup 10000 proto static
,这个策略规定了源地址是 10.0.0.2 的数据包怎么走要看路由表 10000,而在 10000 这张路由表又是这样的:
default via 10.0.0.1 dev enX0 proto dhcp metric 512
10.0.0.0/24 dev enX0 proto static scope link
按照这个路由表,去往 172.16.0.2 的数据包不妥妥的要往 enX0 上发吗?
最后,我还要做最后一个测试,以验证我的结论:
1 | sudo ip r add 172.16.0.0/24 \ |
然后,那边在 B 上 ping 10.0.0.2
马上就通了。
最后的最后,我把刚加的这条路由删掉了,因为我还没想好要不要修以及怎么修这个问题。
1 | sudo ip r del 172.16.0.0/24 table 10000 |
由于 Amazon Linux 2023 中在策略路由里将从 EC2 私网地址为源地址的数据包强制走了另外一张路由表,在那张表里源地址为 EC2 私网地址的数据包会走 enX0,而我的 OpenVPN 服务启动时只修改了缺省的路由表:main,故而导致从 OpenVPN 的客户端不能通 EC2 的私网地址。
所以,这到底是 Amazon Linux 2023 的 bug 呢,还是 OpenVPN 的 bug 呢?这个问题还需要进一步的探讨和研究。
]]>某个项目用了 linear.app 来做任务分配和跟踪,为了写周报,想利用 API 来自动获取任务信息。
在 linear.app 里,点击自己的头像->Settings,点击左边导航栏的 API
,在右边页面的 Personal API keys
下面 Create key
一下,然后记住。
linear.app 的官方的 SDK 是 TypeScript 写的,但实际上 JavaScript 也是兼容的吧。官方给的安装 SDK 的命令就是下面这个:
1 | npm install @linear/sdk |
linear.app 的公开的 API 都是用 GraphQL 搭建的,官方也建议用 GraphQL 来获取数据
前方高能预警:调包侠再次上线!
核心实现代码:
1 | import { LinearClient } from '@linear/sdk' |
把以上代码存为文件:linear.js
,再用 Node.Js 来跑一下:
1 | node linear.js |
周报出炉!
]]>VPC 内需要有一台 EC2(有无公网 IP 好像没关系),并做好相关配置
Amazon Linux(无论是 1,还是 2,或者是 2023) 一般是预装好的,只需要确认是否正常启动:
1 | sudo systemctl status amazon-ssm-agent |
如果系统没有安装过 SSM Agent,那么安装(以 CentOS 8 为例):
1 | sudo dnf install -y \ |
注意:
在打开“默认主机管理配置”后,您的实例可能需要最长 30 分钟才能使用所选角色的凭证。您必须在要自动管理 Amazon EC2 实例的每个区域中打开“默认主机管理配置”。
如不做其他调整,最多 30 分钟以后,你会在 System Manager -> Fleet Manager -> Managed nodes 下看到你的 EC2 了
1 | # 我的本地环境是 Macbook Air (m1), |
1 | aws --profile test \ |
1 | aws --profile test \ |
然后就可以愉快的在本地连数据库了:
1 | mysql -h 127.0.0.1 -P 5555 -U admin -p |
原本有一个 Client VPN endpoint 在 AWS 新加坡。有几个原因导致要迁移:
由于 Amazon Linux 2023 里没有 OpenVPN 的包,也考察过 Fedora 36 的包,但思来想去,还是源代码编译安装吧,所以 OpenVPN 最后还是源代码编译安装的。
登录 EC2 后,开始操作:
1 | wget https://swupdate.openvpn.org/community/releases/openvpn-2.6.6.tar.gz |
还是在 EC2 上,/usr/local/openvpn/etc
目录下
1 | sudo vim /usr/local/openvpn/etc/server.conf |
有几个地方需要改:
cipher AES-256-GCM
dh none
user nobody
group nobody
proto tcp
explicit-exit-notify 0
cert /usr/local/openvpn/etc/server.crt
key /usr/local/openvpn/etc/server.key
ca /usr/local/openvpn/etc/ca.crt
push "route 172.16.0.0 255.240.0.0"
EC2 上
1 | echo "net.ipv4.ip_forward = 1" > /etc/sysctl.d/10-OpenVPN.conf |
EC2 上
1 | sudo /usr/local/openvpn/sbin/openvpn \ |
所有做包转发的 EC2,都需要强制关掉 AWS 官方的 source/destination check。方法是:
Actions
->Networking
->change source/destination check
,然后点“stop”
至此,VPN 从 AWS 的 Client VPN endpoint
已经迁移到我们自己的 EC2 上了,以前的客户端,只需要改下 remote 那一行的服务器地址为 EC2 的公网地址,以及将 proto 改成 tcp(Client VPN endpoint 缺省是 udp,而且不能改)即可继续使用,连新的 VPN 服务器。
乐宝幼儿园的时候上过一段时间的 Scratch 的课,他对这个表现出了浓厚的兴趣,于是我就给他买了基本相关的书籍,他也爱不释手。由于领导注意到乐宝对电子产品的痴迷,怕他迷失,所以规定他周末才能玩儿半小时的 Scratch。我发现他在用 Scratch 做一点小程序(照着书吧),而且还乐此不疲。正好我也有时间,所以我想琢磨下怎么做个游戏,然后再教乐乐(编写)。
真的是这样吗?哈哈,真的起源原因真不是这样的,而是因为乐乐手头有一个我二十多年前买的 Handspring 的 Visor,就是这一款:Handspring Visor Deluxe PDA@ifixit,乐乐也很喜欢,但我网上找了找,几乎已经没有任何应用了,连中文支持:CJK,貌似都没法用了。于是我想能不能自己写点简单的小程序,port 上去。于是就有了写个小游戏:2048 的想法。
这才是最初的需求,至于改用 Scratch 来弄,那是后来的想法。
后来一搜,Scratch 官网就有一大堆的 2048 游戏程序例程(当然是别人分享出来的),我看了好多,都觉得有点复杂。而且油管上也有人录视频专门讲怎样编写 2048 这个游戏。本来想哪天翻译下来,再录个视频(又给自己挖了个坑:)。然后在中文世界里翻一翻,发现 B 站也有详细讲解的中文的视频。具体链接在这里:B 站用 Scratch 编写 2048 游戏的教学视频 然后我的这个 2048 程序也是完全按照这个视频做(抄)下来的。
所以,这里说起来过程,其实就是一个字:抄。:)
言归正传。这个视频里其实还是有一些小坑的。大家从头看到尾了就会知道。有些的,是前面挖,但是后面自己填了,但是有一些是没填的。我这里就提一下没填的。其实主要就是一个:变量 clone?
的问题。
这个变量我理解应该是标识角色是否是克隆体的。由于作者的疏忽,视频里作者点击“新建一个变量”,然后输入变量名“clond?”,保持缺省选项:“所有角色可见”的前提下点击“OK”,结果发现系统已有这个变量。这是个容易忽视的小细节。在我的系统里(Scratch 3.29)里,照作者的方式是能新建这个变量:clone?
的,就算系统已存在叫“clone?”的变量。
然后一直到最后,我都发现有一个小问题:就是我的程序跑起来,会在 4x4 方格的右下方,显示一个方框角色,怎么都弄不掉。仔细再看了看程序代码,发现这个方块是方块角色做完 16 次克隆自己的操作以后移动到的位置。但是按照程序里处理广播消息:show 的积木块的代码来讲,母体角色是应该不显示的呀。再仔细看看处理广播消息:show 的程序,发现这个逻辑有问题:
这段程序是在 clone? = 1
的前提下才执行的(这个思路貌似很清晰:只有克隆块才执行),但问题是启动时变量 clone?
被赋值为 0,但是在“当作为克隆体启动时执行”的代码块里,又将 clone?
设置成了 1。问题来了,clone?
是个全局变量,克隆体里将其设置为 1 了,那么母体角色也能读到,所以每次做 show 操作时,母体角色执行时也会是 clone? = 1
成立,所以母体角色也被显示了出来。:(
当然,也有其他办法来修复这个 bug,但我又翻了翻 Scratch 关于变量的资料,发现其实这里只要将 clone?
设置为本角色可见就行了。因为在母体角色里,clone?
是为 0 的(系统启动时设置的)。克隆以后,克隆体继承了这个私有变量(本角色可见的变量),然后又在“作为克隆体启动时”的代码块里将其(clone?
)设置成了 1,但是母体角色里 clone?
还是 0!!!!!这样母体角色在执行处理 show 消息的代码块时,判断 clone? = 1
不成立,所以不会被显示。问题被解决。
这里贴一张改好后我自己玩儿 2048 时的截图
然后,最最后,我把代码贴出来,有兴趣的可以用来教小朋友哟。哈哈
]]>上一任租户有个可能运营商送的监控,有个摄像头,反正没用了,我就拆下来看看,发现里面有个 TF 卡,标着 256G 容量。就是如下这货:
插到电脑里,发现只能看到 134G 的容量,DiskUtil 里也是,如下图:
MacOS 下,执行:
1 | sudo diskutil eraseDisk xxx xxxx xxxx xxxx |
大致意思就是使用 MacOS 下的命令 diskutil 及相关参数 eraseDisk 来做。
注意:diskutil 的图形模式不具有这些功能!
这回,终于能认出来 268G 的容量了,如下图所示:
于是,插上电脑(HP Chromebook 11a G6 EE,关于这台机器,可以看文章:[How to Install Xubuntu on a Chromebook](“/2022/11/How to Install Xubuntu on a Chromebook/“))开始安装 Linux,结果发现老失败,说是 TF 卡那个分区失败。于是开始怀疑卡(标称容量)有问题,网上搜了些相关资料,然后在电脑上下载了个叫 f3 的程序,用其工具 f3probe
来测了一下,结果是:30G!测出来真实的容量只有 30G!
然后根据建议用 f3fix
命令修复了下,想把正确的容量大小写回去,结果发现……跟我想要的结果不一样。再次考虑到 f3 是一个八年前的项目了,我又找了台 windows 机器,装了一个 DiskGenius,想再确认一下容量。
这一回,DiskGenius 只认出 26G 的容量!!!最后我赶紧分区、格式化,然后插回到监控摄像头里,这种容量造假的 TF 卡,我可不敢用来跑系统。说不定速度也是造假的呢。
]]>鱼总毕业了,带回来一台 Chromebook(HP Chromebook 11A G6 EE),说是毕业了,学校就把学生用的电脑送给学生了。
鱼总说这电脑配置挺渣的,但续航还行,ebay 上还能卖个二三十刀,让我看着办。
我还能怎么办?!凉拌呗。当下失业在家,没有收入,当然有垃圾必捡,且用且珍惜啦。
于是,折腾走起。鉴于国内使用 ChromeOS 的种种不便,决定还是装一套 Linux 跑着吧。本来,ChromeOS 就直接支持 Linux(打开开发者模式就会有个简单的 Linux 可用),而且还能通过几种工具(如 Crouton 和 Crostini 或 chrx )安装 Linux,但我觉得还是要装一个“干净”的 Linux 更好一些。
在 Chromebook 上打开开发者模式(Developer Mode),方法很简单。
创建一个 Linux distribution 的安装 U 盘。
因为下一步刷写新的 firmware 需要关闭 write protection。所以这一步我们需要提前做。根据 Chromebook 的型号不一样,关闭 WP 的方法各异,具体请查阅:https://mrchromebox.tech/#devices,找到你的 Chromebook 的型号,看看其的 WP Method 是哪种情况,我的 HP Chromebook 11A G6 EE 是“battery”,意思是可以通过摘掉电池(battery)的方法来临时禁掉 firmware write-protect。
这里禁掉 WP 的方法很多,有的是拧下一颗螺钉……
于是我们先拆机,具体可以参考油管上的一个视频:HP Chromebook 11 G6 EE Battery Replacement@youtube,或者是拆机图:HP Chromebook 11 G6 EE Battery Replacement@ifixit,先把盖子拆了。
看到电池以后,把电池和主板连接的那个接头小心的拔出即可。
刷一个 UEFI 的 BIOS 的 firmware,这里用的是 mrchromebox 改过的 coreboot
shell
,回车cd; curl -LO mrchromebox.tech/firmware-util.sh && sudo bash firmware-util.sh
上面的过程有几个需要注意的地方:
这里终于要用到前面做的 USB 启动盘了。
这个事情的需求,其实……就是闲得。
开个玩笑。我其实之前用 Tasker 这个 APP 做过类似的事情,见之前文章:分享一些自己DIY的task的profile,但是有一阵遇到了 android 手机的壁纸 bug,我的 pixel 给干挂了两回,其中有一回甚至给重制了才救回来,救回来之后就没起过自动更换壁纸的任务了。
这次是看到 V 站上有个大佬,展示自己极少的 APP 时,截图里展示了一个桌面,上面的壁纸上有格言,还有英文单词。于是我就自然而然的想要不要把毒鸡汤也写到壁纸上呢?:)
我这里环境(Termux 和 Termux-API)是现成的,但如果没有需要安装的话,请记住,不要装 google play 上的 Termux 和 Termux-API,而是要装 F-Droid 这个市场上的 Termux 和 Termux-API!
注意:要给 Termux 足够的权限(也许 Termux-API 也需要):
最后,还要打开 Termux,输入:
1 | apt install termux-api; |
打开 Termux,继续输入:
1 | apt install ImageMagick; |
毒鸡汤 也是我自己 fork 了某个大佬的代码,自己搭建的服务。本身没提供 API 服务,这里也没想再开发一个 API 接口,所以直接模拟 web 访问,然后把需要的数据抓出来即可。不过我们还需要手工折行。
我自己有个壁纸服务:壁纸,会定时更新输出的壁纸,后台爬虫是用 go 实现的。
这里我就直接用了自己的这个壁纸服务,定时(每小时)去抓一个壁纸回来。接着做如下处理:
最后自然是把上一步保留的文件用 termux-wallpaper 命令(来自于软件包 Termux-API)设置成新壁纸。
把上面的流程写成代码(假设存为文件 $HOME/bin/change_wallpaper.sh),再用 termux-job-scheduler(来自于软件包 Termux-API)将这个代码设置为定时运行。我的例子里我是这样用的。打开 Termux,输入命令:
1 | termux-job-scheduler \ |
在图片上写中文(含全角标点)时需要用中文的字体,因为普通字体里没有中文字符呀!
所以,要在所有可用字体里选出有中文字符且全角标点位置不在中间的,其实还有个想法,就是想找一个酷一点的中文字体,我把所有可用字体做了个循环,测试写中文字符以及全角标点,结果保存到文件里,代码大概如下:
1 | for i in $(\ |
我先在我的 Mac 里跑的,找到一堆合适的字体以后,再去找 Termux 里 magick -list font | grep "Fonts:" | awk '{print $2}'
的结果来做对比,结果发现,匹配上的只有一种字体:Noto-Serif-CJK-SC。:(
当然,也可以再单独在 Termux 里安装新的好看的可用字体。但我没这么做,看以后需求吧。
其实最早这个方案我是打算用 crond 来做定时任务的,软件都安装设置好了。
打开 Termux,
1 | apt install cronie termux-services; |
关闭并重新打开 Termux
1 | sv-enable crond; |
但是发现用 crond 跑其他任务都没问题,但是跑 termux-API 里的命令总会报 Selinux 的错误!实在是搞不定啊,于是才转向 termux-job-scheduler 方案。
其实刚用 termux-job-scheduler 时日志里也出跟 crond 一样的信息,当时心就哇凉了,但没想到后来自己居然就好了?!:)
ImageMagick 软件包里的命令:convert 有个参数:*-crop*,功能是用来从图片上截取一部分,这个参数还需要提供 x、y 两个参数,这两个可以理解为横坐标(x)和纵坐标(y),这个时候学过一点点编程基础的小可爱们是不是自然而然都会以为 -crop 参数(其实是操作参数,可以理解为命令)截取的长方形图片是以这个横坐标 x、纵坐标y 为顶点的呢?
我一开始也是这么认为的,所以当我用 -gravity Center 将坐标零点设置为图片中心之后,我将参数 x 和 y 分别设置成了 -540 和 -1200,结果就悲催了,最后经过调试,才知道当有 -gravity Center 时,x 和 y 是指截取长方形的中心的坐标!!!!
所以,这里的 x 和 y 都应该是 0 才对!!
最后,show you the code:
1 |
|
最后,附壁纸截图一张:
]]>如今公有云用的越来越多,各个区域、不同可用区,还有各种特殊服务,再加上也许还有自建 IDC,还有办公网内网。我的传统是会将这些内网打通的。所以,各个节点网络的 IP 地址分配策略(方案)就成了一个绕不开的话题。
我常用的一些 VPC 创建管理策略:
这里指的是在 RFC 1918 里定义的“私有地址空间(Private Address Space)”,各大公有云厂商允许分配给 VPC 的 IP 地址只能是这其中的。
以最简单的 VPC 配置四个 C 段地址为例(我常用是一个 VPC 两个 C 段),假设其是 10.0.0.0/22(也就是 10.0.0.0/24、10.0.1.0/24、10.0.2.0/24 和 10.0.3.0/24 四个 C 段),那么:
找三个可用区,
可以看出这个 VPC 还剩一段 IP:10.0.3.192/26,这一段就留作冗余。
注意:
本方案并没有考虑 IPv6 的情况,以后有机会更新的时候,会把 IPv6 的支持考虑进去。
]]>这个问题我觉得中小公司有需求,但是大公司应该没这个需求,大公司肯定都找第三方直接 MPLS 之类的商业全套解决方案了。但是对于缺钱的中小企业,我觉得还是有借鉴意义的。
这篇文章本来是要讲“中小企业维护海外服务器的 VPN 方案”的,但讲着讲着,发现大部分内容,都是讲的“内网打通”。:(
这个方案准确讲是来自我在某个前司(前司比较多:)的一段工作经历,他们业务跑在海外公有云(AWS)上,技术团队在国内,连服务器需要先拨 VPN,直接拨经常断,所以我就折腾了这么一个方案出来,我在那里的一年多时间,完全没有出过问题。
正所谓:一图胜千文。所以,请看图:
注意:这里为了脱敏,我把一些真正的公网 IP 地址和公司产品的名字以及一些我认为是隐私的信息隐去了。
另外,上图其实可以和我的另外一篇文章:怎样在 checkpoint 设备和 AWS 北京的 EC2 之间搭建 IPsec 隧道 结合起来看。
所以,这个图其实是个“内网打通”的示意图。
各大公有云厂商,都有成熟的产品来处理内部的各个 VPC 之间的内网互通,比如如上图所示,aws 的相关产品,就叫 “transit gateway”,阿里云也有类似的产品,好像叫“云企业网”还是什么别的。Azure 和 GCP 就不太了解,但肯定有类似产品。
所以,这个问题的答案就是:
答案其实跟海外的一样:
当然,这里也有例外,比如上图所示:北京 office 和 AWS 北京节点之间,就是用 IPSec 而不是 WireGuard 打通的(具体怎么打通,前面有提到的一篇文章中有详细记载)。为什么这样呢?那主要是因为公司给北京办公室配置了设备呀,checkpoint 的防火墙!这货不支持 WireGuard。故而只能在 AWS 北京节点起台 ec2,装个 IPSec 服务,然后两者打通。
这个方案就是路由表的维护需要仔细又仔细。其实并不难,主要是复杂,需要细心,维护时尽量对着图来做,配完多做测试。
前面有提到这个方案也可以用做 VPN 优化的。首先我们看看优化之前我们的 VPN 架构是怎么样的。
之前,VPN server 都是在海外的公有云节点上,国内连一个是慢,而最重要的是不稳定,非常容易被封。
而(内网打通)之后,我的 VPN 方案我推荐其主要接入点放在国内同一家厂商据用户最近的接入点(如上图例就是 aws 北京接入点,再准确点就是 IPSec 那台 EC2),然后再在海外每个节点保留一个冗余接入点即可。注意:这些 VPN 接入点的认证都是统一的。
这样一来从(VPN)主接入点来说,用户从国内(大概率是从北京)连过来,不容易被干扰,大概率不会被封,而同一厂商国内节点到海外节点之间数据链路也会比较稳定通畅,也不容易被干扰、被封。所以,整条链路不一定有多快,但肯定是要稳定的多得多得多。
想想如果新加入一个节点,会需要做哪些操作。
通常,我们会把新的节点和已有的所有节点直连,当然,跨境的节点之间例外。而做 WireGuard 点对点配置,加一个对端点,需要改整个的配置,所以,理论上在一个点上改 WireGuard 配置时,上面的所有 WireGuard 链接都会受影响(因为大致需要重启 WireGuard 服务)。
还有一个,就是路由选择的可能的坑,比如节点 A、B 和 C 之间,两两互通,那么从 A 到 C,路由 A->C 和 A->B->C 都是可以的,而且一般情况下自然是直连也就是 A->C 更好,所以我们这里的方案也是 A->C。说了“一般情况”,那么肯定就还有“例外”吧,对的,像国内家庭宽带到海外节点之间,就是典型的例外情况,这种情况下直连远不如走国内的厂商中转一下。那么,像我们这样把这种例外情况下就不做直连,路由也直接走中转不就得了?这也不是绝对的,事情是变化的,也许这一时刻这条路由更优,下一时刻又是另外一条路由更优。:- 对啦,我想说的就是,远期有时间的时候,可以考虑下把路由扔给 OSPF 来管理,这样逼格完全就不一是一个层次了!:)
其实其实,说到“内网互联的方案”的我最最理想的情况,还是类似于自建 zerotier 的方案。自己搭建PLANT,然后每个节点找台网关机器接入自己的 zerotier 网络,这就完了,所有节点也就互通了。而且路由当能直通的时候,节点之间是直通的,当节点之间不能互通的时候,可以通过 PLANT 来互通。这才是内网互通的最优雅解决方案。下回有空谢谢这个。不过最好还是得哪个贵司给我个机会让我实践一下。:O
]]>为了把从美国带回来的在家吃灰了几个月的 Google 智能音箱(Google Nest Mini)用起来。而之前由于家里都是终端设备自己搞定科学上网的需求,家里并没有全局的科学上网方案。但这一次由于要用 Google Nest Mini,则必须要搞个设备,搭科学上网环境了。
家里还有个吃灰几年的极路由三(HiWiFi HC5861),用的是联发科的架构(MediaTek MT7620A),这一次打算将其用起来,作为科学上网的设备。
于是将其刷上最新的 OpenWRT。具体过程就不说了。
然后因为我所有的设备,但凡支持,都会起 zerotier,于是这太极三也装上了 zerotier,并加入我的网络(跟我的 vps 以及其他设备在同一个虚拟的 zerotier 网段)
因为设备连接 WiFi 时大都会允许设置一个 proxy,所以,在最初的方案里,我是想让这台极三充当一个 socks proxy 的角色,当需要科学上网的设备(这里就是 Google Nest Mini)通过 WiFi 接入家庭网络的时候,将 proxy 指过来,这样实现设备的科学上网。
这个方案也简单,只需要在极三上起一个 V2Ray 服务,这个服务的入站(inbound)只需要开一个整个局域网共享的 socks proxy 的支持就可以了,出站(outbound)当然是对接海外 vps 上的 V2Ray 服务。
最后,这个方案的环境弄好了,结果配 Google Nest Mini 的时候发现无法让其使用 socks proxy,故而最后这个方案没有用起来。
这个方案是想设备(Google Nest Mini)用 WiFi 来连科学上网设备极三,然后在极三上用 iptables 把所有流量转发到海外 vps 的 zerotier 那个网卡所在的 IP 地址的 socks proxy 端口(V2Ray 服务支持)上。
这个方案的问题在于我极三的 WiFi 我用来连家里的 WiFi 了,再要起一个 sid 接受 WiFi 连接呢,配置起来比较麻烦,而且,可能会影响家里原来 WiFi 的信号(因为 WiFi 会互相干扰)。
最后,这个方案虽然也没被放弃,但是极三上的 zerotier 却是配好了。
这是最终实施并生效的方案。
大致情况如下:
这其实是个难点。极三上能装软件的空间只有 10M,结果直接 opkg install v2ray-core
出来的可执行文件 v2ray 直接有 20+M,显然不能直接装。幸好有大佬把 v2ray-core port 到了 OpenWRT 上[^1],他编了个 v2ray-core-mini 勉强可用。具体在极三上:
1 | cd /tmp |
然后还要一些数据(因为 v2ray-core-mini 包里不含 geoip.dat 和 geosite.dat 等数据文件,这些文件太大了),我们这里手工下载了一个 geosite.dat,这个就够了,那个 geoip.dat 有二十多兆,太大了。
1 | cd /usr/bin |
最好还装上 V2Ray 服务的 luci 包,这样就可以在 web 上直接配置了。注意:有个叫 luci-i18n-v2ray-zh-cn 的中文语言包我没装,主要是为了节省空间,这个也不是必须的。
1 | cd /tmp |
极三可以用 wan 口去接主路由的 lan 口,但我这里是用的 WiFi 去连的主路由的 WiFi,这种方式使极三上的网。后面的 dhcp 配置里会有所体现。
弄清楚逻辑以后配置部分也没啥可讲的。就是:
注意:
主路由也是 OpenWRT,主要是修改其 DHCP 配置,
1 | cat >> /etc/config/dhcp << EOF |
注意:
[^1]:V2Ray for OpenWrt
]]>最近发现 ssh 到自己的路由器,发现连不上,报错:
Unable to negotiate with 10.0.0.1 port 22: no matching host key type found. Their offer: ssh-rsa
NOTE: 上面的 “10.0.0.1” 是服务器的 IP 地址
网上查了下,发现是 OpenSSH 新版本的锅。OpenSSH 8.8 开始,缺省不再支持使用 SHA-1 hash 算法的 RSA 签名。
其实这个变动对稍稍新一点的 OpenSSH 服务器(据说 7.2 及以后版本)没有问题,因为其除了 SHA-1 外,还支持 SHA-256、SHA-512 等更强壮的算法。ssh-rsa 的密钥会自动使用更强壮的 hash 算法了。
但是对一些较老的 OpenSSH 服务器(7.2 以前版本),则就有问题了,因为其对 ssh-rsa 只支持 SHA-1 一种 hash 算法。但此时客户端又不支持这种算法,故而连接会失败。系统上面的错误。
ssh 连接有问题的服务器时,加上两个参数即可。如:
1 | ssh \ |
ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/pk4ym_ed25519 -C "m@theyan.gs"
乐乐的倾听者的音频资源又需要更新了,于是跟我提了几个需求,让我去“下”(下载)某个著名儿童频道主播播讲的节目(有故事还有其他)。
这个主播有官网,但是官网上没有资源,只有 app 和公众号(可能还有在喜马拉雅的)的二维码。
但是发现了其还是有一个移动版的“官网”(域名是 m. 开头的),这个网站跟官网貌似没有同步更新,上面还能直接听节目。
大致看了下页面源代码,很快就扒出了音频资源的下载链接,在命令行用 wget 抓了一下,居然也没有反盗链,实在是良心!
先要准备环境(我是在 MacOS,所以用了 Homebrew)
1 | # Command Line Tools (CLT) for Xcode |
下面开始抓取并声称下载资源的命令行。
1 | curl "https://m.xxx.xxx/api/media/audiolist.ashx?mid=7268&aid=516&mids=" -o audiolist_qianer_history.json |
1 | curl -s "https://m.xxx.xxx/api/media/audiolist.ashx?aid=486" | \ |
1 | curl -s "https://m.xxx.xxx/api/media/audiolist.ashx?aid=250" | \ |
1 | curl -s "https://m.xxx.xxx/api/media/audiolist.ashx?aid=477" | \ |
1 | curl -s "https://m.xxx.xxx/api/media/audiolist.ashx?aid=8" | \ |
1 | curl -s "https://m.xxx.xxx/api/media/audiolist.ashx?aid=360" | \ |
1 | curl -s "https://m.xxx.xxx/api/media/audiolist.ashx?aid=485" | \ |
最后记得把命令输出的命令行代码拷贝出来,再粘贴出来执行一下。资源就会都下载到当前目录下了。
需要这些资源又不想自己下载的可以找我。
]]>无非就是“又”失业了,重新开始找工作,原本还不想招惹外包公司,无奈行情不好,外包工作也是工作呀,于是乎,就定了某个外包公司的面试,第一面:外包公司的技术面。
主要问题都是跟 aws 有关系,这个岗位的甲方是个外企,肯定重度使用 aws。而且还在用 aws 的 eks 服务。
感觉面试官的视野还是很重要的。
有个细节:腾讯会议面试,面试官几个人,可能是三个,首先特意让我把视频打开,于是我打开了,但是对方并没有打开。好吧,我是求职者,不对等也正常。
但为什么面试需要让面试者打开视频呢?这个不太明白,也许相关 HR 会比较清楚这一点。
问我 eks 里的服务通过 ingress 暴露出去,然后数据包是怎么从外网到 pod 的。
这个题我答的不好,前东家其实差不多就是这个架构:nginx-ingress,然后外面是 aws 的 LB,我一直在解释外网流量到 aws 的 LB 设备之后然后是转到 eks 集群的 node 节点的某个 tcp 端口,我的意思是,其实服务最终是通过 nodeport 透出去的。
上面我说的这个大概是基本上没太大问题的,但是人家问的应该不是这个。:(
其实上面我提到的 nodeport 透出去的服务正是 nginx-ingress(或者是 nginx-ingress-controller,具体忘了,我得再看看 nginx-ingress)
这个其实我比较熟悉,http 基本协议嘛。
我说这个简单,在反代的 nginx 配置里将 client ip 直接写入一个特定的 http 头,然后真实的服务里再把这个头取出来即可。
其实这个回答完全没毛病,我之前有项目就是这么干的。但面试官却感觉好像抓住了什么一样拼命问我到底是哪个 http 头?搞得我都有点上头了,我于是说:“哪个头不一样吗,只要跟后端协商好了就行了”。还被追问,还问一般标准是哪个头,于是我只能说 X-Forwarded-For,于是面试官认可了。
我其实没有细说为什么要另外弄一个头,这是因为客户端访问服务,中间可能会过 n 层代理,理论上每一层都会且必须要往 X-Forwarded-For 里写东西,但实际上,守规矩的人有,但绝对不是全部!于是我们的逻辑就是单独再搞一个 http 头,算是有点私有协议的意思,自己用,这样感觉比直接用 X-Forwarded-For 更靠谱一些。
某个面试官问的,我当时回答:我不知道。我真不知道,或者我们曾经也有用过这种功能,但因为具体不是我配的,我就没了解到。但我知道,这个是绝度可以实现的,大致猜想是通过 webhook 之类的东西来做就可以。
我又说,我们有时并没有用 Jenkins,面试官就逼问:“没有 Jenkins 怎么做 CI/CD 呢?”,我当时就笑了,说:“我的好几个前司,项目的 CI/CD 是直接在 gitlab 里做的。”(他可能不太清楚 gitlab 本身就有 CI/CD 的功能)。而我恰恰由于要维护这个,曾经大概看过相关配置。
估计他也不知道 github-action 之类的东西吧。
我回答说之前的某司,我用过 aws 上的什么服务来着(我真是这么说的,我忘了那个叫 Lambda 了),用那个写了个 python 程序,定时执行一些操作。那个我理解就是 serverless
于是我就说了一堆,但的确好多服务我忘了名字了,我只能简单介绍下这个服务是干啥的。我估计我用的好多服务面试官们也没用过,:)。这个很正常,就像他们用过的服务有些我也没用过一样。
我居然只回答出 nodeport 和 ingress 两种,连 LB 设备这个都忘了。:(
最终的结果,自然是挂了呀。:(
]]>最近在美丽国矿场帮忙,顺便修下矿机。
本来心里有些想法,需要有设备(计算设备、网络设备)来实现,无奈手头没有资源。后来修神马矿机的时候发现其系统是基于 OpenWRT 的!于是就想如果能拿到 root 权限的话,是不是就能利用现有系统来做很多事情了?于是就开始研究怎么 root 其控制板(其实还有其他难点,比如控制板怎么取电?还要给控制板找一个盒子)。
前同事、硬件玩儿家、大佬陈总给了我一个关键性信息:用 ttl 连接控制板可以直接获得 root 权限!
然后我就开始找设备,正好同事为了维修,早就采购的有 ch341a 编程器,于是我又让其帮忙采购了一包杜邦线就 OK 了。
这里其实没有什么太多的技巧,就是用杜邦线把 ch341a 的几个 pin 脚接到神马矿机控制板的几个 pin 脚上,再把 ch341a 的 usb 头插进电脑,最后再用模拟终端软件打开,如果没有问题,则会直接进 root 环境。
连接方法也简单:
注意:这里没有用杜邦线(因为当时杜邦线还没采购回来,所以用的是风扇的电源线),但这个图能清楚显示出接的是控制板上的哪几个 pin 脚
注意:这图里也没有用杜邦线
我在 MacOS 未成功,最后用的是 Windows + Putty 配置成功了,连接的端口看下“设备管理器”,连接的其他配置参数为:115200,8,无,1,无
这个不是所有版本的控制板都可行的。猜想应该是早期工程师用来调试用的,后来把这个关掉了。据我测试的版本来说: