Tekton 与 Kaniko:云原生 CI/CD 构建实践

Tekton 什么是 Tekton Tekton(发音:/ˈtɛktɒn/,“TEK-ton”)名称来自希腊语 τέκτων,意为"建造者"。 Tekton 是一个开源的云原生 CI/CD 框架,运行在 Kubernetes 上,通过 CRD(自定义资源定义)的方式定义流水线。它是强制 Kubernetes 原生的,所有流水线组件都以 Pod 方式运行,没有其他执行模式。 与 Jenkins、GitLab CI 等工具不同,Tekton 从设计之初就只能运行在 Kubernetes 上,而不是"可选支持 K8s"。这是架构层面的硬性约束,带来的好处是与 K8s 生态深度集成,代价是强依赖 K8s 环境。 Tekton 是 CD Foundation 旗下项目,前身是 Knative 的 Build 模块。 核心概念 Step(步骤) 流水线中的最小执行单元,对应容器中的一条命令。 Task(任务) 由一组有序的 Step 组成,运行在同一个 Pod 中,Steps 共享存储卷。 apiVersion: tekton.dev/v1 kind: Task metadata: name: build-and-push spec: params: - name: image type: string steps: - name: build image: gcr.io/kaniko-project/executor:latest args: - "--dockerfile=$(workspaces.source.path)/Dockerfile" - "--context=$(workspaces.source.path)" - "--destination=$(params.image)" workspaces: - name: source Pipeline(流水线) 由多个 Task 按顺序或并行组成,定义完整的 CI/CD 工作流。 ...

2026-03-25 · 3 min · 551 words · -

pnpm basic, npm basic

pnpm - 高效的 Node.js 包管理器 pnpm 简介 pnpm (performant npm) 是一个快速、节省磁盘空间的 JavaScript 包管理器,作为 npm 和 yarn 的替代方案。它通过创建硬链接和符号链接的方式来共享依赖,避免重复安装相同的包。 核心特点 节省磁盘空间 所有版本的依赖都存储在硬盘上的单一位置(全局存储目录) 当安装包时,文件会从全局存储硬链接到项目的 node_modules 如果你有 100 个项目使用相同版本的某个依赖,磁盘上只会有这个依赖的一份文件 极快的安装速度 由于使用硬链接,安装过程比 npm 和 yarn 都快 多个项目共享依赖时,速度优势更加明显 严格的依赖解析算法避免了冗余操作 创建非扁平化的 node_modules 使用符号链接创建依赖的嵌套结构 只有 package.json 中声明的依赖才能访问 避免了"幽灵依赖"(phantom dependencies)问题 严格的依赖管理 防止访问未声明的依赖 确保项目的可重现性和安全性 pnpm 工作原理 全局存储 (~/.pnpm-store/) ├── package-a@1.0.0 ├── package-b@2.0.0 └── package-c@3.0.0 ↓ (硬链接) 项目 node_modules/ └── .pnpm/ └── package-a@1.0.0/ └── node_modules/ └── package-a (实际内容) ↓ (符号链接) └── package-a → .pnpm/package-a@1.0.0/node_modules/package-a 与 npm/yarn 的对比 特性 pnpm npm yarn 磁盘空间效率 ⭐⭐⭐⭐⭐ ⭐⭐ ⭐⭐ 安装速度 ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐ 依赖隔离 ⭐⭐⭐⭐⭐ ⭐⭐ ⭐⭐ Monorepo 支持 ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐ 严格性 ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ pnpm 安装 全局安装 pnpm # 使用 npm 安装 npm install -g pnpm # 使用 Homebrew (macOS/Linux) brew install pnpm # 使用独立脚本安装 curl -fsSL https://get.pnpm.io/install.sh | sh - # Windows (PowerShell) iwr https://get.pnpm.io/install.ps1 -useb | iex 查看版本 pnpm --version pnpm -v pnpm 基本命令 安装依赖 # 安装 package.json 中的所有依赖 pnpm install pnpm i # 安装指定包 pnpm add <package> pnpm add lodash # 安装指定版本 pnpm add lodash@4.17.21 # 安装到 devDependencies pnpm add -D <package> pnpm add --save-dev jest # 全局安装 pnpm add -g <package> pnpm add -g typescript # 安装指定 workspace 包 pnpm add <package> --filter <workspace> 更新依赖 # 更新所有依赖 pnpm update pnpm up # 更新指定包 pnpm update lodash pnpm up lodash # 更新到最新版本(忽略 package.json 中的版本范围) pnpm update --latest pnpm up -L # 交互式更新 pnpm update -i 删除依赖 # 删除指定包 pnpm remove <package> pnpm rm lodash # 删除全局包 pnpm remove -g <package> 查看依赖 # 列出所有依赖 pnpm list pnpm ls # 列出指定包的依赖树 pnpm list <package> # 查看过期的包 pnpm outdated # 查看包信息 pnpm view lodash pnpm info lodash 运行脚本 # 运行 package.json 中定义的脚本 pnpm run <script> pnpm run build pnpm run test # 简写(对于常用命令) pnpm start pnpm test pnpm t 清理缓存 # 清理未被引用的包 pnpm store prune # 查看 store 状态 pnpm store status # 查看 store 路径 pnpm store path 安全审计 # 检查依赖包的安全漏洞(对应 npm audit) pnpm audit # 自动修复漏洞(对应 npm audit fix) pnpm audit --fix # 仅生产环境依赖审计 pnpm audit --prod # 输出 JSON 格式 pnpm audit --json # 审计并显示详细信息 pnpm audit --audit-level=<severity> # severity 可选值: low, moderate, high, critical pnpm audit 与 npm audit 的差异: ...

2026-03-24 · 10 min · 1972 words · -

Exception Handling

异常捕捉的确是对性能有影响的,那是因为一旦异常被抛出,函数也就跟着 return 了。而程序在执行时需要处理 函数栈 的上下文,这会导致性能变得很慢,尤其是线程栈比较深的时候。但从另一方面来说,异常的抛出基本上表明程序的错误。程序在绝大多数情况下,应该是在没有异常的情况下运行的, 所以,有异常的情况应该是少数的情况,不会影响正常处理的性能问题。 对于我们并不期望会发生的事,我们可以使用异常捕捉;对于我们觉得可能会发生的事,使用返回码。 https://time.geekbang.org/column/article/675 你觉得自己是一个Java专家吗?是否肯定自己 已经全面掌握了Java的异常处理机制?在下面这段代码中,你能够迅速找出异常处理的六个问题吗? 1 OutputStreamWriter out = … 2 java.sql.Connection conn = … 3 try { // ⑸ 4 Statement stat = conn.createStatement(); 5 ResultSet rs = stat.executeQuery( 6 “select uid, name from user”); 7 while (rs.next()) 8 { 9 out.println(“ID: " + rs.getString(“uid”) // ⑹ 10 “,姓名: " + rs.getString(“name”)); 11 } 12 conn.close(); // ⑶ 13 out.close(); 14 } 15 catch(Exception ex) // ⑵ 16 { 17 ex.printStackTrace(); //⑴,⑷ ...

2026-03-23 · 6 min · 1146 words · -

EAFP vs LBYL

两种处理错误/边界条件的编程风格,在 Python 社区尤为常见。 LBYL — Look Before You Leap(先检查再操作) 谚语来源: “Look Before You Leap” 字面意思是"跳跃之前,先看清脚下"。想象要跳过一条沟——不先看清落脚点就跳,可能会摔进坑里。引申为行动之前先确认条件是否安全,对应中文谚语"三思而后行"、“谋定而后动”。 在编程里,“leap”(跳跃)= 执行操作,“look”(看)= if 条件检查。 操作前先检查前提条件是否满足。 # LBYL 风格 if key in my_dict: value = my_dict[key] else: value = default if os.path.exists(filepath): with open(filepath) as f: data = f.read() 特点: 逻辑清晰,防御性强 存在 TOCTOU(Time-Of-Check-Time-Of-Use)竞态条件风险——检查和使用之间状态可能改变 代码中充满 if 判断,容易冗长 EAFP — Easier to Ask Forgiveness than Permission(先操作再处理异常) 短语来源: 这句话来自生活场景的比喻——想做某事时,与其事先去请示许可(可能被拒绝、很麻烦),不如直接去做,事后出了问题再道歉求谅解,因为道歉往往比请示更容易。 英文 字面意思 编程含义 Ask Permission 事先请求许可 用 if 检查条件是否满足 Ask Forgiveness 事后请求原谅 用 except 处理出错的异常 这个说法由 Python 之父 Guido van Rossum 推广,体现了 Python 的哲学:代码应该表达意图,而不是充满防御性检查。 ...

2026-03-23 · 1 min · 161 words · -

Backpressure, 背压

什么是背压 背压 (Backpressure, back-pressure), 又称负压。 Backpressure 并不是响应式编程 (Reactive Programming) 独有的概念, 也不是一种「机制」或「策略」。 Backpressure 是一种现象: 在数据流从上游生产者向下游消费者传输的过程中, 上游生产速度大于下游消费速度, 导致下游的 Buffer 溢出, 这种现象就叫做 Backpressure。 背压的本质 可以用水管来类比: 上游 = 水源 (生产者, Producer) 下游 = 水龙头 / 水桶 (消费者, Consumer) 管道 = 消息队列 / Buffer 当水源出水速度远远大于水桶的接收速度时, 管道中的水压就会升高。如果不加以控制, 水桶会溢出, 即数据丢失或系统崩溃。这个"升高的压力"就是背压。 背压出现的场景 背压广泛存在于各类系统中: 消息队列: 生产者发送消息的速率超过消费者消费速率, 队列积压 流式计算: Kafka、Flink 等处理管道中, 上游数据涌入速度超过下游处理能力 网络传输: TCP 协议中, 发送方速率超过接收方处理能力时, 接收窗口收缩 响应式编程: RxJava、Project Reactor 等框架需要显式处理背压 微服务调用链: 下游服务响应慢, 上游请求积压导致线程池耗尽 背压的处理策略 背压本身是现象, 应对背压才是策略。常见的应对方式有以下几种: 1. 控制生产速率 (Flow Control) 主动降低上游的生产速度, 使其与下游消费能力匹配。典型实现是 TCP 的滑动窗口机制: 接收方通过 ACK 报文中的窗口大小字段, 告知发送方当前可接收的数据量。 ...

2026-03-20 · 3 min · 439 words · -

PriorityQueue

概念 优先级队列(Priority Queue)是一种特殊的队列,队列中每个元素都附有一个"优先级"。出队时,不再遵循普通队列的 FIFO(先进先出)原则,而是优先级最高(或最低)的元素先出队。 直观类比:医院的急诊室——无论谁先到,病情最重的患者优先就诊。 核心特性 插入(insert / enqueue):将元素连同优先级一起加入队列 取最值(peek):查看优先级最高的元素,不移除 取出最值(poll / dequeue):取出并移除优先级最高的元素 不保证全局有序:内部结构只保证堆顶(最值)正确,其余元素顺序不确定 内部实现:二叉堆 绝大多数语言的标准库都用**二叉堆(Binary Heap)**实现优先级队列。 堆的结构 用完全二叉树表示,通常以数组存储 最小堆(Min-Heap):父节点 ≤ 子节点,根为最小值 最大堆(Max-Heap):父节点 ≥ 子节点,根为最大值 数组索引关系(从 0 开始): 节点 索引 父节点 (i-1) / 2 左子节点 2*i + 1 右子节点 2*i + 2 核心操作:上浮与下沉 上浮(Sift Up):插入新元素时,将其放在数组末尾,然后与父节点比较,不满足堆性质则交换,直到满足为止。 下沉(Sift Down):取出堆顶后,将末尾元素移到堆顶,然后与子节点比较,不满足堆性质则与较小(或较大)的子节点交换,直到满足为止。 时间复杂度 操作 时间复杂度 插入 $O(\log n)$ 取出最值 $O(\log n)$ 查看最值 $O(1)$ 建堆(heapify) $O(n)$ 两种变体 最小优先级队列(Min Priority Queue) 优先级数值最小的元素最先出队。例如:Dijkstra 最短路径算法中,每次选取距离最小的节点。 最大优先级队列(Max Priority Queue) 优先级数值最大的元素最先出队。例如:任务调度中,优先执行优先级最高的任务。 ...

2026-03-20 · 1 min · 125 words · -

Git basic commands, git 常用命令

Git basic commands 目前比较流行的版本管理系统 相比同类软件,Git有很多优点。其中很显著的一点,就是版本的分支 (branch) 和合并 (merge) 十分方便。 有些传统的版本管理软件,分支操作实际上会生成一份现有代码的物理拷贝,而Git只生成一个指向当前版本 (又称"快照") 的指针,因此非常快捷易用。 commands git status --porcelain #用于以简洁、脚本友好的格式显示 Git 仓库当前的状态,方便自动化处理和快速查看文件的变动情况。 git ls-files --unmerged git diff --name-only --diff-filter=U #显示出 HEAD 对应的提交的 hash 值 git rev-parse HEAD git rev-parse --short HEAD # windows install git winget install Git.Git # 显示工作树状态, (已经修改但是没 git add, 或者 没有 git commit) # 显示索引文件和当前HEAD提交有差异的路径,工作树和索引文件有差异的路径,以及工作树中不被Git追踪的路径(也不被gitignore[5]忽略)。前者是你通过运行 "git commit "会提交的东西;第二和第三者是你在运行 "git commit "之前通过运行 "git add "可以提交的东西。 git status -s # 查看本地仓库的当前分支和远程分支的差异(已经 commit 但是还没 push), 只显示 commit id 和 comments git cherry -v # 查看本地仓库的当前分支和远程分支的差异(已经 commit 但是还没 push), 展示方式类似 git log git log master ^origin/master # 计算对象数和磁盘消耗 git count-objects -vH # 指定目录 1.8.5 以前 git --git-dir=/Users/jhoffmann/tmp/my-project/.git --work-tree=/Users/jhoffmann/tmp/my-project/ pull # 指定目录 >=1.8.5 git -C /Users/jhoffmann/tmp/my-project/ pull options -C, 大写 C 指定目录, .git 所在的目录 –version, 查看 git 版本 origin https://www.zhihu.com/question/27712995 ...

2026-03-18 · 19 min · 4027 words · -

k8s command

k8s command commands kubekey https://github.com/kubesphere/kubekey Rancher https://rancher.com/ archlinux install k8s ubuntu install k8s commands # 查看某一个 pod 配置 kubectl get pod <pod-name> -n <namespace> -o yaml # 找到 Pod 所属的 Controller(通常是 Deployment) kubectl get pod <pod-name> -o jsonpath="{.metadata.ownerReferences[0].name}" # 查看 Deployment 的 YAML 启动命令 kubectl get deployment bgp-opt-backend -o yaml # exec api kubectl exec -it "$(kubectl get pods | grep -Eo '^[^ ]+' |grep api)" -- bash # pod kubectl get pod -A -o wide # 查看 pod, 比如能看到镜像版本 kubectl describe pods pod0 # configmap kubectl apply -f redis-config.yaml kubectl get configmap kubectl get configmap -n namespace0 kubectl edit configmap configmap0 kubectl delete configmap configmap0 # 显示集群信息 kubectl cluster-info kubectl cluster-info dump # 查询所有节点标签信息 kubectl get node -o wide --show-labels # kube-system namespace 的 pod kubectl get pods -n kube-system kubectl label node 192.168.0.212 gpu=true kubectl get node -L gpu kubectl get node -L kubernetes.io/arch # delete lable kubectl label node minikube disktype- kubectl describe node node0 ## 节点关机操作 ```bash # 1. 标记节点为不可调度(防止新 Pod 调度到该节点) kubectl cordon <node-name> # 2. 驱逐节点上的 Pod(优雅地将 Pod 迁移到其他节点) kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data # 3. 验证节点上是否还有 Pod 运行 kubectl get pods --all-namespaces -o wide | grep <node-name> # 4. 关机 sudo poweroff # 5. 节点重新上线后,恢复调度(取消不可调度状态) kubectl uncordon <node-name> 查看 pod 状态 kubectl get pods –all-namespaces ...

2026-03-10 · 16 min · 3198 words · -

Git

Git graph LR work["Working tree<br/>工作树/工作区"] stage["Index / Staging Area<br/>暂存区"] repo["Local Repository<br/>本地仓库"] remote["Remote Repository<br/>远程仓库"] work -->|add| stage stage -->|commit| repo repo -->|push| remote remote -->|pull| work remote -->|"fetch/clone"| repo stage -->|checkout| work repo -->|merge| work repo -->|"reset --soft"| stage repo -->|rebase| stage repo -->|"reset --mixed"| work 工作区 (working tree) working tree, 2.9.1 之前被称作 Working Directory https://stackoverflow.com/questions/39128500/working-tree-vs-working-directory 也称工作区, 工作目录、工作副本 我们日常开发操作是在工作区中进行的。 工作区的内容会包含提交到暂存区和版本库(当前提交点)的内容,同时也包含自己的修改内容。 ...

2026-03-06 · 2 min · 344 words · -

video, h.264, h.265, ffmpeg

“video, h.264, h.265, ffmpeg” H.265与H.264是ITU-T VCEG 制定的视频编码标准。H.265标准围绕着现有的视频编码标准H.264,保留原来的某些技术,同时对一些相关的技术加以改进。新技术使用先进的技术用以改善码流、编码质量、延时和算法复杂度之间的关系,达到最优化设置。具体的研究内容包括: 提高压缩效率、提高鲁棒性和错误恢复能力、减少实时的时延、减少信道获取时间和随机接入时延、降低复杂度等。H264由于算法优化,可以低于1Mbps的速度实现标清数字图像传送;H265则可以实现利用1~2Mbps的传输速度传送720P (分辨率1280*720) 普通高清音视频传送。 H.265旨在在有限带宽下传输更高质量的网络视频,仅需H.264的一半带宽即可播放相同质量的视频。H.265标准也同时支持4K(4096×2160)和8K(8192×4320)超高清视频。 H.264 H.264,同时也是MPEG-4第十部分,是由ITU-T视频编码专家组 (VCEG) 和ISO/IEC动态图像专家组 (MPEG) 联合组成的联合视频组 (JVT,Joint Video Team) 提出的高度压缩数字视频编解码器标准。这个标准通常被称之为H.264/AVC (或者AVC/H.264或者H.264/MPEG-4AVC或MPEG-4/H.264 AVC) 而明确的说明它两方面的开发者。 H.264最大的优势是具有很高的数据压缩比率,在同等图像质量的条件下,H.264的压缩比是MPEG-2的2倍以上,是MPEG-4的1.5~2倍。举个例子,原始文件的大小如果为88GB,采用MPEG-2压缩标准压缩后变成3.5GB,压缩比为25∶1,而采用H.264压缩标准压缩后变为879MB,从88GB到879MB,H.264的压缩比达到惊人的102∶1。低码率 (Low Bit Rate) 对H.264的高的压缩比起到了重要的作用,和MPEG-2和MPEG-4ASP等压缩技术相比,H.264压缩技术将大大节省用户的下载时间和数据流量收费。尤其值得一提的是,H.264在具有高压缩比的同时还拥有高质量流畅的图像,正因为如此,经过H.264压缩的视频数据,在网络传输过程中所需要的带宽更少,也更加经济。 H.265, HEVC(高效视频编码) H.265是ITU-TVCEG继H.264之后所制定的新的视频编码标准。H.265标准围绕着现有的视频编码标准H.264,保留原来的某些技术,同时对一些相关的技术加以改进。 新技术使用先进的技术用以改善码流、编码质量、延时和算法复杂度之间的关系,达到最优化设置。具体的研究内容包括: 提高压缩效率、提高鲁棒性和错误恢复能力、减少实时的时延、减少信道获取时间和随机接入时延、降低复杂度等。H264由于算法优化,可以低于1Mbps的速度实现标清数字图像传送;H265则可以实现利用1~2Mbps的传输速度传送720P (分辨率1280*720) 普通高清音视频传送。 H.265旨在在有限带宽下传输更高质量的网络视频,仅需原先的一半带宽即可播放相同质量的视频。这也意味着,我们的智能手机、平板机等移动设备将能够直接在线播放1080p的全高清视频。H.265标准也同时支持4K(4096×2160)和8K(8192×4320)超高清视频。可以说,H.265标准让网络视频跟上了显示屏"高分辨率化"的脚步。 H.265 与 H.264 有何不同 在讨论 H.265有哪些提升和优点之前,我们不妨先来了解一下H.264。H.264 也称作 MPEG-4AVC(Advanced Video Coding,高级视频编码),是一种视频压缩标准,同时也是一种被广泛使用的高精度视频的录制、压缩和发布格式。H.264 因其是蓝光光盘的一种编解码标准而著名,所有蓝光播放器都必须能解码H.264。更重要的是,因为苹果公司当初毅然决然抛弃了Adobe 的VP6 编码,选择了 H.264,这个标准也就随着数亿台iPad和iPhone 走入了千家万户,成为了目前视频编码领域的绝对霸主,占有超过80%的份额。H.264 也被广泛用于网络流媒体数据、各种高清晰度电视广播以及卫星电视广播等领域。H.264相较于以前的编码标准有着一些新特性,如多参考帧的运动补偿、变块尺寸运动补偿、帧内预测编码等,通过利用这些新特性,H.264比其他编码标准有着更高的视频质量和更低的码率,也因此受到了人们的认可,而被广泛应用。 H.265/HEVC 的编码架构大致上和H.264/AVC的架构相似,也主要包含: 帧内预测(intra prediction)、帧间预测(inter prediction)、转换(transform)、量化(quantization)、去区块滤波器(deblocking filter)、熵编码(entropy coding)等模块。但在HEVC编码架构中,整体被分为了三个基本单位,分別是: 编码单位(coding unit,CU)、预测单位(predict unit,PU)和转换单位(transform unit,TU)。 H.265为 何优于H.264 比起H.264/AVC,H.265/HEVC提供了更多不同的工具来降低码率,以编码单位来说, 最小的8x8到最大的64x64。信息量不多的区域(颜色变化不明显,比如车体的红色部分和地面的灰色部分)划分的宏块较大,编码后的码字较少,而细节多的地方(轮胎)划分的宏块就相应的小和多一些,编码后的码字较多,这样就相当于对图像进行了有重点的编码,从而降低了整体的码率,编码效率就相应提高了。同时,H.265的帧内预测模式支持33种方向(H.264只支持8种),并且提供了更好的运动补偿处理和矢量预测方法。 反复的质量比较测试已经表明,在相同的图象质量下,相比于H.264,通过H.265编码的视频码流大小比H.264减少大约39-44%。由于质量控制的测定方法不同,这个数据也会有相应的变化。通过主观视觉测试得出的数据显示,在码率减少51-74%的情况下,H.265编码视频的质量还能与H.264编码视频近似甚至更好,其本质上说是比预期的信噪比(PSNR)要好。这些主观视觉测试的评判标准覆盖了许多学科,包括心理学和人眼视觉特性等,视频样本非常广泛,虽然它们不能作为最终结论,但这也是非常鼓舞人心的结果。 目前的HEVC 标准共有三种模式: Main、Main10 和Main Still Picture。Main模式支持8bit色深(即红绿蓝三色各有256个色度,共1670万色),Main10模式支持10bit色深,将会用于超高清电视(UHDTV)上。前两者都将色度采样格式限制为4: 2: 0。预期将在2014年对标准有所扩展,将会支持4: 2: 2和4: 4: 4采样格式(即提供了更高的色彩还原度)和多视图编码(例如3D立体视频编码)。 ...

2026-03-03 · 2 min · 253 words · -

ps command

ps command Linux 中的 ps 命令是 Process Status 的缩写 输出指定的字段 ps -eo pid, ppid, command ps -e -o 'pid,comm,args,pcpu,rsz,vsz,stime,user,uid' 其中 rsz 是是实际内存 ps -e -o 'pid,comm,args,pcpu,rsz,vsz,stime,user,uid' | grep oracle | sort -nrk5 其中 rsz 为实际内存,上例实现按内存排序,由大到小 http://blog.fpliu.com/it/software/procps ps 命令用来列出系统中当前运行的那些进程。ps 命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的进程,如果想要动态的显示进程信息, 可以使用 top 命令。 要对进程进行监测和控制,首先必须要了解当前进程的情况,也就是需要查看当前进程,而 ps 命令就是最基本同时也是非常强大的进程查看命令。使用该命令可以确定有哪些进程正在运行和运行的状态、进程是否结束、进程有没有僵死、哪些进程占用了过多的资源等等。总之大部分信息都是可以通过执行该命令得到的。 linux 上进程有 5 种状态 运行 (正在运行或在运行队列中等待) 中断 (休眠中, 受阻, 在等待某个条件的形成或接受到信号) 不可中断 (收到信号不唤醒和不可运行, 进程必须等待直到有中断发生) 僵死 (进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放) 停止 (进程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信号后停止运行运行) STAT 进程的状态 R 运行 Runnable (on run queue) 正在运行或在运行队列中等待。 S 睡眠 Sleeping 休眠中, 受阻, 在等待某个条件的形成或接受到信号。 I 空闲 Idle Z 僵死 Zombie (a defunct process) 进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放。 D 不可中断 Uninterruptible sleep (ususally IO) 收到信号不唤醒和不可运行, 进程必须等待直到有中断发生。不可中断的睡眠,通常是I/O T 停止 traced or stopped 进程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信号后停止运行运行。 停止或被追踪 terminate终止 P 等待交换页 W 进入内存交换(从内核2.6开始无效) 无驻留页 has no resident pages 没有足够的记忆体分页可分配。换出,表示当前页面不在内存 (从内核2.6开始无效) X 死掉的进程 < 高优先级进程 N 低优先级进程 L 内存锁页 Lock 有记忆体分页分配并缩在记忆体内, 些页被锁进内存 s session leader (在它之下有子进程) l 多进程的 (使用 CLONE_THREAD, 类似 NPTL pthreads) + is in the foreground process group, 前台运行. 默认情况下, ps 不会显示很多进程信息, 只是列出与当前终端会话相关的进程 ...

2026-03-02 · 4 min · 650 words · -

kitty

kitty kitty 是一个 GPU based terminal https://sw.kovidgoyal.net/kitty/ SSH 连接远程主机 xterm-kitty: unknown terminal type Kitty 使用 xterm-kitty 作为 $TERM 环境变量的值。通过 SSH 连接远程主机时,该值会被传递过去,但远程主机的 terminfo 数据库中没有 xterm-kitty 的定义,导致 git、vim 等程序报错: 'xterm-kitty': unknown terminal type. 解决方案:使用 kitty +kitten ssh Kitty 内置了 ssh kitten,连接时会自动将 terminfo 传到远程主机。 在 ~/.zshrc(或 ~/.bashrc)中添加别名: alias ssh='kitty +kitten ssh' 然后执行: source ~/.zshrc 之后直接执行 ssh openclaw 即可,无需其他改动。 远程控制(Remote Control) Kitty 支持通过命令行远程控制终端,可以实现自动化窗口管理、发送命令等功能。 启用远程控制 在 ~/.config/kitty/kitty.conf 中添加: # Unix Socket 方式(推荐,可从任何终端控制) allow_remote_control socket-only listen_on unix:/tmp/kitty.sock 注意:使用 Unix Socket 方式时,Kitty 会在 socket 文件名后自动添加进程 ID,例如: ...

2026-02-20 · 10 min · 2079 words · -

network manager

“network manager” sudo pacman -S networkmanager sudo systemctl status NetworkManager.service sudo systemctl start NetworkManager.service sudo systemctl restart NetworkManager.service sudo pacman -S nm-connection-editor sudo pacman -S network-manager-applet nmcli device nmcli connection nmcli c delete System policy prevents control of network connections System policy prevents control of network connections System policy prevents modification of network settings for all users< vim /usr/share/polkit-1/actions/org.freedesktop.NetworkManager.policy Open /usr/share/polkit-1/actions/org.freedesktop.NetworkManager.policy with root/sudo privileges and search for the following line: ...

2026-02-18 · 2 min · 290 words · -

git merge, git rebase

git merge git rebase interactive rebase Join two or more development histories together merge 合并 用于将两个或多个分支的更改合并到一起。它通常用于将一个分支上的开发成果合并到当前分支(如将 feature 分支合并回 main 分支)。其主要作用是整合不同开发者或分支上的工作,保持代码库的统一和最新。 # 基本用法 # git merge <branch-name> # merge 默认会把 commit 的历史都合并进来 # 把 branch_0 合并到当前分支 git merge branch_0 # -m 参数用于指定合并提交(merge commit)的说明信息,即合并时生成的 commit message。 git merge branch_0 -m "MSG0" # 禁用 Fast forward git merge branch_0 -m "merge with no-ff" --no-ff 合并方式 Fast-forward(快进合并) 如果当前分支没有新的提交,仅仅是落后于目标分支,Git 会直接把指针向前移动到目标分支的位置,这种合并不会产生新的合并提交。快速合并,看不出做过合并。快进合并后不会留下一个明显的"feature 分支合并节点",只有一条线性的记录。 特点: 不创建 merge commit 分支指针直接前移 提交历史呈线性 无法看出曾经有分支存在 示意图: ...

2026-02-13 · 11 min · 2185 words · -

kong

Kong 插件开发语言 Kong 支持使用多种语言开发自定义插件: 语言 方式 说明 Lua 原生支持 Kong 基于 OpenResty/Lua 构建,Lua 是最成熟、性能最好的插件开发语言,官方内置插件均用 Lua 编写 Go Go PDK 通过 go-pdk 库开发,编译为独立进程,Kong 通过 IPC 通信调用 JavaScript / TypeScript JavaScript PDK 通过 kong-js-pdk 开发,运行在独立的 Node.js 进程中 Python Python PDK 通过 kong-python-pdk 开发,运行在独立进程中,适合快速原型开发 WebAssembly (Wasm) Wasm Filter Kong 3.4+ 支持,可以用 Rust、C/C++、Go (TinyGo) 等编译到 Wasm 的语言开发,性能接近原生 除 Lua 外的其他语言插件都通过进程间通信(IPC)与 Kong 交互,会有一定的性能开销。生产环境对性能要求高的场景推荐使用 Lua 或 Wasm。 kong run postgresql docker network create kong-net # 创建 postgresql, 并创建一个实例 kong-db # KONG_DATABASE 数据库类型,必须是 postgres # 初始化 kong 数据库 nerdctl run --rm \ -e KONG_DATABASE=postgres \ -e KONG_PG_HOST=postgresql \ -e KONG_PG_PORT=5432 \ -e KONG_PG_USER=user_0 \ -e KONG_PG_PASSWORD=password_0 \ -e KONG_PG_DATABASE=kong_db \ -e KONG_PASSWORD=password_0 \ kong:3.9.1 kong migrations bootstrap # kong OSS + kong manager OOS nerdctl run -d --name kong \ --network=kong-net \ -e "KONG_DATABASE=postgres" \ -e "KONG_PG_HOST=postgresql" \ -e "KONG_PG_PORT=5432" \ -e "KONG_PG_USER=user_0" \ -e "KONG_PG_PASSWORD=password_0" \ -e "KONG_PG_DATABASE=kong_db" \ -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ -e "KONG_PROXY_LISTEN=0.0.0.0:8000,0.0.0.0:8443 ssl" \ -e "KONG_ADMIN_LISTEN=0.0.0.0:8001,0.0.0.0:8444 ssl" \ -e "KONG_ADMIN_GUI_LISTEN=0.0.0.0:8002" \ -p 80:8000 \ -p 443:8443 \ -p 8444:8444 \ -p 8001:8001 \ -p 8002:8002 \ kong:3.9.1 # -p 80:8000 # HTTP 代理端口 # -p 443:8443 # HTTPS 代理端口 # -p 8001:8001 # Admin API HTTP 端口 # -p 8444:8444 # Admin API HTTPS 端口 # -p 8002:8002 # Admin GUI HTTP 端口 curl -i -X GET --url http://localhost:8001/services # Kong Manager OSS http://kong:8002/ load balance # 创建一个 upstream curl -X POST http://192.168.50.31:8001/upstreams --data "name=k8s" # 添加两个 targets 到 upstream curl -X POST http://192.168.50.31:8001/upstreams/k8s/targets \ --data "target=192.168.50.80:6443" \ --data "weight=100" curl -X POST http://192.168.50.31:8001/upstreams/k8s/targets \ --data "target=192.168.50.82:6443" \ --data "weight=100" # 创建一个Service 目标到 Blue upstream # host: upstream name curl -X POST http://192.168.50.31:8001/services/ \ --data "name=k8s-service" \ --data "host=k8s" # 最后, 添加一个 Route 作为一个端点到 Service curl -X POST http://192.168.50.31:8001/services/k8s-service/routes/ \ --data "hosts[]=k8s.wiloon.com" commands curl -s localhost:8001 | jq '.configuration' kong manager add route upstreams name: enx-api targets target address: enx:8080 gateway service new gateway service name: enx-api-service service endpoint protocol: https host: enx-api-upstream ca certificate cert: past the content of ca-cert.crt certificates cert: the content of wiloon.crt key: wiloon.key upstreams Upstream 是在 Kong 中管理后端服务的负载均衡机制。当请求到达 Service 时,Kong 会通过定义的 Upstream 来选择一个具体的后端实例(例如,一个微服务的多个副本)。 如果不使用负载均衡就不需要配置 upstreams 了, 直接在 gateway service 中配置 service endpoint 即可. ...

2026-02-11 · 4 min · 662 words · -

Linux 显示器分辨率问题修复:手动加载 EDID 固件

EDID 简介 什么是 EDID? EDID (Extended Display Identification Data) 是一种标准化的数据结构,用于显示器向计算机系统描述自己的能力和特性。可以将它理解为显示器的"身份证"或"技术规格说明书"。 EDID 包含的信息: 基本标识信息: 制造商 ID(如 Dell = “DEL”, Samsung = “SAM”) 产品型号代码和序列号 生产日期(周数/年份) 显示能力参数: 支持的分辨率列表(如 1920x1200, 1600x1200, 1280x1024) 支持的刷新率(如 60Hz, 75Hz) 原生(推荐)分辨率 色彩深度和色域信息 物理特性: 屏幕物理尺寸(以毫米为单位,用于计算正确的 DPI) 显示接口类型(模拟/数字) Gamma 值(2.2 是常见值) 系统如何读取 EDID? 是的,操作系统从显示器读取 EDID 信息。 这是一个自动化的初始化过程: ┌─────────────────────────────────────────────────────────────┐ │ 1. 物理连接 │ │ 显示器连接到主机(HDMI/DisplayPort/DVI/VGA) │ │ 硬件检测到连接 │ └──────────────────┬──────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ 2. DDC 通信初始化 │ │ 主机 → 显示器:发起 DDC (Display Data Channel) 请求 │ │ 使用 I2C 总线协议 │ └──────────────────┬──────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ 3. EDID 数据传输 │ │ 显示器 → 主机:返回 EDID 数据(128 或 256 字节) │ │ 通过显示线缆内的专用数据通道 │ └──────────────────┬──────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ 4. 内核处理 │ │ GPU 驱动解析 EDID → 验证校验和 → 提取支持的模式 │ └──────────────────┬──────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ 5. 自动配置 │ │ 选择最佳分辨率(通常是原生分辨率)→ 配置显示输出 │ └─────────────────────────────────────────────────────────────┘ 通信协议细节: ...

2026-02-08 · 17 min · 3512 words · -

Linux 显示器分辨率问题修复:手动加载 EDID 固件

EDID 简介 什么是 EDID? EDID (Extended Display Identification Data) 是一种标准化的数据结构,用于显示器向计算机系统描述自己的能力和特性。可以将它理解为显示器的"身份证"或"技术规格说明书"。 EDID 包含的信息: 基本标识信息: 制造商 ID(如 Dell = “DEL”, Samsung = “SAM”) 产品型号代码和序列号 生产日期(周数/年份) 显示能力参数: 支持的分辨率列表(如 1920x1200, 1600x1200, 1280x1024) 支持的刷新率(如 60Hz, 75Hz) 原生(推荐)分辨率 色彩深度和色域信息 物理特性: 屏幕物理尺寸(以毫米为单位,用于计算正确的 DPI) 显示接口类型(模拟/数字) Gamma 值(2.2 是常见值) 系统如何读取 EDID? 是的,操作系统从显示器读取 EDID 信息。 这是一个自动化的初始化过程: ┌─────────────────────────────────────────────────────────────┐ │ 1. 物理连接 │ │ 显示器连接到主机(HDMI/DisplayPort/DVI/VGA) │ │ 硬件检测到连接 │ └──────────────────┬──────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ 2. DDC 通信初始化 │ │ 主机 → 显示器:发起 DDC (Display Data Channel) 请求 │ │ 使用 I2C 总线协议 │ └──────────────────┬──────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ 3. EDID 数据传输 │ │ 显示器 → 主机:返回 EDID 数据(128 或 256 字节) │ │ 通过显示线缆内的专用数据通道 │ └──────────────────┬──────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ 4. 内核处理 │ │ GPU 驱动解析 EDID → 验证校验和 → 提取支持的模式 │ └──────────────────┬──────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ 5. 自动配置 │ │ 选择最佳分辨率(通常是原生分辨率)→ 配置显示输出 │ └─────────────────────────────────────────────────────────────┘ 通信协议细节: ...

2026-02-08 · 17 min · 3512 words · -

Fork 项目同步与提交 PR 的完整流程

概述 在参与开源项目开发时,通常的工作流程是:Fork 主仓库 → 在自己的仓库开发 → 保持与主仓库同步 → 提交 Pull Request。本文记录这个完整的操作流程。 前置准备 添加上游仓库 首次 fork 项目后,需要添加原始仓库(上游仓库)作为远程仓库: # 添加上游仓库 git remote add upstream <原始仓库的 git 地址>igin https://github.com/your-username/project.git (fetch) origin https://github.com/your-username/project.git (push) upstream https://github.com/original-owner/project.git (fetch) upstream https://github.com/original-owner/project.git (push) origin: 你的 fork 仓库 upstream: 原始仓库(上游) 保持本地主分支同步 在开发新功能前,或定期需要将上游仓库的最新变更同步到本地: 1. 获取上游仓库的最新变更 git fetch upstream 这会下载上游仓库的所有分支和提交,但不会合并到本地。 2. 切换到本地主分支 git checkout main # 或者 git switch main 3. 检查当前状态 git status 确保工作区是干净的,没有未提交的更改。 4. 合并上游主分支 git merge upstream/main 为什么 main 分支用 merge 而不是 rebase? ...

2026-02-02 · 3 min · 457 words · -

python basic

python basic 数据类型 list array, 列表, 数组 list/dict str to list/dict >>> import ast >>> x = '[ "A","B","C" , " D"]' >>> x = ast.literal_eval(x) >>> x ['A', 'B', 'C', ' D'] >>> x = [n.strip() for n in x] >>> x ['A', 'B', 'C', 'D'] colon syntax # check if two list equal sorted(a) == sorted(b) : is the delimiter of the slice syntax to 'slice out' sub-parts in sequences , [start:end] [1:5] is equivalent to "from 1 to 5" (5 not included) [1:] is equivalent to "1 to end" [:20] from start to 20 # Python 合并两个列表 # 法一: # Python合并两个列表, 相加是拼接 list1=[1,2,3] list2=[4,5,6,7] list3=list1+list2 print('list3',list3)#输出[1,2,3,4,5,6,7] # 注意:Python合并两个NumPy数组,相加时候是对应相加 import numpy as np arr1=np.array([1,2,3]) arr2=np.array([4,5,6]) arr3=arr1+arr2 print(arr3)#输出[5 7 9] #那么NumPy数组怎么拼接呢,使用concatenate arr4=np.concatenate((arr1,arr2),axis=0) print('arr4',arr4) # 法二: l3=[] l1=[1,2,3] l2=[4,5,6] l3.append(l1) l3.append(l2) print('l3',l3)#输出[[1, 2, 3], [4, 5, 6]],注意这里是二维列表,不是我们想要的结果 # 如何才能达到我们要的结果,使用 extend l1.extend(l2) print('l1',l1)#[1, 2, 3, 4, 5, 6] # 总结: # Python合并两个列表,可用两个列表相加存入新列表,或者使用extend在原列表修改 ———————————————— ...

2026-01-29 · 38 min · 8022 words · -

git reset

git reset git reset 是一个重置 (reset) 命令, 通过 git reset 命令可以修改 HEAD 指向不同的提交,这个提交甚至都不必是当前分支上的某次提交, 只要是版本库中合法提交都可以使用这个命令进行设置,相应的版本库的内容也会发生对应的变化, 它可以使你正在开发的 dev 分支瞬间变成 master 分支。 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-NC-SA 版权协议,转载请附上原文出处链接和本声明。 原文链接:https://blog.csdn.net/albertsh/article/details/106448035 # 默认 --soft # 默认 HEAD git reset # 如果本地有没提交到 local repo 的话, 会提示 Unstaged changes after reset, 如果的确是要放弃修改, 可以执行 git reset --hard # 丢弃 工作树 和 索引 的修改 git reset --hard # 等价于 git reset --hard HEAD # reset 最近一次 commit git reset --hard HEAD^ git reset --hard HEAD~1 # reset 最近两次 commit git reset --hard HEAD~2 # reset 到某一个 commit, 退到/进到 指定 commit_id # 默认是 --mixed 模式(保留工作区修改,撤销 commit 和 git add) git reset commit_id # 等价于 git reset --mixed commit_id # hard reset 到指定 commit(危险!会丢失所有修改) git reset --hard commit_id git reset --soft HEAD^ # 重置到远程分支(丢弃本地未 push 的 commit) git fetch origin git reset --hard origin/main # 如果是其他分支,替换 main 为对应分支名 进行了错误的提交,但是还没有 push 到远程分支,想要撤销最近的几次提交 (commit),可以使用 git reset –-soft/hard 命令。 ...

2026-01-29 · 5 min · 996 words · -