跳到主要内容

端口占用问题后续

· 阅读需 1 分钟

https://blog.wangzhy.com/blog/windows-port-occupancy-issue 后续

发现是因为开启了 Clash Verge 的 tun 模式。

tun 模式的工作原理

  1. 创建虚拟网卡,所有的流量都会被重定向到这个虚拟网卡
  2. 接管所有的网络
    1. 系统级代理
    2. 本地回环地址
    3. 进程间的本地通信
  3. 端口绑定冲突,Clash 为了转发流量可能会做一下操作
    1. 预先占用或监听某些端口
    2. 拦截端口绑定操作
    3. DNS 劫持和流量重定向
  4. 防火墙级别拦截

高效完成任务而不感到疲惫的方法

· 阅读需 4 分钟

是否每天都觉得过筋疲力尽,这大概归因于两点。

  1. 你每天都要干很多事
  2. 每件事对你来说都有阻力(或许是事情太难,也或许是你太懒了)

然后你就需要用意志力(willpower)去克服阻力(resistance),获得干活的动力(motivation),久而久之就产生了倦怠(burnout)

willpower -> resistance -> motivation ..... burnout

为了解决这个现象,需要搞明白三个问题。

  1. 阻力来自哪里
  2. 如何应付阻力
  3. the exhaustion trap

第一个问题:阻力来自哪里?

每天都有很多事要做,但是直到一天都快过完了,任务却没有完成多少,觉得自己今天啥都没干又浑浑噩噩的过了一天,躺在床上,思考今天本应该要完成的事。大脑突然充满干劲,但你现在什么都干不了(总不能起来吧,你明天还有很多事要做呢,还得上班呢)然后,你失眠了。第二天,又重复这个过程,形成一个恶性循环。

第二个问题:如何应付阻力?

养成一个好习惯(habit),因为习惯是 autopilot 的(理解为本能),你只用花费很少的意志力就能克服阻力。

养成一个好习惯需要经历 4 个阶段。决策(decision),启动(initiation),强化(reinforcement),养成习惯(habit)

decision: 做一个决策是很容易的,比如想要干一件事,想要学习什么东西。做这个决定是很容易的,几乎不需要克服什么阻力(也许是强加给你的,比如上级安排的任务)。

initiation: 启动的阻力和门槛也很低。开始干活/学习,制定一个计划也没有什么难度。

reinforcement: 强化这个阶段就需要克服极大的阻力了,需要重复,直到养成一个好习惯。

habit: 这是我们的终极目标。

将强化阶段根据认为心理学划分为四个象限,横轴是 reinforcement 和 punishment,纵轴是 positive 和 negative。

正向强化就是通过增加某些东西(如多巴胺)来强化系统。一般是通过奖励机制来获得多巴胺,但这个会随着时间的推移,逐渐适应(3-6周)。它虽然有效,但难以维持。

负向强化通过移除某些负面行为来强化习惯。比如强烈的警告(未系安全带时的紧迫提示音,快到 DDL 的工作任务)等。通过解决这些东西来进行强化习惯(这不是一个好习惯)。 这个短期有效,不能持续。因为这个是依赖压力或者某些 bad things. 通过解决压力或 bad things 来进行强化。所以有的人就会把所有的事堆在一起,等到 DDL 的时候 才会开始处理。然后得到了一种强化,然后下次还这样。于是一个坏的习惯就养成了。但是对现在并没有任何改变。每天还是会有很多事情等着你。一个好的负向强化方案是:当你 感觉到压力大的时候,尝试冥想,这会使你放松,压力减小,使你得到了一种强化。

正向惩罚,就是通过增加一些不好的东西使你得到惩罚(低效且不可靠)。因为正向惩罚只教你不应该做什么,而没有教你应该怎么做。正向惩罚会导致负强化增强,这是一个恶性循环。 只有在一些情况下,正向惩罚是有效的/推荐的。那就是在危机人身安全的时候。

负向惩罚,通过移除某些东西来进行惩罚。如不准玩游戏,不准出门。

还有一个概念就是 extinction(灭绝)。extinction 指的是通过移除维持行为的强化物来避免某种行为。某种不好的行为存在是因为有某种强化物导致它存在,你要做的就是移除这种强化物。

拖延症就是一种负向强化。

解决拖延症一个好的方案是,给一个 3-5 分钟的时间,不以完成任务为目的开始做这件事,到时间之后你可以选择是否要继续。持续这样,知道养成习惯。

另一个好的方法是,准备好干这件事需要的东西,如你要学习什么东西,那就提前一天把文档打开,工具打开,第二天直接干就好了。 坐下来好好想想,要从现状到完成目标,需要完成哪些步骤,不应该做什么。保持以解决问题为导向,思考 what can i do.把能提前做的都提前做

想想所有阻碍你前进的障碍,what can i do

你应该寻找解决方案,而非仅发现问题。

Windows 端口被占用

· 阅读需 7 分钟

问题的解决过程

今天碰到了一个很诡异的端口占用问题。

项目使用的端口是 9052,在启动的时候出现了下面的提示。

Description:
Web server failed to start. Port 9052 was already in use.

Action:

Identify and stop the process that's listening on port 9052 or configure this application to listen on another port.

这是一个很常见的端口占用问题,通过下面的命令就能解决了。

netstat -aon | findstr "9052"
taskkill /T /F /PID 1234

但是,在我执行 netstat -aon | findstr "9052" 之后,什么都没有输出。

奇了怪了,不应该呀。然后用 TCPView 搜索 9052 端口占用情况,也什么都没有输出。

然后我把我的问题丢给了 AI。

netstat -ano | findstr 9052  查找不到占用 9052 的应用程序,但是在启动 springboot 的时候,出现了以下提示,我应该如何排查问题? 找出占用 9052 的应用程序?

Description:

Web server failed to start. Port 9052 was already in use.

Action:

Identify and stop the process that's listening on port 9052 or configure this application to listen on another port.

AI 给了我一些的建议

  1. 用管理员运行 cmd,然后再主席 netstat 命令

  2. 使用 TCPView 软件查看

  3. 检查是否是被 IPv6 占用

    netstat -ano -p tcp | findstr 9052
    netstat -ano -p tcpv6 | findstr 9052
  4. 使用 PowerShell 执行下面的命令 (好使)

    Get-NetTCPConnection -LocalPort 9052 | Format-Table -Property LocalAddress, LocalPort, State, OwningProcess

    # 然后查看进程详情
    Get-Process -Id <PID>

    得到下面的输出

    Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
    ------- ------ ----- ----- ------ -- -- -----------
    2865 686 227392 34016 204.83 16184 1 Foxmail

最后查出来是 FoxMail 占用了 9052 端口。

思考

那现在的问题是为什么 netstat 没有结果输出, Get-NetTCPConnection -LocalPort 9052 却可以找到占用 9052 端口的应用呢?

我继续向 AI 追问。

为什么 netstat -ano | findstr 9052 没有结果输出,而 Get-NetTCPConnection -LocalPort 9052 | Format-Table -Property LocalAddress, LocalPort, State, OwningProcess 却可以找出占用  9052 端口的应用?

AI 的解释是 2 个命令的工作原理不一样。

netstat 比较老,是从 TCP/IP 协议栈的缓存中读取数据,数据不是实时的,有刷新延迟。在某些情况下,短连接或者刚建立的连接可能不会立即显示。

Get-NetTCPConnection 直接查询内核, 更准确及时。

还有一个问题,Tcpview.exe 也是从内核中读取数据,为什么当时我也没有找到呢?

继续向 AI 追问

那为什么 Tcpview.exe 没有读取到数据,Get-NetTCPConnection -LocalPort 9052 | Format-Table -Property LocalAddress, LocalPort, State, OwningProcess 却读到了数据?

AI 给出了几个可能的原因:

  1. Tcpview.exe 设置不对,如监听的协议,过滤器等设置的有问题。
  2. TCPView 的刷新时机问题,虽然都是从内核读取数据,但是 Tcpview.exe 还是会有刷新时间间隔的。默认是 1 秒。
  3. 没有以管理员权限启动 Tcpview.exe, 但是却以管理员权限启动 PowerShell。
  4. 使用问题,我在搜索的时候只输入了 9052,但是 TCPView 的显示可能是 *:9052. 我应该输入 :9052

但是现在这个问题已无法复现了,无法得知具体是哪一个原因。只能等到后续这个问题再次出现才能知道原因了。

那么,如果这个问题再次出现,我应该如何执行什么命令,来确定它的根本问题?

继续就这个问题向 AI 追问。

由于 netstat -ano | findstr 9052 和 TCPView 查询不出数据,Get-NetTCPConnection -LocalPort 9052 | Format-Table -Property LocalAddress, LocalPort, State, OwningProcess 却可以找出占用  9052 端口的应用的问题已无法复现,那么下次这个问题再次出现,我应该执行什么命令来确定这个问题的根本原因?

AI 给我返回了一个 .ps1 文件,是的,一个 .ps1 文件,之前我从来没有接触过 ps1 的任何语法。

我粗略的看了下这个 .ps1 文件,用到的语法大概是定义变量/方法,执行方法,搭配一些 if-else 语句。

然后我给 AI 提问,让它给我介绍下这些语法。

我之前从来没接触过 ps1 脚本请向我解释 ps1 中如何定义变量,方法,如何执行方法,if-else 语句的语法。

PowerShell 脚本学习

.ps1 语法学习时间

变量

  1. $name = value 来定义变量

  2. $arr = @("apple","banana","orange") 定义数组

  3. 定义哈希表

     $person = @{
    Name = "wangzhy"
    Age = 29
    City = "zhuhai"
    }
  4. 定义布尔值

     $isActive = $true
    $isDeleted = $false
  5. 特殊变量

    • $_
    • $?
    • $null
    • $true
    • $false
    • $HOME
    • $PSVersionTable
  6. 变量的使用

    • 双引号内可以直接插入变量 "my name is $name" => my name is wangzhy
    • 单引号内不会替换变量 'my name is $name' => my name is $name

函数

function name {
# function body
}

在函数体内通过 param($name) 获取参入的参数。默认按照参数传递顺序进行赋值,也可以指定。

function add {
param($a,$b)
Write-Host "a = $a"
Write-Host "b = $b"
return $a + $b
}

Write-Host " a + b = " (add 2 10) # a=2,b=10
Write-Host " a + b = " (add -b 2 -a 10) # a=10,b=2

给函数参数设置默认值 param($a,$b = 11) 如果没有给 b 传递值,那么 b 的默认值是 11。

条件判断

if(conditon){

} elseif(conditon) {

} else {

}

比较运算符

  • -eq

  • -ne

  • -gt

  • -ge

  • -lt

  • -le

  • -eq

  • -ceq 忽略大小写

  • -like 模糊匹配

  • -math 正则匹配

  • -and

  • -or

  • -not

三元运算符 $result = ($age -ge 18) ? "成年" : "未成年"

$() 的用途

  • 用于访问对象的属性或方法 $($process.Id) 执行 $process 对象的 Id 属性
  • 执行复杂表达式 $($a + $b)
  • 命令替换 Write-Host "当前时间: $(Get-Date -Format 'HH:mm:ss')"
  • 嵌套属性访问 $($connection[0].LocalPort)

.ps1 脚本文件的格式要是 **UTF-8 with BOM** 的,不然的话,如果包含中文,会出现报错。

管道符 | 的使用:将左边命令的输出传递给右边命令的输入。

  • Get-Process | Sort-Object CPU -Descending | Select-Object -First 5 获取进程 → 排序 → 选择前 5 个
  • 123 | Set-Clipboard 将 123 输出到剪贴板

最后得到一个 .ps1 文件

# ============================================
# 指定端口(通过 -port 传入,默认是 9052 端口)占用问题诊断脚本
# 当问题出现时立即运行此脚本
# ============================================

param($port = 9052)
$timestamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$logFile = "port_diagnosis_$timestamp.txt" # 日志文件

function Run-Write-Log {
param($Command)
$CommandResult = iex $Command
$Message = $CommandResult
if ($Message -isnot [string]) {
$Message = $Message | Out-String
}

Write-Host "========== $Command ==========" -ForegroundColor "GREEN"
Write-Host $Message
"========== $Command ==========" | Out-File -FilePath $logFile -Append -Encoding UTF8
$Message | Out-File -FilePath $logFile -Append -Encoding UTF8
return $CommandResult
}

$ignore = Run-Write-Log "netstat -ano | findstr :$port"
$cr = Run-Write-Log "Get-NetTCPConnection -LocalPort $port -ErrorAction SilentlyContinue"

if ($null -ne $cr) {
# 这里要对 $($conn.OwningProcess) 去重
foreach ($conn in ($cr | Select-Object -Property OwningProcess -Unique)) {
$ignore = Run-Write-Log "Get-Process -Id $($conn.OwningProcess)"
}
}

# 通过 vscode 打开这个日志文件
code $logFile

AI 对软件行业的影响

· 阅读需 1 分钟

原文: https://www.chrisgregori.dev/opinion/code-is-cheap-now-software-isnt

code is cheap now, software isn't

构建软件的门槛已经坍塌,任何人都可以通过 Claude Code 成功构建出一个程序。

这个程序只是为了解决一个一次性问题的,用之即弃。就像 txt 文本,临时记录一些内容。

软件真正的成本不在于初始编写,而在于后续维护、边界情况处理、不断累计的 UX debt(用户体验债务)以及数据所有权的复杂性。

软件工程正在迈入新时代。

软件工程的未来两年

· 阅读需 5 分钟

https://x.com/dotey/status/2010852013874045284

AI 编程正在从代码补全进化到自主执行开发任务的 AI 智能体。

初级开发者正在减少

软件开发的工作岗位可能跟会变少或变多。 变少是因为 AI 编程导致了一个人 + AI 能够干的活相当于之前的一个团队。 变多是因为 AI 编程让软件开发进入到之前从未雇佣程序员的领域(如成本或者技术问题)。

所以,未来需要的是一个精通 AI 的多面手。“你 + AI” 要能抵得过之前的一个团队。

初级程序员应该具备的技能:

  • 利用 AI Agents 构建大功能(但是要理解并能解释每一行代码)如果看不懂 AI Agents 生成的代码, 那么这个工程是无法维护的。因为目前 AI 对于一些细节处理还是有缺陷的。
  • 死磕 AI 难以替代的技能:沟通、拆解问题、领域知识(业务)。
  • 关注邻近角色,如 QA,产品,数据分析等。
  • 建立作品集,特别是集成 AI API 的项目。

高级程序员应该具备的技能:

  • 能够使用自动化来处理一些常规任务。
  • 设置 CI/CD, 代码检查器和 AI 辅助测试来捕捉基础问题。
  • 能够指导初级程序员。
  • 高级程序员的价值在于放大整个团队的产出,而不仅仅是贡献代码

AI 编程时代,编程技能会退化

28 原则。 AI 编程中,80% 的工作 AI 能处理的很好,20% 的工作是机器搞不定的。如架构、棘手的集成、创造性设计、边缘情况等。

编程方式在转变:少打样板代码(重复代码),多审查逻辑错误、安全缺陷和需求偏差(做出来的东西与需求不一致)。 关键技能变成了软件架构系统设计性能调优安全分析

初级开发者应该:

  • 把 AI 当工具,弄懂它写的代码,要能够找出它的缺陷。
  • 扎实 CS 基础:数据结构,算法,复杂度,内存管理。
  • 把项目做两遍:先 AI,再人工。然后对比差异。
  • 学习提示词工程(Prompt Engineering),精通工具。
  • 写单元测试,看懂堆栈跟踪,熟练使用调试器。
  • 深耕 AI 无法复制的软实力:系统设计,用户体验直觉,并发推理。

高级程序员应该:

  • 做质量和复杂度的守门员(代码质量要高, 复杂度低, 性能高)。
  • 磨练核心技能:架构,安全,扩展性,领域知识。
  • 练习用包含 AI 组件的模型设计系统,推演故障模式。
  • 警惕 AI 代码中的漏洞
  • 界定哪里能用 AI,哪里必须人工审查(支付,安全等方面)。
  • 投入创造性和战略性工作
  • 健全的判断力,系统级思维和指导能力

角色定位

未来,编写代码的主力一定是会变成 AI。 程序员会编程代码的审计员(程序员变成清洁工,清理 AI 生成的垃圾)或扩展为设计和治理 AI 系统的核心编排者(人人都是架构师,指挥 AI Agents 协同工作)。

初级开发者应该:

  • 寻找写代码之外的机会
  • 主动承担写测试用例,设置 CI/CD 的任务
  • 培养系统思维。
  • 阅读工程博客和系统设计案例
  • 熟悉代码生成以外的 AI 工具,如编排框架, AI API。
  • 成为验证者、设计者、沟通者。

高级程序员应该:

  • 向领导力和架构职责靠拢。
  • 指定标准,确立框架。
  • 定义代码质量清单和 AI 伦理规范。
  • 关注 AI 软件的合规与安全。
  • 深耕系统设计和集成
  • 主动梳理服务流数据,识别故障点。
  • 熟悉编排工具 k8s, AirFlow,Serverless,Agent 工具。
  • 加倍投入技术导师角色:多做代码审查、设计讨论、技术指导。
  • 要能一眼看穿代码本质的能力。
  • 培养产品和商业嗅觉,记录功能背后的商业逻辑。
  • 跟随产品经理,倾听客户声音。
  • 从程序员进化为指挥家。

专才 vs 通才

在技术栈快速变化、AI 渗透的环境下,T 型工程师更吃香:既有广泛的适应力,又有一两手绝活。

AI 工具其实是通才的神器。 后端工程师可以用 AI 做个像样的 UI;前端专家可以用 AI 生成服务端代码。 AI 让人的能力边界大幅拓展。 反观深度专才,领地被自动化蚕食,却难以突围。

初级开发者应该:

  • 打好基础。
  • 前后端都要涉及。

高级程序员应该:

  • 绘制技能图谱。
  • 前后端,UI,产品,测试都要涉及。
  • 做 T 型人才,在专业领域深耕,但积极横向拓展

教育问题

初级开发者应该:

  • 用实战项目补课。
  • 自学。
  • 打磨作品集:至少有一个文档完善的硬核项目。
  • 把 AI 当私人导师。

高级程序员应该:

  • 持续学习新技术
  • 投资继续教育(学习非本行业知识)

总结

无论未来是迎来编程复兴,还是代码自我编写的世界,永远需要这样一种工程师:思考全面、持续学习、用技术解决真问题。

别把 AI 当拐杖,要把它当陪练。 即使有计算器,你也得先懂数学原理。

清空测试环境的 activiti 数据的 SQL

· 阅读需 1 分钟
-- 禁用外键检查
SET FOREIGN_KEY_CHECKS = 0;

TRUNCATE TABLE ACT_EVT_LOG;
TRUNCATE TABLE ACT_GE_BYTEARRAY;
TRUNCATE TABLE ACT_HI_DETAIL;
TRUNCATE TABLE ACT_HI_COMMENT;
TRUNCATE TABLE ACT_HI_IDENTITYLINK;
TRUNCATE TABLE ACT_HI_PROCINST;
TRUNCATE TABLE ACT_HI_VARINST;
TRUNCATE TABLE ACT_HI_TASKINST;
TRUNCATE TABLE ACT_HI_ACTINST;
TRUNCATE TABLE ACT_RU_IDENTITYLINK;
TRUNCATE TABLE ACT_RU_TASK;
TRUNCATE TABLE ACT_RU_VARIABLE;
TRUNCATE TABLE ACT_RU_EXECUTION;
TRUNCATE TABLE ACT_HI_ATTACHMENT;
TRUNCATE TABLE ACT_RU_EVENT_SUBSCR;
TRUNCATE TABLE ACT_RU_JOB;
TRUNCATE TABLE ACT_PROCDEF_INFO;
TRUNCATE TABLE ACT_RE_DEPLOYMENT;
TRUNCATE TABLE ACT_RE_MODEL;
TRUNCATE TABLE ACT_RE_PROCDEF;

SET FOREIGN_KEY_CHECKS = 1;

DOM 选择器

· 阅读需 2 分钟
  1. 元素选择器 querySelector('div')

  2. ID 选择器 querySelector('#id')

  3. 类选择器 querySelector('.myClass')

  4. 属性选择器

    • querySelector('[data-id]') 有 data-id 属性
    • querySelector('[type="text"]') type 属性值为 text
    • querySelector('[href^="https"]') href 以 https 开头
    • querySelector('[class*="btn"]') class 包含 btn
  5. 后代选择器 querySelector('div a')

  6. 直接子元素选择器 querySelector('div > a')

  7. 相邻兄弟选择器 querySelector('h1 + p') h1 之后相邻的 p 元素

  8. 伪类选择器

    • :first-child 第一个子元素
    • :last-child
    • :nth-child(n) 第 n 个子元素
    • :nth-last-child(n)
    • :first-of-type 第一个相同类型的子元素
    • :last-of-type
    • :nth-of-type(n)
    • :only-child 唯一的子元素
    • :only-of-type
    • :hover
    • :focus
    • :active
    • :checked
    • :disabled
    • :enabled
    • :visited 已访问的链接
    • :not(selector)
  9. 复杂组合的案例

    // 选择 class 为 container 的 div 中的所有选中的 checkbox
    document.querySelectorAll('div.container input[type="checkbox"]:checked')

    // 选择第一个 section 中的最后一个 p 标签
    document.querySelector('section:first-of-type p: last-child')

    // 选择不含 disabled 类的按钮
    document.querySelectorAll('button:not(. disabled)')

    // 选择所有偶数行的 tr
    document.querySelectorAll('tr:nth-child(even)')

根据心跳接口计算设备离线时间

· 阅读需 1 分钟

方案一:在内存中缓存设备的在线状态

每次心跳时,读取内存中的数据,更新设备在线状态和时间。

定时任务来更新设备的状态,并记录设备离线事件。

方案二:redis + mysql

redis 存设备实时状态

下线的设备通过定时轮询 reids 数据或监听 redis 的过期事件

mysql 存设备上下线事件

终端是如何工作的

· 阅读需 5 分钟

原文: How Terminals Work

  1. Terminal 就是一个由等大单元格组成的网格.

  2. 每个单元格只能存放一个字符加上一些样式(颜色,加粗,下划线).

  3. 转义序列(Escape Sequences): 特殊字符序列控制着 Terminal 的行为(移动光标, 改变颜色, 清空屏幕)

  4. 当你按一下个键时, 终端会向程序发送转义之后的字符序列. (终端默认不会发送鼠标事件。程序需要先请求鼠标追踪功能,之后点击操作才会转换为带坐标的转义序列)

  5. Signals(信号量): Ctrl + C 组合键不会输入字符,而是会发送一个信号. 终端会拦截特殊的组合键, 并转化为操作系统层面的事件(信号量), 用于中断或控制程序运行.

    • ctrl + c 中断 Interrupt

    • ctrl + z 暂停程序 Suspend

    • ctrl + D 文件结束 End of file

    普通按键会转换为字节流传输给程序,而信号键则被终端拦截并转换为操作系统级别的事件,用于中断或控制进程。

  6. Raw vs Cooked Mode

    • Cooked mode: 需要输入整行后按回车键 (Shell, bash, zsh, cat)
    • Raw mode: 每个按键都会直接发送给程序. (vim, htop, ssh, less)
  7. The Round Trip: 每次按键都会通过终端栈传递给程序,随后输出结果又会回流到屏幕上显示。

    1. 每按下按键
    2. 终端键按键编码成字符
    3. 将字符传输给 Shell 进程
    4. 终端将输入的字符显示出来
    5. 按下回车键(Shell 执行命令)
    6. Shell 将执行结果传输给终端
    7. 终端将结果显示出来

    1. keystore -> 2. encode -> 3. Shell -> 4. execute -> 5. output -> 5. render (repeat!)

  8. 构建复杂终端用户界面 (Building Complex TUIs)

    • htop, vim 这种高级 TUI 会将屏幕划分为多个区域.
      • 每个区域都有自己的内容, 调整大小的方式 (用字符而非像素来构建图形用户界面)
      • 以字符单元格来存储其坐标,尺寸使用制表符 (┌─┐│) 绘制可视化边框
      • 当内容发生变化时, 文本用户界面会自动重新计算这些参数.
      • 每次只会有一个区域获得焦点(focused)
      • 调整终端窗口大小时, 系统会发送 SIGWINCH 信号. TUI 会通过 ioctl() 获取新尺寸,重新计算各个区域尺寸并刷新整个屏幕显示.
      • 先在内存中完成绘制,再一次性输出全部内容。
  9. 终端有 2 套屏幕, 终端根据输入在这 2 套屏幕之间切换.

    • normal(带滚动),
    • alternate(供应用程序作画布使用) (vim, kess, man, htop, tmux 等终端应用都会启用备用屏幕)
  10. Terminal Icons, 就是特殊渲染的 Unicode 字符

  11. 状态管理

    • 在 Claude Code 按下 shift+ tab 组合键时, 终端不会记住任何状态(而是由 Claude Code 在内存中处理)
      • 状态变化时 Claude Code 会重新绘制屏幕的相关部分
      • Claude Code 会保存下面这些程序变量. 注意: 终端本身并不存储应用的状态---它仅显示你发送的字符内容
        • currentMode
        • inputBuffer
        • history
    • Claude Code 可以将状态保存到文件中.
  12. Text Selection & Cursor Positioning

    • 无法通过点击来移动光标
    • 终端本质上是一个被动的显示设备。它只在应用程序指定的位置显示字符。光标位置完全由正在运行的程序控制,终端只能通过发送按键事件来施加影响,而这些事件最终由程序来解析和处理。
  13. 终端术语表

    • Terminal: 终端, 最早终端指的是连接计算机的带屏幕和键盘的物理设备. 现在说终端一般都是指终端模拟器.
    • Terminal Emulator: 终端模拟器
      • iTerm2
      • windows Terminal
      • kitty
    • Shell: 一个解释命令的程序。Shell 负责读取你输入的内容、执行程序,并处理诸如管道、重定向和脚本编写等任务。Terminal 只是那个窗口;Shell 才是运行在其中的程序。
      • sh
      • bash
      • zsh
      • fish
      • ksh
      • tsch
      • nushell
    • bash: 大多数 linux 操作系统默认的 Shell
    • console
    • CLI
      • git
      • npm
      • docker
      • curl

  14. 常见问题

    1. 终端设置与 Shell 配置的区别?
      • 终端设置是软件方面的, 只能修改终端界面的显示, 如字体, 颜色, 大小
      • Shell 配置是需要到服务器上修改文件的.
    2. 通过上下箭头调出之前的命令是 Shell 程序.
    3. 为什么修改 .zshrc 要重启终端?
      • 因为 .zshrc 是 Shell 的配置文件. 已运行的 Shell 仅在启动时读取一次 .zshrc 文件.
      • 通过执行 source ~/.zshrc 让 Shell 重新加载配置
    4. 通过 echo $SHELL 查看使用的是哪个 Shell
    5. 通过 chsh -s /bin/zsh 切换 Shell
    6. 通过 cat /etc/shells 查看支持的 Shell 列表

AI 时代,应该如何学习?

· 阅读需 3 分钟

2026 年, AI 的发展趋势已势不可挡了. 我们能做到只能顺应趋势, 积极拥抱 AI, 学会如何去驾驭 AI.

对于只是把 AI 当作一个搜索引擎的我来说, 还是有很多需要学习的内容.

要选择 AI 容易理解和操作的技术栈。

设计 AI 产品的时候要以 AI 为中心。 现在的流程都是为人设计的,如果让 AI 模仿人的操作,做出来的东西就会很割裂。

看不懂的名词

这里连的每一个名词都可以单独出一篇文章.

Agent 分为 2 类

  1. 软件工程类 Agent (本质是流程驱动的软件开发,LLM 作为数据处理的后端)
    • Dify
    • Coze
    • n9n
  2. AI 原生 Agent(真正以 AI 驱动的 Agent)

Agent

Agent 的定义:在人工智能领域,智能体被定义为任何能够通过传感器(Sensors)感知其所处环境(Environment),并自主地通过执行器(Actuators)采取行动(Action)以达成特定目标的实体。

  • Environment: Agent 所处的外部世界
  • Actuators: 可以是物理设备或代码(函数,脚本等)

AI Agent 是为了实现某个目标循环调用工具的大语言模型。

开发 AI Agent 挑战?

  1. prompt 工程
  2. 自我修复,要能够自动检测并修复生成代码中的错误。
  3. 上下文:无法全部方法放入 context。

(2026.1.9) 在生生产环境中, 68% 的 Agent 被限制在 10 步以内.

使用的方式:结构化控制流: 任务流程都是人画好的, AI 只能在这里面填空.

Skill

Skill 提出的意义: 简化模型对工具使用上下文处理的困难程度,让它更好的执行任务拆分、检验的工作。

BTAS Budget-Aware Test-time Scaling 预算感知测试时缩放

  1. 预算感知规划
    1. 维护一个树状的 checklist, 每个节点表示一个任务, 包含状态和资源消耗信息。
    2. Agent 不是一次性列出所有步骤,而是动态更新的。
      1. 新的信息可能会创建新的分支,解决待定步骤,废弃无效路径。
      2. 预算足够时扩大搜索深度,预算紧张时深挖验证深度.
  2. 预算感知验证

Agent 目前的困境

目前的问题是需要给上下文减负。(沟通噪音和认知负担消耗了大量的上下文)

  1. 有效工具管理(如 skill 机制)
  2. 内建自我验证能力(如 BATS)
  3. 模型间高效沟通协议(A2A 协议), 未来肯定是会同时执行多个任务的(agent 与 Agent 之间需要沟通)。
    1. Claude Code 采用的是多 Agent 模式,主 Agent 负责与用户交互,并调度子 Agent 来完成特定子任务。