MoreRSS

site iconDerobukal修改

博客名:御坂研究所,一个偏软件开发和技术实践的博客。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

Derobukal的 RSS 预览

Kotlin与Java对照手册

2025-04-24 22:21:27

Generated By AI

📗 1. 基本类型

类型 Kotlin 写法 Java 写法 简要说明
数字 Int, Long, Float, Double, Short, Byte int, long, float, double, short, byte Kotlin 数值类型映射到相应的原生/包装类型。
布尔 Boolean boolean 只能取 true/false,与数字不互通。
字符 Char char 单个 Unicode 字符,支持转义序列。
字符串 String String 不可变;支持多行文本块 """..."""
数组 Array<T>, IntArray T[] 提供原始类型专用数组如 IntArrayByteArray
无符号整型 UInt, ULong, UShort, UByte 编译时检查范围,运行时越界抛 IllegalArgumentException

📘 2. 语法对照

功能 Java 写法 Kotlin 写法 简要说明
变量定义 int x = 10; final String name = "Tom"; var x = 10 val name = "Tom" var 可变,val 只读;类型由编译器推断。
类 + 构造 public class P { P(String n) { ... } } class P(val name: String) 主构造中声明属性,自动生成字段 & 访问器。
数据类 手动写字段/构造/equals/toString data class User(val id: Int, val n: String) data 自动生成常用方法 & 解构组件。
函数定义 public int sum(int a, int b) { return a + b; } fun sum(a: Int, b: Int) = a + b 表达式函数可省略大括号和 return
空安全 if (s != null) len = s.length(); else len = 0; val len = s?.length ?: 0 String? 可空,?.?: 插入编译期空检查。
分支匹配 switch(x) { case 1: ... } when(x) { 1 -> ...; else -> ... } when 是表达式,支持范围 & 任意对象比较。
循环 & 集合 for(int i=0;i<10;i++)``list.stream().filter() for(i in 0 until 10)``list.filter{} 0 until 生成 IntRange;集合链式调用基于扩展函数。
单例 class S { private static S i=new S(); … } object S { fun foo() {} } object 编译时生成线程安全单例,无需额外样板。

✨ 3. 独有亮点

特性 示例 简要说明
默认 & 命名参数 fun g(msg: String = "Hi", name: String = "You") g(name="Tom") 编译器生成默认方法,命名参数避免重载歧义。
扩展函数 fun String.ex() = uppercase() 编译后为静态方法,第一个参数是接收者,调用如成员方法。
解构声明 val (x, y) = Point(1, 2) data class 自动生成 componentN(),一行取多值。
密封类 sealed class R; data class Ok(val d: String): R(); object Err: R() 限定子类范围,when 可做穷尽检查。
内联函数 inline fun <T> m(b: ()->T): T { … } 在调用处展开函数体,减少高阶函数的运行时开销。
集合构造器 listOf(1, 2), mutableListOf("A"), mapOf("a" to 1) 内建集合工厂函数,语法简洁;to 表示键值对。
数组构造器 arrayOf(1, 2), intArrayOf(1, 2) 支持泛型与原始类型数组,避免装箱。
表达式返回值 val max = if (a > b) a else b val result = try { … } catch { … } ifwhentry 都是表达式,可直接赋值。
区间语法 & 步进 for (i in 1..5), for (j in 1 until 5 step 2) .. 表闭区间,until 表半开,step 控制步长。
字符串模板 "Hello, $name" "Length: ${s.length}" $变量 可直接拼接,复杂表达式用 ${}
Lambda 尾随语法 list.filter { it > 0 }.map { it * 2 } 大括号可直接跟随函数调用,链式语法自然、简洁。

📚 4. 常用标准库函数

函数 用法示例 简要说明
let user?.let { print(it.name) } 非空时执行块,it 引用原对象。
apply User().apply { age = 18 } 在对象上执行块并返回该对象,常用于初始化。
also list.also { println("init") } 执行副作用并返回对象,常用于日志 / 调试。
run val r = run { compute(); result } 无接收者的作用域块,返回最后一行结果。
with with(cfg) { load(); validate() } 对象上下文块,this 指向接收者,返回结果。
takeIf str.takeIf { it.isNotBlank() } 条件为真返回对象,否则返回 null
sequence sequenceOf(1,2,3).map { … } 惰性集合处理,适合大规模数据管道。

🧩 5. 类型系统对比

功能 Java 写法 Kotlin 写法 简要说明
泛型 List<String> List<String> 支持协变 / 逆变(out / in)和 reified 泛型函数。
类型别名 typealias Name = String 简化复杂类型声明。
枚举类 enum Color { RED, GREEN } enum class Color { RED, GREEN } 支持在枚举中定义属性 & 方法。
内联类 @JvmInline value class USD(val amount: Int) 编译时包装或展开,零开销封装。

🔍 6. 类型检测与转换

功能 Java 写法 Kotlin 写法 简要说明
类型检查 if (obj instanceof String) if (obj is String) is 后自动智能转换,无需显式强转。
安全转换 (String) obj obj as String / obj as? String as? 安全转换失败返回 null
基本转换 Integer.parseInt(str) str.toInt(), toDouble(), toLong() 通过扩展函数提供常见类型转换。

🔄 7. 控制流程 & 异常

功能 Java 写法 Kotlin 写法 简要说明
条件 & 循环 if, switch, for, while, do-while if, when, for, while, do-while when 可做表达式,替代 switch
返回 & 跳转 return, break, continue, throw 同 Java 支持在 lambda 中局部返回,如 return@label
异常处理 try-catch-finally, checked exception try-catch-finally,无 checked exception Kotlin 不区分受检异常,简化错误处理。

📦 8. 包与导入

功能 Java 写法 Kotlin 写法 简要说明
包声明 package com.example; package com.example 不需要分号。
导入 import java.util.List; import java.util.List 支持导入顶层函数和属性。
别名导入 import foo.Bar as Baz 解决命名冲突或简化引用。

⚙️ 9. 面向对象相关

功能 Java 写法 Kotlin 写法 简要说明
接口默认实现 default void f() {} 接口中可直接写方法体 接口内方法可有实现,无需关键字。
抽象类 abstract class Shape { … } abstract class Shape { … } 抽象成员不需再加 abstract 前缀。
继承 & 覆写 class A extends B { @Override … } class A : B() { override fun … } : 表示继承,override 必显式标注。
可见性修饰符 public/protected/private public/protected/private/internal internal 表示同模块内可见。
内部类 class Outer { class Inner {} } class Outer { inner class Inner {} } 默认是静态嵌套,加 inner 变为非静态内部类。

🧵 10. 协程 vs 多线程

场景 Java 写法(线程/异步) Kotlin 写法(协程) 简要说明
启动任务 new Thread(() -> work()).start(); GlobalScope.launch { work() } 协程更轻量、省资源,适合大规模并发。
异步返回值 Future<Integer> f = exec.submit(...); val result = async { compute() }.await() 内建 async/await,语义更清晰。
延迟执行 Thread.sleep(1000) delay(1000) 非阻塞挂起,不占用线程。
结构化并发 手动管理线程池和生命周期 coroutineScope { … } 协程作用域自动管理生命周期,避免泄漏。

📦 11. 集合操作对比

功能 Java 写法(Stream) Kotlin 写法(扩展函数) 简要说明
过滤 list.stream().filter(x -> x > 0).collect(...) list.filter { it > 0 } 语法简洁,链式调用更直观。
映射 list.stream().map(x -> x * 2).collect(...) list.map { it * 2 } Lambda 简洁,扩展函数无额外依赖。
分组 Collectors.groupingBy(...) list.groupBy { it.key } 直接返回 Map<K, List<V>>,更易读。
排序 list.sort(Comparator.comparing(...)) list.sortedBy { it.prop } 函数式排序,链式可读性好。
聚合 reduce, sum, collect reduce, sumOf, fold 内建多种聚合函数,常用时无需额外导入。

持续更新中…

参考:

https://book.kotlincn.net/text/d-basics.html

利用whisper为视频自动生成字幕

2025-01-02 18:37:24

whisper是一个由openai开发的通用语言识别模型,我们可以使用它来为视频自动创建字幕。

环境安装

为了加速,我们需要使用GPU来进行计算,因此需要安装基于CUDA的pytorch。首先我们需要安装Miniconda,这里安装的时候直接点击下一步即可。

安装完毕之后,我们需要创建一个新的环境,这里我们创建一个名为whisper的环境:

conda create -n whisper python=3.8conda activate whisper

1. 安装CUDA

安装好了Miniconda之后,我们需要安装CUDA,执行nvidia-smi

$ nvidia-smiThu Jan  2 11:49:53 2025+-----------------------------------------------------------------------------------------+| NVIDIA-SMI 560.94                 Driver Version: 560.94         CUDA Version: 12.6     ||-----------------------------------------+------------------------+----------------------+| GPU  Name                  Driver-Model | Bus-Id          Disp.A | Volatile Uncorr. ECC || Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. ||                                         |                        |               MIG M. ||=========================================+========================+======================||   0  NVIDIA GeForce GTX 1060 6GB  WDDM  |   00000000:01:00.0  On |                  N/A ||  0%   39C    P8             10W /  120W |     505MiB /   6144MiB |      0%      Default ||                                         |                        |                  N/A |+-----------------------------------------+------------------------+----------------------+

通过这个命令可以看到Driver Version: 560.94CUDA Version: 12.6,因此我们需要安装12.6版本的CUDA,更加详细的版本对照表在这里。在安装的时候可以选择自定义安装选项,一般来说只要勾选CUDA下的 Development和Runtime即可。

安装完毕之后执行命令nvcc -V查看CUDA版本:

$ nvcc -Vnvcc: NVIDIA (R) Cuda compiler driverCopyright (c) 2005-2024 NVIDIA CorporationBuilt on Thu_Sep_12_02:55:00_Pacific_Daylight_Time_2024Cuda compilation tools, release 12.6, V12.6.77Build cuda_12.6.r12.6/compiler.34841621_0

2. 安装cuDNN

根据自己下载的CUDA来选择对应版本的cuDNN,下载地址在这里。下载完毕之后解压到CUDA的安装目录下,一般来说是C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA{版本号},如果有重名的文件直接替换即可。

之后进入extras\demo_suite目录,执行如下命令:

bandwidthTest.exedeviceQuery.exe

如果出现了PASS的字样,说明安装成功。

3. 安装pytorch

切换到我们之前创建的whisper环境,使用如下命令安装CUDA版本的pytorch:

pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118

安装之后执行python命令进入python环境,执行如下代码:

1
2
import torch
torch.cuda.is_available()

如果显示True则说明CUDA版本的pytorch安装成功。

4. 安装whisper

切换到我们之前创建的whisper环境,执行如下命令安装whisper:

pip install -U openai-whisperpip install setuptools-rust

安装完毕之后执行如下命令就可以使用whisper了:

whisper 'C:/Users/raymond/Desktop/voice.aac' --language zh --model turbo

如上命令表示对C:/Users/raymond/Desktop/voice.aac文件进行中文语言的识别,使用turbo模型。第一次执行该命令会下载模型文件,模型文件较大,下载时请确保网络通畅。执行结果如下

[00:00.000 --> 00:03.060] 提到肉毒毒素[00:03.060 --> 00:04.540] 你会想到什么[00:04.540 --> 00:10.820] 你真的了解它吗[00:10.820 --> 00:12.540] 2017年[00:12.540 --> 00:14.180] 肉毒毒素以万能药标签[00:14.180 --> 00:15.500] 登上时代周刊方面[00:15.500 --> 00:17.280] 目前它在全球[00:17.280 --> 00:18.960] 已被应用于几十种适应症[00:18.960 --> 00:20.560] 仅在2019年[00:20.560 --> 00:23.000] 接受注射的就已超过620万例[00:23.000 --> 00:24.880] 但不要忘了[00:24.880 --> 00:26.780] 肉毒毒素更是一种神经毒素[00:26.780 --> 00:29.000] 还曾被当作生化武器使用... 省略 ...

生成字幕

我们可以使用ffmpeg将音频从视频中提取出来,然后使用whisper生成字幕,最后使用ffmpeg将字幕添加到视频中。

使用如下命令提取音频:

ffmpeg -i input.mp4 -vn -acodec copy output.aac

然后使用whisper生成字幕,我们先在pycharm中创建一个test-whisper项目,并且把python解释器设置为Miniconda创建的whisper环境。创建一个main.py文件,写入如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import whisper
from whisper.utils import get_writer

root = 'E:/'

# 使用turbo模型
model = whisper.load_model('turbo')
prompt = '如果使用了中文,请使用简体中文来表示文本内容'

# 选择声音文件,识别中文,并且打印详细信息
result = model.transcribe(root + 'output.aac', language='zh', initial_prompt=prompt, verbose=True)
print(result['text'])

# 保存字幕文件
writer = get_writer('srt', root)
writer(result, 'output.srt')

如上代码表示使用turbo模型,识别中文,打印详细信息,并且保存字幕文件。执行完毕之后我们可以在E:/目录下看到生成的字幕文件。

最后我们使用ffmpeg将字幕添加到视频中:

ffmpeg -i input.mp4 -i output.srt -c:s mov_text -c:v copy -c:a copy output.mp4

之后我们在播放这个视频的时候就会有字幕了。

参考

video-subtitle-generator
基于Anaconda的pytorch-cuda
CUDA与cuDNN的安装与配置
ffmpeg视频合并、格式转换、截图

ffmpeg笔记

2024-06-18 18:13:25

合并一个文件夹内的所有视频
1
2
3
4
5
find *.mp4 | sed 's:\ :\\\ :g'| sed 's/^/file /' > fl.txt
ffmpeg -f concat -i fl.txt -c copy output.mp4
// 忽略错误信息
ffmpeg -safe 0 -f concat -i fl.txt -c copy output.mp4
rm fl.txt

参考资源

视频压缩
1
2
3
4
5
6
// 视频使用h.264编码,声音使用aac编码
ffmpeg -i input.mp4 -vcodec h264 -acodec aac output.mp4
// 视频使用h.265编码,压缩到更小文档
ffmpeg -i input.mp4 -vcodec libx265 -crf 28 output.mp4
// 视频使用h.264编码,保留更好的质量
ffmpeg -i input.mp4 -vcodec libx264 -crf 20 output.mp4

crf越小,视频质量越高;crf越大,视频文件越小

编码参数也可以简写,从-vcodec-acodec改为-c:v-c:a

1
2
3
ffmpeg -i input.mp4 -c:v libx264 -crf 23 output.mp4
ffmpeg -i input.mp4 -c:v libx265 -crf 28 output.mp4
ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 31 -b:v 0 output.mkv

参考资源

其中AVC/H264HEVC/H265都是软件编码,速度很慢。可以选择英伟达的硬件编码:hevc_nvenc与h264_nvenc,它们使用硬件加速,速度很快。

参考资源

使用英伟达显卡进行编码:

1
ffmpeg -i video.mp4 -c:v hevc_nvenc -crf 28 output.mp4

将视频从H.264转码到H.265,花了55分钟,视频体积从3.8GB减小到430MB,效果立竿见影。转码命令:ffmpeg -i 1.mp4 -c:v libx265 -vtag hvc1 -c:a copy 1_hevc.mp4

在win10可以用scoop安装ffmpeg,更新Windows上面通过scoop安装的所有程序
scoop list | foreach { scoop update $_.Name }

将视频以同样的编码,按照指定时间进行裁剪

1
ffmpeg -ss 00:05 -to 08:53.500 -i ./input.mp4 -c copy video.mp4

利用ffmpeg快速剪辑视频

1
ffmpeg -ss 07:18 -to 13:45 -i ./aaa.mkv -c copy bbb.mkv
  • -ss表示开始时间
  • -to表示结束时间
  • -i是输入文档
  • -c表示使用被剪辑视频一样的编码
  • bbb是输出文档的名称

合并视频和声音,视频使用原始编码,声音改为aac编码

1
ffmpeg -i 1.mp4 -i 1.opus -c:v copy -c:a aac output.mp4

将PNG格式图片转为JPG格式图片

1
ffmpeg -i image.png -preset ultrafast image.jpg

修改图片的尺寸

1
2
ffmpeg -i image.jpeg -vf scale=413:626 2寸.jpeg
ffmpeg -i image.jpeg -vf scale=390:567 1寸.jpeg

将一个音频重复10次

1
ffmpeg -stream_loop 10 -i input.m4a -c copy output.m4a

如何参与Apache顶级开源项目

2024-01-24 19:27:14

我们在日常工作中经常会使用到很多的开源项目,开源也是一个在工作和学习中都离不开的内容。一般来说,开源项目可以选择直接开源,也可以选择捐赠给某些基金会,例如Linux FoundationCNCFASF等等。以ASF为例,如果一个项目想要成为顶级项目,则需要先通过孵化器孵化,孵化结束毕业才能成为顶级项目。最近我因为一些原因参与了云原生网关APISIX开源项目,这里做一下介绍。

搭建环境

首先我们需要下载源代码并且构建开发流程,根据官网介绍,我们把项目代码fork到自己的仓库并clone到本地,随后在本地仓库中将原始的项目设置为上游upstream,之后新建分支进行开发即可

~ git clone [email protected]:RitterHou/apisix.git~ cd apisix~ git remote -v~ git remote add upstream https://github.com/apache/apisix.git~ git config --global user.name "derobukal"~ git config --global user.email "[email protected]"~ git fetch upstream~ git checkout master~ git rebase upstream/master~ git push origin master~ git checkout -b issue-10484~ cd ..

根据官方教程,我们还需要安装APISIX的开发环境注1

~ export https_proxy="http://192.168.65.100:7890"~ export http_proxy="http://192.168.65.100:7890"~ wget https://raw.githubusercontent.com/apache/apisix/master/utils/install-dependencies.sh~ APISIX_RUNTIME='1.1.1' bash install-dependencies.sh~ cd apisix~ make deps~ sudo mkdir /usr/local/apisix~ sudo mkdir /usr/local/apisix/logs~ sudo chown raymond:raymond /usr/local/apisix -R~ sudo make install

以及安装和启动etcd

~ ETCD_VERSION='3.4.18' wget https://github.com/etcd-io/etcd/releases/download/v${ETCD_VERSION}/etcd-v${ETCD_VERSION}-linux-amd64.tar.gz && tar -xvf etcd-v${ETCD_VERSION}-linux-amd64.tar.gz && cd etcd-v${ETCD_VERSION}-linux-amd64 && sudo cp -a etcd etcdctl /usr/bin/~ cd ..~ etcd

最简单的PR

搭建好了环境之后,就可以修改代码并提交PR了。一般来说开源项目都会有多种类型的改动,以apisix为例,它限制了PR可以为固定的几种类型

featfixdocsstylerefactorperftestbuildcichorerevertchange

包含了文档修改、新功能、bug修复等等,我们选择比较简单的文档修改作为第一个PR。我在使用APISIX的过程中,发现它证书相关的文档中存在一个错误

在上图中,这里的地址不应该是/hello而应该是/get,因此我们可以在本地仓库新建一个分支并对这个问题作出修改。修改后我们将这次改动提交(为了使提交更加的清晰和安全,建议合并commit并对commit进行签名)并push到我们自己的远程仓库,随后在GitHub上面创建一个针对原始仓库的Pull Request。一般项目在创建一个PR的时候都会有模板信息,照着模板信息进行填写即可,填写完毕就可以提交PR并等待项目的成员进行处理了

修复issue中的问题

在APISIX中有着很多的ISSUE

我们可以关注这些ISSUE看有没有自己能解决的问题。一般来说,带有good first issue标签的都是比较简单并且适合新人的,我们可以优先从这些issue中寻找自己能解决的问题

在确定了issue之后,我们可以请求管理员将这个issue分配给自己,防止别人也会去解决这个问题从而浪费时间。当然,有的时候issue即使已经被分配给别人了,但是如果他一直没有解决这个问题,我们仍然可以请求将这个issue分配给自己

搭建测试环境

对于issue-10484,因为涉及到代码更改,因此需要执行测试。APISIX使用了test-nginx框架来执行测试,官方有关于如何进行测试的介绍

我们需要安装测试框架注2

sudo cpan Test::Nginx

并下载依赖测试模块

➜  apisix git:(issue-10484) git clone https://github.com/api7/test-toolkit/ t/toolkit

修改完代码之后可以执行相关的测试

~ PATH=/usr/local/openresty/nginx/sbin:/usr/bin PERL5LIB=.:$PERL5LIB FLUSH_ETCD=1 prove -Itest-nginx/lib -r t/admin/ssl2.tt/admin/ssl2.t .. ok    All tests successful.Files=1, Tests=52, 11 wallclock secs ( 0.06 usr  0.01 sys +  3.61 cusr  1.05 csys =  4.73 CPU)Result: PASS

如果测试没有问题就可以提交PR了。

通过CI的测试

apisix使用GitHub的workflow进行CI执行测试,以redhat-ci.yaml为例,它会在多个平台上执行多个文件夹内的测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
jobs:
test_apisix:
name: run ci on redhat ubi
runs-on: ubuntu-20.04
timeout-minutes: 90
strategy:
fail-fast: false
matrix:
events_module:
- lua-resty-worker-events
- lua-resty-events
test_dir:
- t/plugin/[a-k]*
- t/plugin/[l-z]*
- t/admin t/cli t/config-center-yaml t/control t/core t/debug t/discovery t/error_page t/misc
- t/node t/pubsub t/router t/script t/secret t/stream-node t/utils t/xds-library

如上所示,GitHub action中的matrix默认会对其下面的的多个选项进行合并,例如redhat-ci.yamlevents_moduletest_dir组合起来就会构成8个执行脚本

lua-resty-worker-events t/plugin/[a-k]*lua-resty-worker-events t/plugin/[l-z]*lua-resty-worker-events t/admin t/cli t/config-center-yaml t/control t/core t/debug t/discovery t/error_page t/misclua-resty-worker-events t/node t/pubsub t/router t/script t/secret t/stream-node t/utils t/xds-librarylua-resty-events t/plugin/[a-k]*lua-resty-events t/plugin/[l-z]*lua-resty-events t/admin t/cli t/config-center-yaml t/control t/core t/debug t/discovery t/error_page t/misclua-resty-events t/node t/pubsub t/router t/script t/secret t/stream-node t/utils t/xds-library

github的CI会对这些所有的任务执行测试。如果测试执行失败了,需要重点关注失败的日志,并在本地调试直到可以通过测试。如果遇到数据不对的问题,可以重新对数据进行初始化

apisix quit && apisix init && apisix init_etcd && apisix start

社区交流

在代码提交并创建了PR之后,我们可能会收到一些反馈,这时候我们就需要针对这些反馈作出回应。以#10771为例

我在提交了代码之后,管理员认为需要将aes_encrypt_pkeyaes_decrypt_pkey方法中的field字段去掉。我一开始在写代码的时候就发现这个字段去掉会导致数据加解密过程中ssldata的行为不一致,可能导致错误。不过管理员让我放心删,没问题,本着信任的态度我就把参数删除掉了

但是删除掉了之后测试却怎么也跑不过,我因为非常信任社区管理员也没有怀疑是因为ssldata逻辑不一致导致的,而是从其它地方入手进行排查。最终花了大量的时间经过了很多**的排查之后,发现其实就是因为ssldata的行为逻辑不一致导致的。我随后询问了管理员,并且把field参数加了回来

field参数加回来之后,所有的test cases就都能跑过了

所有测试用例通过,一段时间之后PR被review没有问题,就会被合并到master分支了

参考

Revolution OS
S04E00-吴晟:开源项目进入 Apache 孵化器意味着什么
Apache 是如何运作的?
新手如何快速参与开源项目
如何从小白成长为 Apache Committer?

  1. 在执行install-dependencies.sh脚本的时候,会下载golang的依赖,比如gRPC-Go,这里需要保证网络能够顺畅访问golang的官方仓库。

  2. 为了保证test-nginx正常安装,需要网络顺畅,能够正常访问相关资源。

使用frp实现内网ssh穿透

2024-01-06 06:00:22

最近需要远程访问一台虚拟机内的Linux,因为虚拟机没有公网IP,因此选择使用frp转发ssh流量的方式来实现远程访问。首先访问frp的release页面并根据操作系统和CPU下载相应的版本,之后解压得到frpcfrps文件。

frps是服务端版本,它需要部署在一台拥有公网IP的主机上,它的配置frps.ini如下

[common]bind_port = 10625token = y9XBLEu2ymW1s5N3W7OuDPhUG4IohVmQ

其中bind_port代表了它所监听的端口号,而token则是客户端连接时需要用到的验证信息。

frpc是客户端版本,它的配置frpc.ini如下

[common]server_addr = 100.26.21.285server_port = 10625authentication_method = token token = y9XBLEu2ymW1s5N3W7OuDPhUG4IohVmQ[ssh]type = tcplocal_ip = 127.0.0.1 local_port = 22remote_port = 10626

common代表通用配置,它包含了4个配置

  1. 作为服务端的远程主机的公网IP
  2. frps在远程主机所监听的端口号
  3. 验证方式,这里是通过token进行验证
  4. 验证的token值

ssh代表了进行ssh转发的设置,它的含义如下

  1. 转发的方式,这里是tcp协议
  2. 本地主机的地址,因为访问的就是当前机器,设为127.0.0.1
  3. 本地ssh服务所监听的端口,默认端口22
  4. 远程(服务端)进行ssh流量转发时所监听的端口

有了如上的配置之后,我们可以在远程主机上使用该配置启动frps

./frps -c ./frps.ini

需要注意远程主机的10625和10626端口需要关闭防火墙的设置,以保证可以通过外部进行访问。之后启用本地的客户端

./frpc -c ./frpc.ini

本地机器如果没有安装ssh服务,则需要先安装ssh服务。启动了服务端和客户端之后,可以在服务端看到客户端成功连接的日志信息,之后通过

ssh [email protected] -p 10626

命令就可以成功访问虚拟机内Linux的ssh服务了,整个网络流程大致如下

  1. 客户端提前通过服务端的10625端口已经创建好了客户端与服务端的连接
  2. 用户访问远程主机frps的10626端口
  3. 远程主机上的frps通过与客户端的连接将流量发给frpc
  4. frpc将流量转发给本地的ssh服务
  5. 用户最终可以操作本地的ssh

参考

使用frp端口映射实现内网穿透(SSH、HTTP服务)

安装并使用zsh

2023-10-19 00:18:09

首先我们安装zsh,并切换默认的shell为zsh,之后重启进入zsh

sudo apt-get install zshchsh -s /bin/zshsudo shutdown -r now

之后我们安装oh-my-zsh,因为网络的原因所以设置了代理

wget -e https_proxy=192.168.65.100:7890 https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.shchmod +x install.sh./install.sh

然后再安装zsh命令自动补全插件zsh-autosuggestions

git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions

之后编辑~/.zshrc文件,修改ZSH_THEME="simple",并且在plugins里面添加zsh-autosuggestions配置

ZSH_THEME="simple"plugins=(git zsh-autosuggestions)