Anoyer - 三流痞子 - Anoyer
type: channel
link: http://193.112.96.159/index.php/author/1
description: Anoyer
items: 大模型Prompt技巧全解析
items: 20分钟聊聊clang-tidy那些事
items: Clang 新手教程
items: 单元测试的必要性？一文聊聊单元测试
items: Etcd 部署和基础操作
items: Ubuntu Bash环境变量加载详情
items: 国内安装k8s 三马车 kubectl kubelet kubeadm
items: Ubuntu 自建本地apt源
items: Ubuntu 升级 Cmake
items: 内网穿透之FRP

大模型Prompt技巧全解析
type: item
date: 2025-02-27T09:55:00+08:00
description: 第一节：Prompt定义及基本框架一、 什么是Prompt大模型 prompt 指在大语言模型应用中，用于 “提示” 模型唤起特定能力以解决实际问题的提问方式。早期它被称作 “输入形式” 或 “输入模板”，后来 “prompt”（提示）这一叫法因契合大语言模型语境，能准确体现其在调用模型能力方面的关键作用，成为公认术语。大模型多数核心能力在预训练阶段形成，prompt 就像钥匙，引导模型从预训练积累的海量信息中，精准唤起如理解复杂文本、总结信息、生成内容、逻辑推理等能力，满足用户实际需求。它并非把模型当作单纯知识库，而是高效调用其能力，实现类似人类运用智能解决复杂问题的效果，是 prompt 工程的核心，对用好大语言模型意义重大。二、 撰写Prompt的基本框架1、Prompt包含的要素● 指令：想要模型执行的特定任务或指令。● 上下文：包含外部信息或额外的上下文信息，引导语言模型更好地响应。● 输入数据：用户输入的内容或问题。● 输出指示：指定输出的类型或格式。2、Prompt五大框架2.1 RTF框架RTF(Role-Task-Format)框架是一个非常简单通用的Prompt提示框架，我们和任意大模型对话场景下都可以使用该规范进行改进输出。● R-Role(角色)：指定大模型担当固定角色(程序员、数据分析师、讲解员、记者等等)● T-Task(任务): 任务，告诉大模型需要为我们做的事情● F-Format(格式)：大模型最终结果的返回格式(比如：表格、Markdown、英文等等)主要优点：● 简单、方便。● 指定Role角色，可以让大模型在当前的角色范围内回答知识，这在一些特定的领域中非常有效。● 指定Role角色也能让工程上检索知识能够确定边界范围，配合元数据所发挥的威力会更强。● 如果结合RAG知识内容检索，那么上下文回答的内容会让用户感觉更加是顺畅。2.2 思考链模式通过这种模式来逐步改善大模型的推理能力，非常适合一些复杂的任务处理。例如：● 分析型或者逻辑推理型的任务● 决策● 解决问题(比如程序员根据错误日志找Bug)而要使用这种模式，只需要在末尾添加”让我们逐步思考”即可。例如：# 数据源（与指令区分） user_datasource = """XXX……""" prompt1 = """分析一下在人工客服服务场景下，'''{user_datasource}'''中客户有哪些诉求。用一句话概括。""" prompt2 = """分析一下在人工客服服务场景下，'''{user_datasource}'''中客户有哪些诉求。用一句话概括。让我们逐步思考。""" # 模型输出结果 output1：在人工客服服务场景下，客户主要诉求为：微信账号存在安全风险导致无法添加好友、单点拦截、下载安装微信出现问题等，寻求客服协助解决问题。 output2：在人工客服服务场景下，客户主要诉求为：微信账号存在安全风险导致无法添加好友，以及因违规行为被限制登录，客户希望客服能够尽快处理这些问题。 # 分析结果 output1中的”单点拦截”并不是用户的诉求，而output2显然更加正确2.3 RISEN框架● R-Role:大模型扮演的角色● I-Instructions: 指示命令，和Task-任务差不多● S-Steps: 步骤● E-End Goal: 最终目标● N-Narrowing(Constraints): 缩小范围(约束条件)，和RTF框架中的Format有异曲同工之妙，一个是格式的约束，而这里的约束可以是任意方面，比如回答的内容(特定领域)、字数限制等等方面该框架主要适合：● 撰写具有特定约束的任务(例如博客文章)● 有明确指导方针的任务（例如商业计划）2.4 RODES框架● R-Role: 角色● O - Objective: 目标● D - Details: 详细的细节● E - Examples: 示例● S - Sense Check: 感官检查2.5 密度链模式密度链模式Prompt是Salesforce、麻省理工学院和哥伦比亚大学的研究人员推出的一种新提示，它非常的高效，使用递归来创建越来越好的输出的提示，与普通提示生成的 GPT-4 摘要相比，它生成的摘要更加密集且更适合人们理解。适合：● 总结● 改进您最喜欢的提示● 通过递归生成可用的长格式内容(感兴趣的同学可以自己检索一下)第二节：打造高效Prompt的两大核心原则在Prompt工程领域，掌握精妙的撰写策略是释放语言模型强大潜力的关键。本节将深入探讨prompt撰写的两大核心策略，为您揭示如何通过优化指令，引导模型生成更贴合需求、更具质量的输出。一、原则一：编写明确和具体的指令为了让模型精准理解我们的意图，编写清晰、明确且具体的指令至关重要。…

20分钟聊聊clang-tidy那些事
type: item
date: 2023-04-06T11:26:56+08:00
description: 20分钟聊聊clang-tidy那些事在1月初凯新有过在各算法/公共模块引入 Clang-tidy 的提议 ，在3月初我向大家分享了一个关于完善算法/业务项目CI流程的静态代码检查的文档，其中都提到了一个工具，那就是clang-tidy，今天我便带大家聊一聊clang-tidy。Clang-tidy大家应该多少对clang-tidy这个工具有一定的了解，它是一个基于clang的静态代码分析框架。同时它是一个功能非常强大的lint工具。绝大部分lint工具只能在出现问题的地方给出提示，之后需要人为修改，而clang-tidy拥有自动修复功能（当然怎么修复需要相应 checker 作者提供）。并且clang-tidy采用模块化设计，非常容易扩展。如果用户想往clang-tidy添加一个新的检测功能，只需要编写一个clang-tidy checker实现（如何编写一个clang-tidy check以后将会有一章详细介绍），每一个checker检测一种问题，例如检测某个违反Code style的模式，检测某些API不正确使用的方法等等。那么提到了Code Style，我们不得说一说Google Code Style，这是目前使用最为广泛的一种代码规范。为此Google Code style也提供了一个cpplint脚本，用于检测代码中违反code style的地方。同时clang-tidy也支持检测代码中违反google code style的地方（google-*check）。那么可能会有人问他们之间有什么区别呢？cpplint是一个python的脚本，它是采用正则表达式匹配出违反code style的代码, 所以它能检测的功能会受限于正则表达式，它不能够检测所有的违反code style的地方，并且还会有False positive和True negative；而clang-tidy则是基于抽象语法树(AST)对源文件进行分析，相比之下，是在分析的结果更加准确，能检测的问题也更多。OK 到这里我们应该对clang-tidy 进行静态代码分析的原理有了一个大致的框架它基于clang，基于抽象语法树AST实现的。那clang和AST是什么？Clang众所周知clang是一个编译器，是一个以LLVM为后端的编译前端那么clang和llvm还有什么其他关系呢？这里我们可能需要说一下广义的llvm和狭义上的llvm了。在LLVM整体架构中，前端用的是clang，因此广义的LLVM是指整个LLVM架构，而狭义的LLVM指的是LLVM后端（包含代码优化和目标代码生成）。在LLVM架构中，源代码（c/c++）经过clang生成中间代码，之后中间代码通过优化器进行一系列的优化，最后通过后端生成机器码。而在经过前端生成中间代码过程中，前端会对代码进行词法分析、语法分析以及语义分析。而在语法分析过程中变为生成一棵语法树，也就是我们说的AST。int add(int a, int b){ typedef long long ll; return a + b; }// 我们可以使用-fsyntax-only -Xclang -ast-dump 打印出源码文件的ast // clang -fmodules -fsyntax-only -Xclang -ast-dump main.m `-FunctionDecl 0x1398df030 <test.cpp:1:1, line:4:1> line:1:5 add 'int (int, int)' |-ParmVarDecl 0x1398deed8 <col:9, col:13> col:13 used a 'int' |-ParmVarDecl 0x1398def58 <col:16, col:20> col:20 used b 'int' `-CompoundStmt 0x1398df250 <col:22, line:4:1> |-DeclStmt 0x1398df198 <line:2:5, col:25> | `-TypedefDecl 0x1398df140 <col:5, col:23> col:23 ll 'long long' | `-BuiltinType 0x139840750 'long long' `-ReturnStmt 0x1398df240 <line:3:5, col:16> `-BinaryOperator 0x1398df220 <col:12, col:16> 'int' '+' |-ImplicitCastExpr 0x1398df1f0 <col:12> 'int' <LValueToRValue> | `-DeclRefExpr 0x1398df1b0 <col:1…

Clang 新手教程
type: item
date: 2023-04-06T11:25:00+08:00
description: Clang 新手教程长话短说这个新手教程会让你弄清楚什么是clang，clang AST，clang plugins 和clang tools 等等。让你大概知道clang 可以解决什么问题，而且小白也是可以用clang libraries 来开发工具的 :)Clang 是什么？Clang 是一个以LLVM为后端的编译前端。编译前端主要负责parse 源码，检查错误，并生成Abstract Syntax Tree (AST)。Ref: Understanding the Clang AST什么时候会用到Clang？需要基于编译器的AST 对源码做精确的编辑需要引入自定义的编译错误和警告基于C/C++ 源码的代码生成(code generation)，比如生成数据结构的序列化，语言交互接（Foreign function interface）Clang AST 是什么？Clang AST 的节点是由几种没有共同基类的类来组成（建模）的Clang’s AST nodes are modeled on a class hierarchy that does not have a common ancestor.其中比较常用的四种class 是Type,Decl,DeclContext,Stmt每种节点都有专门的遍历函数来获取子节点ASTContext 里可以获取AST 的额外信息，比如源码的地址例子// test.cc int foo(int num) { int result = (num / 2); return result; } void test_f() { int i = 10; int b = foo(i); }clang -Xclang -ast-dump -fsyntax-only test.ccRef: Introduction to the Clang AST - Clang 15.0.0git documentationClang APIsClang 提供C 和C++ APIC API (libClang) 稳定但是不完整C++ API（LibTooling）完整但是不稳定LibTooling 主要用于开发standalone 工具，并且plugins 只能使用LibToolingRef: Choosing the Right Interface for Your Application - Clang 15.0.0git documentationClang plugins v.s. Clang toolsClang plugin 在编译时对AST 进行一些额外的操作。plugin是动态库（.so），在运行时由编译器加载，可以很容易集成到编译环境中。Clang tools 是由LibTooling 开发的可执行程序，比如clang-check，clang-format，clang-tidy 这些llvm project 提供的。有时候两种方式都能解决问题：# 1. As a loadable Clang plugin: clang -cc1 -load <BUILD_DIR>/lib/libLACommenter.so '\' -plugin LACPlugin test/LACInt.cpp # 2. As a standalone tool: <BUILD_DIR>/bin/ct-la-commenter test/LACInt.cpp考虑点：能不能控制用哪个编译器？clang / gcc?需不需要make 或者break buildClang 6.0 写的plugin Clang 7.0 不一定能用（API 不稳定！）CI 环境使用哪种工具用户接入成本更低？RecursiveASTVisitor v.s. ASTMatcherLibTooling 有两种framework: RecursiveASTVisitor 和ASTMatcherThe RecursiveASTVisitor provides hooks of the form bool VisitNodeType(NodeType *) for most AST nodesASTMatcher 是一套用来匹配和遍历AST 的DSL两种framework 可以一起使用来解决比较复杂的问题！https://github.com/banach-space/clang-tutor/blob/main/README.md#unusedforloopvar优先考虑用ASTMatcher，因为可以用clang-query 来验证DSL 是否正确clang-query test.cc# some useful commands to setup clang-…

单元测试的必要性？一文聊聊单元测试
type: item
date: 2022-04-08T16:50:00+08:00
description: 单元测试写的代码能一次正确执行是每个程序员的追求，但世事皆不能尽如人意，我们的代码经常会有 Bug，这就需要测试的存在。测试有黑盒和白盒之分。黑盒测试，测试时认为被测程序就像一个漆黑的盒子，虽然不明白其中的运行原理，但知道怎么输入有对应的输出。QA (Quality assurance)，也就是我们的测试部门一般负责对程序进行黑盒测试，调用接口时传确定的参数，再校验接口响应值符合某种预期。与黑盒测试对应的是白盒测试，白盒测试要求被测试人员了解被测程序的构造，从而构造测试用例校验程序各个分支逻辑。从这一方面来说，单元测试就是一种白盒测试。单元测试，又称为模块测试，是针对程序模块（软件设计的最小单位）来进行正确性检验的测试工作，一般对面向对象语言来说，这个最小单位是类或重要的类方法，它不仅可以用作功能测试，将单元测试集成到依赖集成工具之后，它们还可以在模块编译时执行，进行模块的回归测试。工作以来，我对单元测试的认知不断刷新，从拒绝到勉强接受，再到理解其中妙处，最近竟然有些理解我以前觉得不可思议的 TDD（测试驱动开发）了，我觉得有必要把其中心路历程整理一下，无论是之后回忆还是翻出来打脸，应该都很有意思。初遇单测不写单测刚开始工作时的公司是一个小型公司，项目小且业务简单，部门也没有要求，我是不写单元测试的。不接触就无法理解它，这时候我对单元测试的认识就是收益很低的”测试工具”，认为代码是自己写的，自己再编造一些数据去迎合这些代码，根本测试不出来什么，而且编造数据还要花费大量的尽力，收益和付出完全不成正比，程序的正确性靠 QA 就完全够了。可能跟我有类似想法的同事也有很多，后来我们干脆把所有的类方法都改成了静态方法，程序运行时不用再去创建服务对象了，这样，代码就变成了披着面向对象外衣的函数式程序。当然，这也进一步导致了单元测试不可能实行了，因为方法是层层调用的，想要构造出一组能正确运行的数据都非常困难，就更不用说再测试各种分支逻辑了。随波逐流后来换到了目前所在的岗位，部门强制要求每段逻辑都要有对应的单测 case，这样我才真正接触到了单元测试。刚开始写单元测试时内心是非常煎熬的，不认同还要被强制要求做，当然很不爽，更重要的是不习惯。原来功能开发完成后，自己改改参数调两遍接口测下就行，现在还要再写同样多甚至更多的代码来校验功能代码是否正确，花费的不仅是时间，还有心力。而且有些代码就没法写单测，费尽心思构造出数据，可能还没测出功能代码的问题，改单测 case 的 bug 就能让人崩溃了。这时我采用的策略就是仿着原来的单测 case 写，现在看来之前的很多单测 case 也没什么质量，又由于自己水平低，导致最终写出来的单测 case 基本没什么意义，要么是重要逻辑覆盖不到，要么是只能覆盖一些通用逻辑，就算有问题，调接口测一下也能测出来。收获也不能说完全没有，毕竟有非常明显的 bug 还是能够测出来的，而且有时候误改了之前的代码，也能够在 QA 反馈前及时解决，但总体来说，这样写单元测试是不划算的。单测的意义缘由后来 case 越写越多，在越来越熟练地满足单测覆盖的要求时，我也在不停思考这样的工作有什么意义，直到有一天被 leader review 代码，我感觉有些开悟了。被 review 代码的功能是将一个 json 字符串解析为服务里的配置模型，考虑到它只是一个解析字符串的功能，我把它定义为一个”工具类”，里面用静态方法实现，这样调用解析方法时不用注入 bean，使用类名.方法即可。我以为这个类虽然称不上完美无缺，但命名、日志、异常处理都很完善，至少算得上中规中矩，没想到被 leader 一顿狠批，因为他直接跳到这个工具类的上层类，发现这个类没有单测覆盖。为什么上层类没有写单元测试呢，不是因为上层的逻辑太过复杂，而且因为如果我想测这个上层类，就需要构造出一个能够解析为配置模型的大型字符串，还要传上一堆配置参数到这个解析工具类里，这个字符串不好构造不说，即使构造出来了，写在代码里这么一堆，也异常难看，如果之后要变更这个配置模型的结构，更是一场噩梦。思考被教育一顿后，我终于明白了，上层代码的单元测试难写，是因为这么一个工具类，工具类的静态方法无法 Mock 返回值，这就需要我构造大量的真实数据，费力也讨不了好，简而言之，是因为我的设计烂导致单测不好写。接着我观察了更多据说写不出单测的代码，反思了之前遇到的单测难写的代码，拿这些代码去对比代码设计原则，发现了这些代码的一个共同点：它们都严重违背了一种或更多设计原则，也就是说，它们都是烂代码。”不好写单测的代码都是烂代码”，我觉得我理解了单元测试的（部分）意义，单元测试不仅用来测试代码功能，还可以用来测试代码设计。从此之后，我开始更重视单元测试了，单元测试的名字不再用 “testMethodNam…

Etcd 部署和基础操作
type: item
date: 2021-10-28T15:21:00+08:00
description: docker部署方式（etcd可以单实例也可以集群）sudo docker run -d -it \ --name etcd_test \ -e ETCDCTL_API=3 \ -p 2379:2379 \ -p 2380:2380 \ quay.io/coreos/etcd:v3.3.9 \ etcd \ --advertise-client-urls http://0.0.0.0:2379 \ --listen-client-urls http://0.0.0.0:2379如果需要添加挂载目录，则追加属性--volume=etcd-data:/etcd-data以及--data-dir=/etcd-data；根据电脑架构选择合适的镜像（arm架构：e2eteam/etcd:3.4.13-0-linux-arm64）基本操作进入服务sudo docker exec -it etcd_test sh基本命令## 增加 / # etcdctl --endpoints="127.0.0.1:2379" put /test_key1/sub1 "key111" OK ## 查询 / # etcdctl --endpoints="127.0.0.1:2379" get /test_key1/sub1 /test_key1/sub1 key111 ## 删除 / # etcdctl --endpoints="127.0.0.1:2379" del /test_key1/sub1 1 ## watch监听某个key 被操作的记录 / # etcdctl --endpoints="127.0.0.1:2379" watch /test_key1/sub1 PUT /test_key1/sub1 123 PUT /test_key1/sub1 1234 DELETE /test_key1/sub1 ## 查看当前endpoint的状态 / # etcdctl endpoint --cluster=true status -w table +---------------------+------------------+---------+---------+-----------+-----------+------------+ | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX | +---------------------+------------------+---------+---------+-----------+-----------+------------+ | http://0.0.0.0:2379 | 8e9e05c52164694d | 3.3.9 | 20 kB | true | 4 | 18 | +---------------------+------------------+---------+-- ## 查看集群状态 / # etcdctl --endpoints="127.0.0.1:2379" endpoint status -w table +----------------+------------------+---------+---------+-----------+-----------+------------+ | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX | +----------------+------------------+---------+---------+-----------+-----------+------------+ | 127.0.0.1:2379 | 8e9e05c52164694d | 3.3.9 | 20 kB | true | 4 | 18 | +----------------+------------------+---------+---------+-----------+-----------+------------+本地命令配置配置etcd服务镜像开机启动 默认镜像并不会开机启动，但往往我们需要服务开机自启，所以通过在/etc/profile中添加以下内容来实现开机启动etcd容器# etcd docker start etcd_test为命令设置别名 因为etcdctl命令在容器内部，每次想要执行都要进到容器里面执行或者使用docker exec etcd_test etcdctl。这样太过于麻烦，我们可以通过别名，简化执行etcdc…

Ubuntu Bash环境变量加载详情
type: item
date: 2021-09-24T18:02:00+08:00
description: Ubuntu Bash环境变量加载详情配置文件1、/etc/environment面对系统的环境，尽量减少对该文件的修改系统配置加载的顺序（相同变量去取后加载的）/etc/profile -> /etc/environment -> ...2、/etc/profile面对系统用户的环境变量，每一次登录时载入/etc/profile.d等配置文件会在/etc/profile 中使用一个for循环语句来调用这些脚本3、~/.bash_profile每个用户都可使用该文件输入专用于自己使用的shell信息,当用户登录时,该文件仅仅执行一次!默认情况下，他设置一些环境变量，执行用户的.bashrc文件，建议使用~/.profile去代替~/.bash_profile4、~/.bash_login登入shell会被加载，建议不使用bash_login5、~/.profile在Debian中使用.profile文件代 替.bash_profile文件。.profile(由Bourne Shell和Korn Shell使用)和.login(由C Shell使用)两个文件是.bash_profile的同义词，目的是为了兼容其它Shell。在Debian中使用.profile文件代 替.bash_profile文件，提倡删除本地~/.bash_profile和~/.bash_login，去使用~/.profile 。6、~/.bashrc该文件包含专用于你的bash shell的bash信息,当登录时以及每次打开新的shell时,该文件被读取.7、/etc/bashrc 或者 /etc/bash.bashrc为每一个运行bash shell的用户执行此文件.当bash shell被打开时,该文件被读取.8、~/.bash_logout当每次退出系统(退出bash shell)时,执行该文件.bash配置文件加载顺序交互登录shell直接通过终端输入账号密码登录使用“su - UserName”切换的用户使用bash --login 登录配置加载顺序（并不代表文件执行顺序，相同变量取后者 ）：/etc/bash.bashrc--> /etc/profile--> ~/.bashrc--> ~/.profile--> ~/.bash_logout 非交互登录shell使用bash --login -c "echo 123"等命令执行shell配置加载顺序：/etc/profile--> ~/.profile 交付非登录shell使用Ctrl + Alt + T 呼出的终端使用bash打开的交互式终端配置载入顺序：/etc/bash.bashrc--> ~/.bashrc非交互非登录shell只使用原有系统配置

国内安装k8s 三马车 kubectl kubelet kubeadm
type: item
date: 2021-09-05T17:11:00+08:00
description: [scode type="blue"]Ubuntu 版本是 20.04 ，用的是树莓派R4B，记录一下自己实际安装过程的操作步骤。[/scode]安装 docker安装所需的软件apt-get updateapt-get install -y apt-transport-https gnupg-agent software-properties-common添加阿里云安装源的密钥curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -添加阿里云安装源add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"安装最新版 docker engineapt updateapt install docker-ce安装 k8s添加阿里云安装源curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add - cat <<EOF > /etc/apt/sources.list.d/kubernetes.list deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main EOF添加安装源密钥gpg --keyserver keyserver.ubuntu.com --recv-keys BA07F4FBgpg --export --armor BA07F4FB | sudo apt-key add -安装三驾马车apt update && \ apt install -y kubelet kubeadm kubectl && \ apt-mark hold kubelet kubeadm kubectl关闭 swap临时关闭swapoff -a 永久关闭，/etc/fstab 中注释掉 swapfile 那一行#/swapfile none swap sw 0 0配置 docker添加 docker 配置 /etc/docker/daemon.json{ "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" }, "storage-driver": "overlay2", "registry-mirrors": ["docker镜像仓库国内加速"] }重启 dockerservice docker restart其他安装与配置如果用到 nas 挂载，需要安装 nfs-commonapt-get install nfs-common启用 kubectl 命令自动完成kubectl completion bash >/etc/bash_completion.d/kubectl参考资料：Ubuntu 国内安装 kubernetes

Ubuntu 自建本地apt源
type: item
date: 2021-09-03T14:47:57+08:00
description: [scode type="blue"]本篇为自建本地apt源类笔记，便于日后记忆[/scode]Operation自建源操作，需要准备好想要放在源中的包，然后执行以下操作mkdir /var/debs cp [源中的包] /var/debs cd /var dpkg-scanpackages debs/ | gzip >debs/Packages.gz echo 'deb [trusted=yes] file:///var debs/' >> /etc/apt/sources.list apt updateSomething需要注意，每次往本地源中加包后，想要update，必需先执行下dpkg-scanpackages debs/ | gzip >debs/Packages.gz

Ubuntu 升级 Cmake
type: item
date: 2021-07-29T14:24:00+08:00
description: 卸载当前旧版本的cmake通过下面命令查看当前的cmake版本cmake --version若版本较旧，执行apt remove 卸载旧版的cmake若当前系统无cmake，可跳过这一步sudo apt remove cmake下载cmakecmake官网：https://cmake.org/download/sudo apt-get install -y build-essential libssl-dev wget https://github.com/Kitware/CMake/releases/download/v3.19.2/cmake-3.19.2.tar.gz tar -zxvf cmake-3.19.2.tar.gz配置cmakecd cmake-3.19.2/ ./bootstrap然后编译安装：make sudo make install hash -r这样就ok了，检查一下cmake的版本：cmake --version可以看到cmake版本为3.19.2

内网穿透之FRP
type: item
date: 2021-07-07T22:36:00+08:00
description: [scode type="blue"] FRP是一个专注于内网穿透的高性能的反向代理应用，支持 TCP、UDP、HTTP、HTTPS 等多种协议。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。[/scode]前言因为公司属于良心型公司，几乎不加班。于是乎，不爱加班的我天天回家便各种[font color="#FFF0F5"]躺平[/font]。但是出于程序猿的自我危机感，还是决定回家后稍微蹦跶下吧。其实早在毕业前就想蹦跶了，但是因为写（~比~）毕（~较~）设（~懒~）所以没行动起来。至于为何会自己在家捣鼓起FRP，这就需要去问我[font color="#4169E1"]精致的广东男孩同事甲[/font]具体起因是因为我的title是云计算工程师，然后又想折腾点东西，便选择了折腾Cloud比较常用的管理云平台中多个主机上的容器化的应用的工具 -- k8s。因为部署k8s我需要linux系统，就装了台Ubuntu 20.04虚拟机；因为虚拟机所在宿主机不好用，便配置了虚拟机ssh环境和mac上的远程终端工具Termius，让我可以在mac上操作虚拟机；因为我想在公司使用mac能ssh处在家中内网环境的虚拟机，便要做VPN代理或者内网穿透；因为甲建议内网穿透或者找收费内网穿透服务，那肯定自己做内网穿透啊，于是甲给我推荐了FRP ~_~。为什么会是FRP通过在具有公网 IP 的节点上部署 frp 服务端，可以轻松地将内网服务穿透到公网，同时提供诸多专业的功能特性，这包括：客户端服务端通信支持 TCP、KCP 以及 Websocket 等多种协议。采用 TCP 连接流式复用，在单个连接间承载更多请求，节省连接建立时间。代理组间的负载均衡。端口复用，多个服务通过同一个服务端端口暴露。多个原生支持的客户端插件（静态文件查看，HTTP、SOCK5 代理等），便于独立使用 frp 客户端完成某些工作。高度扩展性的服务端插件系统，方便结合自身需求进行功能扩展。服务端和客户端 UI 页面。以上内容来自FRP官方文档简介，经过整个部署过程和使用体验，frp确实具有这些功能特性，同时最重要的特性便是部署是真的简单，甚至可以说是无脑，具体见下文。开始部署FRP根据官网教程去github release页面下载了最新版本的linux amd64 二进制文件。下载后便是解压了，然后将解压的文件夹拷入阿里云公网服务器（xxx.xxx.xxx.xxx）和内网虚拟机（192.168.3.54）内了。scp -r frp_0.37.0_linux_amd64/ hh@192.168.3.54:/home/hh/ scp -r frp_0.37.0_linux_amd64/ root@xxx.xxx.xxx.xxx:/root/然后ssh进入公网服务器内，将刚拷入的frp_0.37.0_linux_amd64的文件夹中内frpc相关文件删除，因为frpc为客服端文件，也就是我们虚拟机该跑的东西。cd /root/frp_0.37.0_linux_amd64 rm -rf frpc* cd systemd rm -rf frpc*删除公网服务器内多余的frp文件后，配置frpc.ini，设置了 frp 服务器用户接收客户端连接的端口，内容如下：[common] bind_port = 7000开始配置systemd 服务。使用systemd的原因是为了服务可以常驻在服务器内，开机后服务也会自动启动。首先建需要用到的配置和脚本命令软链接到它该在的地方，注意软链接时必须用绝对路径。cd /root/frp_0.37.0_linux_amd64 ln -s /root/frp_0.37.0_linux_amd64/frps /usr/bin/frps sudo mkdir -p /etc/frp/ ln -s /root/frp_0.37.0_linux_amd64/frps.ini /etc/frp/frps.ini ln -s /root/frp_0.37.0_linux_amd64/systemd/frps.service /lib/systemd/system/frps.service软链接都做完后，便可以载入systemd服务设置开机自启，并启动它了。sudo systemctl daemon-reload sudo systemctl enable frps.service sudo systemctl start frps.service到这里公网服务器部分的frp便部署好了。然后便是按照上面操作配置内网虚拟机的frpc。# 删除grps cd /home/hh/frp_0.37.0_linux_amd64 rm -rf frps*…