Nushell 使用笔记

这里查看官方中文文档.

这份笔记基本上只是官方文档的摘抄.

安装

对于 Windows

1
winget install nushell

对于 Ubuntu

1
npm install -g nushell

(apt软件包管理器无法安装该软件, npm属于跨平台安装)

另外, nushell 使用 rust 语言开发, 使用 rustup 来安装是个好选择.

基础知识

  • 在 Nushell 中, >不再意味重定向, 而是意味着大于号. 要取而代之的话, 应该用|将命令输出导出到其他地方

    1
    2
    3
    4
    # not this
    echo "hello" > output.txt
    # but this
    "hello" | save output.txt
  • 在 Nushell 中, 许多命令的输出变成了表, 可以用以下关键词从表中提取数据:

    • select - 创建一个只包括指定列的新表
    • get - 以列表形式返回指定列内的值
  • 如果一个管道过长, 可以通过子表达式使用多行表示

    1
    2
    3
    4
    5
    (
    "01/22/2021" |
    parse "{month}/{day}/{year}" |
    get year
    )

管道 常用用法

可以用help commands查看命令说明文档

  • 查看名字中包含某字符串的进程
    1
    2
    3
    4
    5
    # win
    ps | where name =~ "nu"
    # linux
    ps aux | where name =~ "nu"
    # [process列举进程](ps) [所有用户, 包含用户信息, 包含无控制终端的](aux) [通过管道流向](|) [筛选查找](where) [name列](name) [包含](=~) [字符串nu]("nu")
  • 对获取的表格进行排序
    1
    2
    ls | sort-by size
    # size 可以为中任何一个列名
  • 只取其中几行的信息
    1
    ls | select name size
  • 只取前几行的信息
    1
    2
    ls | select name size | sort-by size | first 5
    # 按大小排序, 只显示前5大的文件的名称和体积

其他

看半天, 好像使用 Nu 之后, 除了看进程稍微方便一些, 其他地方没用到多少有趣功能…

相比起来, 同时装的另外一个项目: starship似乎更有用, 它能统一不同的shell的外观, 简单配置之后, 能显示 git 信息, 权限信息, 用户信息…

使用记录: 用 Baikal 部署 CalDev 时踩的坑

摘要

想在自己服务器上部署日历服务, 选了较为轻量的 Baikal. 部署过程遇到大量错误与困难, 多方求索最后解决.

第一次用 docker 的方式部署, 结果没做好数据持久化, 导致软件重启后, 之前的日程全部丢失.

第二次用普通方式部署, 遇到大量 nginx 的配置问题, 文件权限问题, php环境问题.

最后发现官方的部署教程是最正确的, 只是有一个路径与实际不符(差了3个字符). 终于部署完成

关键词: CalDAV; Baikal; docker 与数据持久化; ngnix 配置; PHP;

使用 docker 部署

从 .NET, 到 WPF, 以及 C#

印象

.NET 是纯正的面向对象程序构建方式, using xxx引入程序包类似于 C/C++ 的#include引入头文件, 但是引入过程更加像引入类: 通过点运算符, 你可以引入程序包的不同层级, 并且不必担心头文件和源文件之间的复杂包含关系.

.NET 把项目与项目之间的联动也以类似于对象关系的方式实现. 你可以在一个项目中”引入”另一个项目, 这将创建一种类似于类之间的依赖关系, 如果引入的项目生成的是可执行程序, 这相当于使用外部程序; 如果引入的项目生成的是类库, 这相当于使用动态链接库.

构建项目

参照VScode官方教程VS官方教程

最基础的, 需要选择 .NET Framework 的版本, 在这里下载需要的版本或者最新的版本. 如果是要打开运行已有的项目的话, 最好按照项目中记录的版本号, 选择下载对应的版本. 随着版本更新, .NET 的变化还是很大的.

使用 VScode 创建项目

使用 Visual Studio Code 来编写调试程序能更好地了解 .NET 项目组成原理. 注意是通用的 .NET 项目, 而不是 Windows 上专用的 WPF 项目.

想要开始的话: 至少要安装C# Dev Kit拓展, 它将提供自动构建项目的功能, 否则也可以通过 dotnet 命令行来进行构建项目, 引入项目等操作. 其次还可以安装 .NET 拓展包, 对编程有一定帮助. 自己用的时候安装了这几个:

.NET开发用插件

.NET 项目结构浅析

使用拓展提供的命令(.NET: New Project)构建好项目之后, 项目结构中需要理解的地方:

项目中一些文件的内容意义

如上图所示,已发布的输出包含以下文件:

  • HelloWorld.deps.json
    这是应用程序的运行时依赖项文件. 它定义运行应用所需的 .NET 组件和库(包括包含应用程序的动态链接库). 有关详细信息,请参阅 运行时配置文件.
  • HelloWorld.dll
    这是应用程序的依赖于框架的部署版本. 若要运行此动态链接库,请在命令提示符处输入 dotnet HelloWorld.dll. 运行应用的方法适用于安装了 .NET 运行时的任何平台.
  • HelloWorld.exe(HelloWorld 在 Linux 或 macOS 上).
    这是应用程序的依赖于框架的可执行文件版本. 该文件特定于操作系统.
  • HelloWorld.pdb(对于部署是可选的)
    这是调试符号文件. 无需与应用程序一起部署此文件,但应在调试应用程序的已发布版本时保存该文件.
  • HelloWorld.runtimeconfig.json
    这是应用程序的运行时配置文件. 它标识了您的应用程序是为哪个 .NET 版本构建和运行的. 还可以向其添加配置选项. 有关详细信息,请参阅 .NET 运行时配置设置.

值得注意: 发布类库时需要指定TargetFramework, 在xxx.csproj(xxx是项目名)中修改, 它决定了能使用这个类库的 .NET Framework 版本.

使用第三方库的时候, 就像使用非C++标准库一样, 需要把第三方类库”引入”项目(当然也可以在项目内新建一个类库, 引入到另一个类库). 在 Visual Studio Code 中, 操作流程大致如下:

添加类库以及引用的步骤

不难看出. .NET 软件框架的主要特征, 就是以.NET项目为基础单位, 每个项目单独编写和编译, 其主要产物可能是链接库(.dll)可执行程序(.exe). .NET 项目之间再相互引用, 组合而成一整个项目.

而 .NET Framework 则为全局的 .NET 项目提供了程序包, 例如System.IO程序包控制输入输出, System.Text.Json程序包提供Json相关功能… WPF 作为 .NET 类型的子集存在, 其主要特征就是提供了 System.Windows 程序包.

使用 VS 创建项目

如果是在 Visual Studio 2022 (或者其他版本), 创建 WPF 项目相当简单, 只需安装好负载(.NET桌面开发)要选好项目模板(WPF应用程序)就行.

如果是要创建供其他项目使用的类库的话, 选 WPF 类库.

选择项目模板

创建好项目后, 项目配置, 编译运行均为图形界面操作, 与C++项目基本一致, 不再赘述.

使用 NuGet 共享包

类似于 .NET 框架的包管理器.

目前好像直接用dotnet add package Newtonsoft.Xxxx就可以引入nuget.org的第三方包了. NuGet 的介绍见官方教程. 这里先不写.

在 VS 中, 我们可以直接通过 项目>管理 NuGet 程序包 来图形化管理第三方包.

我们还可以在nuget.org注册账号, 上传自己制作的包…

编写内容

参见官方教程

因为涉及到图形界面元素组织, 所以一般用 Visual Studio 进行编写.

窗口

WPF 应用使用 xaml 文件表示窗口, 以类似 xml 文件的形式编写界面元素信息. 通常来说, xaml 文件下还绑定着一个 .xaml.cs 文件, 其用以响应元素上发生的事件.

可以打开 VS 的工具箱窗口, 并选择 xaml 文件, 然后通过拖动元素的方式来新建元素, 再使用属性窗口来详细设定元素参数.

直接在可视化窗口中双击按钮等元素, 可以快速创建该元素的回调函数(正式运行时, 点击该元素会执行的函数), 也可以右键并跳转到改元素的对应函数, 不只是回调函数, 也可以设置其他的绑定内容.

C#语言高级功能

C# 提供了一些额外功能来帮助构建程序, 它们大多是对某些设计的简化, 十分有用. 适当了解对看懂别人的项目或者直接写项目都有帮助

委托 Delegate

参考C# 委托(Delegate) | 菜鸟教程.

在 C# 中,委托(Delegate) 是一种类型安全的函数指针,它允许将方法作为参数传递给其他方法。

C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。委托(Delegate) 是存有对某个方法的引用的一种引用类型变量,引用可在运行时被改变。

委托在 C# 中非常常见,用于事件处理、回调函数、LINQ 等操作。

所有的委托(Delegate)都派生自 System.Delegate 类。

我来一句话总结的话, 就是 类型安全的回调函数用法.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 声明委托的语法:
// public delegate <return type> <delegate-name> <parameter list>
// public delegate 返回类型 委托名 (参数类型 参数名, ...);

// 定义一个 (cmd, rcv) -> bool 类型的委托
public delegate bool SqlCmd(string cmd, List<string> rcv);

// 假设别处已经书写了这么一个 "回调函数"
public bool SqlGetFirstLine(string cmd, List<string> rcv)
{
// ... 发送sql命令, 并保存收到的第一行数据到 rcv
return ret;
}
public bool SqlGetAllLine(string cmd, List<string> rcv)
{
for(...)
{
// ... 发送sql命令, 并保存收到的第一行数据到 rcv
}
return ret;
}

// 实例化和使用
public static Main()
{
// 将回调函数作为"委托"对象的初始化参数
SqlCmd SqlGetDeleget = new SqlCmd(SqlGetFirstLine)
// 执行委托
List<string> lines;
SqlGetDeleget("select * where name equals ker0123", lines);
// 切换实际调用函数, 再执行委托
SqlGetDeleget = new SqlCmd(SqlGetAllLine);
SqlGetDeleget("select * where name equals ker0123", lines);
}

相同类型的委托, 还能够用+, -, +=, -= 拼接成新的委托, 或者排除其中某个委托, 达到一条命令执行两个同类委托的效果.

事件 Event 以及 “发布-订阅” 模型

CMake + clang, 跨平台项目编译.

前言

随着对 C/C++ 的了解, 发现其作为一门语言, 有不止一个编译器. Unix like 系统上的 GCC, Windows 平台上的 MSVC, 以及跨平台的 CLANG.

GCC 的使用最为广泛, 但是其有很重的平台属性(Unix), 虽然在 Windows 平台上有它的移植项目 MinGW(Minimalist GNU for windows), 但是使用其的软件不是很多: Windows 原生软件直接使用 MSVC, 而跨平台软件, 例如基于 Qt 的软件, 则使用的 Clang.

因此, 学习Clang编译器的使用是一件很有必要的事.

至于 CMake, 主要是跨平台的项目编译太离不开它了, 而我自己编程这么久还不会写 makefile. 因此在这里一并学了.

另外该文章还包含的有 lua 脚本语言. 想要在 C/C++ 项目中植入脚本, python 是一个选择, 但据我了解, lua 比 python 快的多. 总之, 这个测试项目用 lua 作为外部库, 实践库导入等操作

以下是这几个项目的相关官方链接:

CMake

安装

直接在官网下载最新版本的可执行文件(文件名为cmake-4.0.2-windows-x86_64.msi). 傻瓜式安装.

安装位置选取在D:\bin\CMake, 可执行文件位于D:\bin\CMake\bin\cmake.exe. 这个位置在配置项目时可能会用到.

使用

按照这个教程进行的学习.

小贴士

  • cmake 语法大小写不敏感.
  • #注释, #[[...]]块注释.

按实例解释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 最低版本 4.0.0
cmake_minimum_required(VERSION 4.0.0)

# 项目名称 Lua-text version 0.1.0
project(Lua-test VERSION 0.1.0)

# 项目C++版本
set(CMAKE_CXX_STANDARD 17)

# 项目目录
set(SOURCE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/src)
set(INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/inc)
set(LIBRARY_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/lib)

#
file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)

include_directories(${PROJECT_SOURCE_DIR}/include)

link_directories(${PROJECT_SOURCE_DIR}/lib)

link_libraries(calc)
add_executable(app ${SRC_LIST})

Godot 学习记录: 与 Unity, UE 完全不同的结构思路

知识点

动态语言与鸭子类型

官方文档

C#也算作动态语言. 与C++, java等静态语言有几个很值得注意的不同:

  • 一些在静态语言编译时能够检查出来的错误, 在动态语言中无法检测出来. 只会在运行的时候报错
  • 动态语言, 包括C#和GDScript, 默认对基础类型的传递是值传递, 默认对其他所有类型是引用传递.

鸭子类型可以视为静态语言的简化和解耦. 对象A调用对象B的某个方法时, 无需检测复杂的继承关系是否使对象B实现了该方法, 会直接尝试调用.

“当我看到一只鸟像鸭子一样走路, 像鸭子一样游泳, 像鸭子一样呱呱叫时, 我就管这只鸟叫鸭子”

但是如果对象B实际上没有实现该方法的话, 程序就会在运行时报错. 按照之前写Unity的经验, 可以举例: 如果某个游戏对象上的脚本尝试获取一个游戏对象上不存在的组件时, 就会报错. 如果再尝试进一步调用组件的方法, 甚至可能会结束程序.

因此, 一般在调用前用如下代码检查是否存在该方法, 再进行调用.

1
2
3
func _on_object_hit(object):
if object.has_method("smash"):
object.smash()

安全行

Gpdot提供了这个工具来在编写代码时告诉程序员, 某行歧义代码是否能正常执行.

1
2
3
$Timer.start()
# => 安全
($Timer as Timer).start()

里氏代换原则 协变与逆变

派生类(子类)对象可以在程序中代替其基类(超类)对象.

要达到这个原则, 简单来说, 子类的输出包含的数据只能比基类更多, 子类能接收的输入只能比基类更宽泛.

协变: 继承方法时, 你可以为子类方法指定一个比该子类方法的父类方法更为具体的返回值类型(子类型). 这保证了子类的输出包含原有输出的所有数据, 只会更多.

逆变: 继承方法时, 你可以为子类方法指定一个比该子类方法的父类方法更不具体的参数类型(超类型). 这保证了子类能够接收原来传给基类的所有数据, 只会能接收更多种.

一句话小技巧

  • 可以用:=来使左边的变量自动推导类型, 达到静态编程的效果.
  • 可以用as xxx来转换返回值类型.
  • Array,

Hexo 使用记录: 安装和简单配置

Hexo 是一个快速, 简洁且高效的博客框架. 使用 Markdown 解析文章,依照配置好的主题来生成静态网页.

本博客用的就是 Hexo.

安装

安装 Hexo 之前要先安装 Git 和 Node.js. Git 的安装不在这里说明, 只说明安装 Node.js.

1
2
3
4
5
6
7
8
9
10
# 如果没有curl, 要先安装curl
sudo apt-get install -y curl
# 下载安装脚本
curl -fsSL https://deb.nodesource.com/setup_23.x -o nodesource_setup.sh
# 运行安装脚本
sudo -E bash nodesource_setup.sh
# 安装Node.js
sudo apt-get install -y nodejs
# 验证安装结果
node -v

安装好 Node.js 后, 开始安装 Hexo

1
2
3
4
5
6
7
8
# 安装 hexo
npm install -g hexo-cli
# 启动 hexo
cd ~
mkdir hexo
hexo init hexo
cd hexo
npm install

配置和使用

可以在 _config.yml 中修改大部分的配置. 具体配置项及其含义见官方文档配置章节.

最开始, 这个网站主要修改了:

1
2
3
4
5
6
7
8
9
10
11
12
# Site
title: Ker's site.
subtitle: 'ker0123的个人网站, 记载了他一段时间的所学.'
description: '网站开始于2025年5月, 自己大学毕业的后几天. 实际上已经工作快半年了. 这段时间发觉自己的技术栈还是太浅了, 对于软件这一块, 尤其是互联网软件, 相关知识及其欠缺. 于是租了个服务器, 开始一边学习一边尝试自己写一些东西.'
keywords:
author: ker0123
language: ch
timezone: 'Asia/Shanghai'

# URL
## Set your site url here. For example, if you use GitHub Page, set url as 'https://username.github.io/project'
url: http://www.kers.site

在命令行使用new命令来生成新文章:

1

AList/OpenList 使用记录: 部署 & 服务器本机存储 & SFTP访问个人电脑文件 & 作为图床.

安装

参考官方文档进行手动安装

安装时, 由于云服务器没有配置代理, 所以使用个人电脑从github上下载, 并使用ssh协议进行上传.

1
2
3
4
5
6
7
8
9
10
11
# 在浏览器中选择最新Realse, 云服务器是Linux系统, x86架构的64位机器, 因此选择`alist-linux-amd64.tar.gz`并复制链接.
curl "https://github.com/AlistGo/alist/releases/download/v3.45.0/alist-linux-amd64.tar.gz"
# scp 本地文件名 云服务器用户名@云服务器IP:云服务器存储位置
scp ./alist-linux-amd64.tar.gz username@192.xxx.xxx.222:~/alist/
# 解压下载的文件,得到可执行文件:
tar -zxvf alist-linux-amd64.tar.gz
# 授予程序执行权限:
chmod +x alist
# 运行程序
./alist server

i386、i486、i586、 i686、 x86、x86_64、x64、amd_64详解
tar压缩解压缩命令详解

配置

安装程序后, 云服务器默认在5244端口上打开服务. 个人电脑可以通过http://192.xxx.xxx.xx:5244/访问刚创建的AList(192.xxx.xxx.xx是云服务器公网地址).

默认账号密码分别是 admin, admin. 先用它登录 AList

登录成功后从页面下方的[管理]按钮, 进入管理界面. 在这里设置好基本的管理员账号密码, 然后重新登录.

本机存储(云服务器)

参照官方文档为 AList 添加存储器. 例如添加本机存储, 用以将云服务器的文件挂载到网盘上.

配置本机存储

SFTP(通过SSH与个人电脑文件同步)

又例如通过 frp 配置好个人电脑的内网穿透, 通过ssh访问内网机器, 由此构建SFTP存储

配置SFTP

第一次部署时, 我采用的是密码登录, 安全性差. 可以换成 ssh 秘钥登录:

  1. 云服务器生成一对秘钥
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # host

    cd ~/.ssh
    # 生成以 forkerspc@kers.site 为账号名(可修改, 不影响功能) 的秘钥对
    ssh-keygen -t rsa -C "forkerspc@kers.site"
    #Generating public/private rsa key pair.
    # 输入存储位置为 id_rsa_for_pc
    #Enter file in which to save the key (/root/.ssh/id_rsa): ./id_rsa_for_pc
    # 不使用密语
    #Enter passphrase (empty for no passphrase):
    #Enter same passphrase again:
  2. 将公钥存到个人电脑(将id_rsa_for_pc.pub文件中的内容复制到C:\ProgramData\ssh\administrators_authorized_keys中)
    1
    2
    3
    4
    # host

    ~/.ssh# cat id_rsa_for_pc.pub
    #ssh-rsa AAAAB3Nza....MqPyLU= forkerspc@kers.site
    1
    2
    3
    4
    # pc

    cd C:/ProgramData/ssh
    echo "ssh-rsa AAAAB3Nza....MqPyLU= forkerspc@kers.site" >> ./administrators_authorized_keys
  3. 将服务器私钥填到AList配置(注意要包括开头和结尾那像是格式的两行)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # host

    cd ~/.ssh
    cat id_rsa_for_pc
    # -----BEGIN OPENSSH PRIVATE KEY-----
    # b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
    # NhAAAAAwEAAQAAAYEAuY+dAZ5Beubd6uqLGaD7TYvJ4zijk5zxm0390DWhP+bu7n9/Dpkk
    # ...
    # 2/xm2MB1CSr1HOm6r7kEV7TFT1r+aQI1I0BrbUAAbQeTuHPt/6vL3SiP98ZBPuPIR9fgkF
    # 40YdJ3L3Nx8bMAAAAQa2VyXzAxMjNAMTYzLmNvbQECAw==
    # -----END OPENSSH PRIVATE KEY-----
    填写私钥
  4. 点击保存, 不出意外就能成功挂载了.

关于 Windows 上的 ssh 密钥登录, 还可以参照这篇文章: windows 上 OpenSSH 服务 启用秘钥登录.

Alias别名(通过别名与权限控制访客的访问范围)

又例如, 通过alias别名, 将多个存储器上的部分内容引用, 放到新的一个文件夹里, 方便设置访问权限.

配置Alias

为访客用户设置只能看到Share目录的权限

生成简单直链, 实现图床用法

首先要在设置>全局中关闭[签名所有]选项, 打开[转发直链参数]选项. 之后便可以右键文件, 选择分享, 生成直链来使用了.

设置全局

另外, 记得配合 元信息 为不想分享的文件夹设置密码, 防止外界可以不登录, 就通过轮询直链访问云盘内的所有文件.

请确保可以公开的文件, 右键分享得到的链接形似http://pan.kers.site/d/share/imghost/zzz.jpg; 期望登录才能获取的文件, 右键分享得到的链接形似http://pan.kers.site/d/pc/Music/desktop.ini?sign=iqp25J4VCbDf6G1M62-_MBlxJspz9aAvLX6_cUXy8gQ=:0

如果不是这样, 请确认有好好设置元信息, 有勾选[应用到子文件夹]

其他

可以通过元信息为云盘内的某些文件, 或者满足某些规则的文件, 设置访问密码. 这点详见官方文档.

启动之后可以通过以下命令来启停AList, 似乎命令之后要接上pid, 能够理解, 毕竟一个服务器能运行多个alist实例.

1
2
3
4
5
6
# 携带`--force-bin-dir`参数启动服务
alist start
# 通过pid停止服务
alist stop
# 通过pid重启服务
alist restart

手动安装之后, 添加守护进程来启停服务存在一些问题. 文章写成时暂未解决, 在github项目下提了issus.

2025年6月11日. Alist 项目社区发生剧变, 项目发起者将项目卖给了某灰色产业公司, 从此Alist软件不再安全.

鉴于原 Alist 项目频繁删 issus(上文中的issus链接就被删了, 也是这个才使我注意到此事), 大部分相关信息链接未来可能无法访问, 这里只提供社区版 fork 的 github 项目地址.

开源道路道阻且长, 时常被这些道德败坏的组织剽窃成果. 但至少我仍然决心要踏上这条道路, 因为如果所有开源社区贡献者都寒心了, 不干了, 那才是真正的没有未来.