在使用WSL的过程中,我们有时候会遇到希望WSL访问Windows主机客户端的需求。在不考虑windows防火墙存在的情况下,这是非常容易实现的。
首先,在windows中运行如下命令查看WSL虚拟网卡下Windows主机的IP地址:
1 | ipconfig |
找到带有WSL的虚拟网卡,类似于vEthernet (WSL)
,然后找到其IP地址(如下图):
其中172.27.48.1
则是主机的IP地址,在wsl中使用这个地址连接即可。
但是在windows中,我们需要配置防火墙规则来允许WSL访问Windows主机客户端。这可以通过两种方式来进行,第一种是直接在防火墙中将你希望从wsl连接的服务端程序的入站规则设置为允许,第二种是直接允许WSL虚拟网卡的所有连接入站。第一种方法相对于第二种比较危险,因为你很可能处于一个复杂的网络环境中,除了wsl,你所在的局域网的其它设备也可以访问你的windows主机,网络中的其它设备也可能可以通过你的ipv6地址访问到你的端口(如果你的ipv6地址被泄露且上层网关没有防护)。所以,我推荐使用第二种方法。
要让windows防火墙允许所有来自WSL虚拟网卡的连接,可以使用Powershell运行如下命令(管理员权限):
1 | New-NetFirewallRule -DisplayName "WSL" -Direction Inbound -InterfaceAlias "vEthernet (WSL)" -Action Allow |
注意上面命令中的vEthernet (WSL)
需要根据你在ipconfig
中找到的虚拟网卡的名称进行修改。
这条命令会在防火墙中创建一个名为WSL
的规则,允许所有来自vEthernet (WSL)
的连接。这样,你就可以在WSL中访问Windows主机的服务端了。
我们需要实现这样一个需求: 假设你患有赛博收集癖症状, 每天都高强度从pixiv和各种涩图群收集大量二刺螈cg到自己的硬盘里, 很快你的硬盘里就收集到了数万张来源、清晰度等各不相同的cg.
然而你发现你下载的cg中有相当一部分是重复的, 这些重复的cg占用了你宝贵的磁盘空间,而你使用的还是一个无法扩容的 Microsoft Surface Pro 64G版, 去除掉系统占用、保留空间等等只剩下十多G的空间了.因此你急切需要一个快速找出你的cg目录下重复图片并去重的方法. 由于下载来源各不相同, 因此使用文件名等等传统的查找方式显然就无法解决这个问题,必须要从分析图片内容入手.
今天介绍的图像哈希与vp树, 就可以解决这样的问题.
通常,我们在校验和比较不同的文件时,一般会对文件使用一种散列哈希算法(aka Cryptographic hash, 例如SHA1
, SHA256
, 或者在对安全性要求不高的场景使用CRC32
等)来提取文件的"特征"。相比巨大的文件本身,文件哈希值更加容易被检索、索引。但是密码学散列哈希有一个特点,即使输入的内容只相差1bit,都会导致哈希结果完全改变,并且这种变化是不可预测的。
而在查找重复图像的过程中,图片可能会经过编码格式转换、颜色空间转换、调色、压缩、变更分辨率等等不会影响图片特征,但是会导致处理前后文件内容相差很大的操作。我们希望有一个哈希算法可以容忍这些由编码与压缩等带来的差异,并且可以评价不同图片之间的相似度,显然传统的哈希算法不能满足我们的需求。因此我们需要使用图像哈希。
本节内容部分由ChatGPT生成。(真的不想写概念了
dHash,也称为"差异哈希",是一种用于图像处理和相似性比较的技术。它的主要思想是将图像转换为一种紧凑的表示形式,以便可以快速计算和比较图像之间的差异。dHash 在图像搜索、相似图像检测、图片 deduplication(去重)、图像压缩等领域有着广泛的应用。
dHash 基于图像的像素差异计算,将图像转换成一个二进制哈希码。具体原理如下:
这样,每个图像都被表示为一个64位的哈希码,其中每一位代表了对应像素差异的比较结果。
pHash,全称为“感知哈希”(Perceptual Hash),是一种图像处理技术,用于计算图像的哈希值,以便比较和识别图像的相似性。与 dHash 不同,pHash 不仅仅关注像素差异,还考虑了人类视觉系统对图像的感知。pHash 在图像检索、内容识别、图像压缩等领域有广泛的应用。
pHash 基于图像的颜色、纹理和结构特征,通过对这些特征进行提取和量化,生成一个紧凑的哈希码。具体原理如下:
生成的 pHash 哈希码不仅考虑了图像的像素值,还捕捉了图像的结构、纹理等感知特征。
aHash,全称为“平均哈希”(Average Hash),是一种用于图像处理和相似性比较的简单而有效的技术。它通过计算图像的平均像素值来生成图像的哈希码,以便比较和识别图像的相似性。aHash 在图像检索、相似图像检测、图像压缩等领域有广泛的应用。
aHash 的原理非常简单,它只考虑了图像的平均像素值,而没有涉及复杂的特征提取或变换。具体原理如下:
生成的 aHash 哈希码简洁,但可以有效地捕捉图像的整体特征。
不同哈希算法之间一般并没有一个最优选择,但是在我的测试下pHash
算法在对图像细节差异的识别上要优于另外两种哈希。在实际应用中你可以对不同的图像哈希算法进行测试,选出你认为最优的即可。后面的比较过程都同时适用于上述三种图像哈希算法。
前文提到的三种哈希算法, 最后生成的都是一个64bit的哈希值, 一般使用一个unsigned int64_t
存储. 在表示的时候也可以将其以二进制的形式按位表示, 例如1101101100110101100010101110000101001110001001000010111110011000
.
在比较不同图片的图片哈希时,只需要求这两个哈希的汉明距离即可, 在字符串表示中汉明距离即为两个相同长度的字符串对应位置的不同字符的数量.而在二进制表示中, 则只需对两个哈希值求位异或然后统计结果中所有1
的数量即可.得出的结果越小, 则两张图片越相近.
下面的算法可以用于快速统计一个ulong
数据中所有1
的数量.
1 | private static readonly byte[] BIT_COUNTS = |
如果想要计算相似度百分比, 则使用下面的表达式转换即可:64 - BitCount(hash1 ^ hash2) / 64
.
接下来考虑存储一个图像集中所有图像哈希值的数据结构.我们希望对这个数据结构进行建立以及区间查找(用于查找重复图片)的时间复杂度尽可能低.考虑到汉明距离满足三角不等式定理,即任意哈希值, 均满足:
因此可以使用VP Tree
来存储图像哈希.
VP树是一个基于度量距离建立的树结构, VP树不关心给定数据的维度, 只需要给定可以计算得到满足三角不等式定理的距离计算函数,即 即可满足建立VP树的条件.
VP树是一个建立在度量空间(Metric Space)上的树,要想理解VP树必须先理解度量空间的概念:
想象一下,你失去了所有方向感,并被蒙住了双眼。你站在一个空旷的广场上,你只能通过声音感知周围的人与你的距离,但是你并不知道它们的方向。
在这样一个空间下,有下面几个基本法则:
与二叉树等等其它树不同,VP树并不按数据与节点值本身的大小关系来划分左子树与右子树,因为度量距离永远为正。VP树将子树节点数据与当前节点数据的距离通过一个半径(有时也叫权重)来划分,所有距离小于半径的数据都会进入左子树,而大于半径的数据都会进入右子树.
在二维空间中vp树的一个节点如下图所示。由于vp树在建立过程中只使用了度量距离,而度量距离存在于任意维度下,因此vp树可以非常轻松地扩展到任意维度。但是为了方便理解,接下来的图片中均在二维空间下举例。
每个VP树节点数据结构需要存储节点本身的数据, 节点的半径 , 节点的左子树指针与右子树指针. 所有位于左子树的节点与该节点的距离都小于或等于 ,而位于右子树的节点与该节点的距离则都大于 .
VP树建立的平均时间复杂度为 , 而单次查询的时间复杂度为
首先选定第一个数据作为根节点 , 然后选定一个半径 (一般为所有其它点到根节点距离的中位数), 将所有距离小于 的点放至左子树,距离大于 的点放至右子树, 然后递归建立子树.
假设我们需要搜索的数据值为 , 同时, 我们希望找到距离 的距离小于 的数据, 那么过程如下.
进入节点 , 首先计算 , 如果 , 则将 加入结果序列中.
接下来分下面两步进行:
搜索左树 | 不搜索左树 |
---|---|
搜索右树 | 不搜索右树 |
---|---|
与二叉树不同, 与 可能同时成立! 因此在某些情况下你必须同时递归搜索左子树与右子树.
上文中对vp树概念的介绍部分参考了这篇文章:http://stevehanov.ca/blog/?id=130
如果想要了解VP树的细节, 建议看看上面的文章。人家讲的比我好太多了
建立完成VP树后, 给定任意图片哈希就可以查询出与该图片距离在给定值以下的图片了. 但是我们希望得到的是一个相似图片组的列表, 即img[][]
, 因此接下来还需要用并查集进行集合操作.
并查集算法因为非常简单且著名, 我这里就不过多介绍了, 如果想要了解可以看看oi-wiki中的文章.在使用路径压缩后, 并查集的所有操作的时间复杂度都非常接近于 .
Anyway, 我们这里要做的就是遍历待查询列表中的所有图片, 通过前面建立的VP树找到与它相似度在给定范围内的所有图片(注意: 如果待查询数据集与前面用于建树的数据集是同一个的话,那么这里的结果里必然有一张是它本身, 不过在并查集中将自己与自己合并这个操作是合法的.)
建树与集合代码如下:
1 | // Building Data Hashes |
使用哈希表,用并查集根节点的id作为索引即可. 代码如下:
1 | Dictionary<int, List<ImgFile>> groupsDict = new(); |
注意在这个过程中我们舍弃了所有只有一个元素的列表. 得到的resultGroups
就是所有相似的两张或以上的图像组了.
因此总体时间复杂度为 , 在可接受范围内了。
上文中所写的哈希计算与对比,都实现在了我写的PixNinja.GUI项目中:
https://github.com/hv0905/PixNinja.GUI
截至发文时,这个项目的主要功能都基本可以使用(虽然UI丑了点)
图像哈希虽然对经过调色、压缩、变更分辨率等等操作的图像具有较好的鲁棒性,但是对于经过旋转、翻转、裁剪等操作的鲁棒性较低,因此图像哈希只能完成非常简单的图像搜索功能。如果你对图像搜索功能的要求更加高,例如希望构建一个类似于google image search
或ascii2d
的图像搜索引擎,那么图像哈希就不够用了。这种图像搜索引擎一般使用了如图片特征点提取等等更高级的算法,同时也需要为经过特征点提取后的索引数据设计合理的数据结构进行快速检索,这些算法就不在本文的讨论范围内了(主要是我也不会)
图像哈希由于在生成时涉及到将图片压缩至8 x 8
或是 9 x 8
的操作,因此不可避免地会丢失部分图像细节。这导致通过图片哈希比较将无法分辨图像中细微的不同,这个问题在面对一些galgame差分cg时尤为明显,如下面是两张表情不一样的galgame差分cg以及它们压缩到8x8之后的样子:
原图 | 压缩处理后 |
---|---|
两张处理后的图片几乎看不出任何细节,这也让这两张图片的图片哈希极为相似或完全一致。要想解决这类问题的一个办法就是加大哈希的长度,例如将图片压缩至16 x 16
并取256位哈希长度,但是这样又会大幅增加哈希计算与比对时的计算量。
不过在处理大多数图片的时候无需过多担心这样的问题,因为其它图片通常不会具有很高的相似度。
本文章假设你已经拥有了一个vSphere/KVM/Windows HyperV虚拟化平台,并已经向主机节点中安装了Nvidia Tesla计算卡(游戏卡,Quando等非计算卡不在本文讨论范围内)
如果你还没有你的Hypervisor主机,强烈建议你去看看我的朋友Anduin Xue的这篇文章: 让你的数据中心使用 GPU 算力!。 事实上,Anduin Xue搭建了我一直用于研究测试的数据中心,同时在我尝试部署GPU服务器时提供了很大的帮助。
要想在Nvidia VGPU进行Cuda计算或者输出显示,必须安装NVIDIA Grid驱动,但是这个驱动居然是tm要钱的,并且如果你是个人非常难以购买。
如果你想要使用Vgpu,一般可以通过评估测试获得90天的许可。
打开NVIDIA Vgpu评估中心, 选择Rigister For Trial
, 邮箱填写参考下方提示,其它信息随意填写即可。
在申请评估试用的时候强烈建议使用一个自定义域名邮箱,而不是公共邮箱(如Outlook, Gmail, QQ等),使用自定义域名邮箱可以极大提高申请的通过率和通过速度,一般在五分钟内即可拿到许可证。
如果你拥有一个自己的域名但没有邮箱服务,可以考虑使用Microsoft Exchange(Paid)或者使用Cloudflare Email Routing服务(Free)快速获得一个邮箱服务。
取得许可证后,使用你的账户登录到Nvidia Application Hub Dashboard,然后按照下面步骤操作。
License Server
, 点击Create Server
Server Instances
, 然后在Actions
中选择Generate Client Configuration Token
,选择你刚才创建的许可服务器,然后Download, 这个文件将在之后为服务器配置许可时用到.在为虚拟机分配虚拟GPU时,可以选择不同的vgpu类型
由于我们需要使用OpenCL/CUDA计算功能,必须确保你选择的GPU类型支持CUDA运算。一般来说,所有Q-Series和C-Series的vGPU都支持CUDA计算(Tesla M6, Tesla M10, Tesla M60仅8Q支持),而A-Series和B-Series不支持CUDA计算。请确保选择Q/C Series的vGPU, 建议选择Q-Series,其功能最为强大详情可以参考Nvidia用户手册
以Tesla P4举例, Tesla P4有8G的显存,可用的vGPU类型有P4-1Q
, P4-2Q
, P4-4Q
, P4-8Q
(这里仅列出Q类型),其中后面的数字代表了显卡可用的显存数,这里选择的显存数大小决定了显卡可以分配到几台虚拟机,例如P4-2Q
可以分配到4台虚拟机,但是每台虚拟机只能使用2G的显存,而P4-8Q
只能分配到一台虚拟机,但是这台虚拟机可以使用全部8G的显存。实际部署中,应该根据你的需求选择合适的显存大小。
这里我们选择P4-8Q
继续。
各种不同计算卡可用的vgpu类型可在grid文档查询。
Grid驱动可以从Nvidia Application Hub Dashboard的Software-downloads中下载,一般来讲客户机驱动应与hypervisor驱动版本号一致。驱动有三种分发版本:deb
, rpm
, runfile
。如果你的平台支持安装对应的软件包,则不建议通过runfile
安装。
这里以Ubuntu 22.04 LTS举例,将对应版本的驱动下载到服务器上后,可以使用下面命令完成安装:
1 | sudo apt install ./nvidia-linux-grid-525_525.105.17_amd64.deb |
这里我使用了apt install
来完成安装而不是dpkg -i
, 因为apt
可以自动安装缺失的依赖。
安装完成后,输入nvidia-smi
,此时应该可以看到vgpu的信息。
首先,编辑gridd配置文件:
1 | vim /etc/nvidia/gridd.conf |
找到FeatureType
并将其改为改为1
, 其它选项保留不动即可。
接下来进入/etc/nvidia/ClientConfigToken
目录(如果没有则创建),将前面下载到的Client Configuration Token
放入,然后使用chmod 744
为其修改权限。
完成后,重启nvidia-gridd:
1 | sudo systemctl restart nvidia-gridd.service |
最后用nvidia-smi -q
确认许可已被正确安装,如果正确安装,你应该可以看到类似下面一段内容:
1 | vGPU Software Licensed Product |
在选择Cuda版本时需要注意,一般来讲Grid驱动会落后标准Nvidia驱动几个版本,因此可能无法安装最新版本的Cuda, 你可以在cuda-release-note中看到不同的cuda版本对驱动的版本要求。
一些AI软件也有CUDA版本要求,也应该根据它的文档确定应该安装的cuda版本.
打开cuda-toolkit-archive,选择你想安装的版本,然后选择你对应的系统即可获得对应的cuda toolkit下载链接。
只要是Linux系统,无论是什么发行版,你都不可以使用平台软件包(deb,rpm等)来安装cuda-toolkit,而是必须使用runfile安装如果使用平台软件包安装,在安装时cuda-driver会与已安装的grid-driver冲突,导致安装无法继续。
下载完runfile
后,使用sudo
运行,然后在选择组件界面,取消勾选安装cuda-driver,否则grid驱动会被覆盖
安装完成后,编辑系统PATH
环境变量 sudo vim /etc/environment
在PATH
末尾加入:/usr/local/cuda-12.0/bin
(版本号自行按需修改)
重新启动你的shell,然后使用下面命令确认cuda已完成安装:
1 | nvcc --version |
You’re all set. 接下来就愉快炼丹吧
在Linux下,如果你尝试通过ntfs-3g
访问NTFS分区下的Onedrive目录,会出现错误无法访问。
使用ll
检查目录,会显示一个错误:unsupported reparse tag 0x9000701a
这是由于Onedrive for Windows使用了一个NTFS下的Reparse Points
来实现文件按需下载,可以访问wiki页面了解更多。
本文章不讨论如何在Linux中实现同步Onedrive的相关内容,只考虑如何在Linux下打开Windows中创建的Onedrive目录,主要适用于双系统用户如果你希望在Linux中创建Onedrive目录并同步Onedrive数据,建议使用abraunegg/onedrive.
2017.3.23AR.4
以上. (使用ntfs-3g --version
查看版本号)首先克隆ntfs3g-onedrive-plugin仓库到本地目录:
1 | git clone https://github.com/deerf0x/ntfs3g-onedrive-plugin.git |
如果上面的仓库不再有效,可使用https://git.aiursoft.cn/EdgeNeko/ntfs3g-onedrive-plugin.git
.
依次运行下面的命令来配置并构建插件:
1 | libtoolize --force |
在终端中运行ntfs-3g获取ntfs-3g的插件目录:
1 | ntfs-3g |
复制上面Plugin path
中对应的目录, 然后打开Makefile
并编辑:
1 | # Use your own editor instead of Kate if necessary |
搜索plugindir
常量定义,如下图(截至本文发布时,位于L369):
将其修改为上面获取的目录:
完成后保存Makefile
并退出.
最后,运行下面命令完成安装:
1 | sudo make install |
如果一切正常,重新挂载包含Onedrive目录的分区,接下来你应该可以正常访问Onedrive目录下的文件了:
仿照现实世界中的量子,我们可以为元宇宙定义一个元粒子
作为宇宙的最小组成单位。元粒子可以看作是由真空中的能量波动产生的。元粒子作为一种亚原子粒子,它没有宏观物体的诸如大小、质量、速度等属性。而是拥有几个微观属性,例如自旋、电荷等等。不过这里的定义不一定是绝对的,根据我们想要构造的元宇宙的属性的不同,我们可以为其赋予其它基本属性。但是我们赋予元粒子的属性也可能要受到运行元宇宙的硬件条件的限制。
基于元粒子,我们就可以定义元宇宙中物质与能量的表示方式。由于物质和能量都是元粒子的一种特定表现形式,我们同时也可以定义物质与能量之间的转换规则(例如在现实世界中,我们有著名的质能方程E=mc^2
)。
由于元粒子本身只是一个纯粹的理论概念,所以元粒子理论上来讲应该在元宇宙中是可以无限存在的,但是实际上由于运行元宇宙的硬件条件的一些限制,例如内存与硬盘的限制,元宇宙中可以表示的元粒子的数量可能会被受到限制。
在确定元宇宙运行的基本法则的时候,我们要按尽可能少与简单的原则来完成。
仿照现实世界的广义相对论和能量守恒定律,我们不难可以猜想出元宇宙运行所需的一条最基本法则:
在一定的封闭系统内,元粒子的数量保持不变。元粒子不会凭空产生,也不会凭空消失。
由于宏观世界的物质和能量都是由元粒子表示的,我们也可以进一步推导得到元粒子守恒的宏观形式:在一定的封闭系统内,物质和能量不会凭空产生,也不会凭空消失,它们只会从一种形式转化为另一种形式,或者在物质和能量之间转化。
为了保证元宇宙能以一个可预测的方式运行,我们可能还要为元宇宙制定一些其它法则:例如约束物体运动的定律、描述热量传递的定律等等,当然,这些定律也许可以被统一为元粒子之间相互作用的定律。
在现实世界中,根据狭义相对论,一个宏观物体所拥有的速度、质量、时间等属性,不仅与宏观物体本身有关,还与观测者所在的参考系有关。若在元宇宙中也遵循类似的定律,那必须选择一个合理的物体作为观测者,使用其的属性作为参考系才可以得到比较有意义的观测结果。
上面对元宇宙的论述仅仅停留在想象,实际在能够真正实现元宇宙前仍然有很多理论与现实问题有待解决,例如最直接的现实问题就是存储与算力问题。由于我们使用元粒子
来定义我们的元宇宙,要表示出一个有研究价值的宏观世界所需要的粒子数量级是非常庞大的,这必然为运算与存储带来巨大挑战。
另外,这篇文章的部分内容参考了ChatGPT聊天AI的聊天输出。不得不说这个Ai模型真的颠覆了我的认知…
]]>%LocalAppData%\Packages\TeamCherry.15373CD61C66B_y4jvztpgccj42\SystemAppData\wgs
.xxxxxxxxxxxxxxxx_yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
. 其中xxxxxxxxxxxxxxxx
为你的XUID
, 如果你曾在你的电脑中登录过多个Microsoft Xbox账号, 可以从这个网站查询各个Gamertag对应的XUID
.container.xxx
文件.container.xxx
文件.文件中可以找到userN.dat
字样,这就代表了这个存档来自第N号存档位(见下图).%appdata%\..\LocalLow\Team Cherry\Hollow Knight\
.userN.dat
. 例如如果你希望存档应用到第1个存档位,则将其重命名为user1.dat
(目标存档位必须空).这个目录是Steam版空洞骑士的存档位置, 但是在Xbox版本中, 存档并不会主动地被存储到这里. 游戏会在启动的时候判断这个目录是否有存档文件, 如果有且这个存档文件在xbox云中对应的存档位是空的, 则会将这个存档迁入xbox云, 否则不会做任何事情.
在迁入之后游戏并不会删除保存在这个位置的存档, 但同时也不会把最新更改存到这里. 如果你之后再次把那个存档位清空了, 重启一下游戏, 你会发现存档又被从这个目录还原回来了(笑)
一般来讲, 部署在 Linux 下的 Asp.Net Core 应用都不会将Kestrel
服务器的监听端口直接暴露在生产环境中, 而是经过一层Web服务器作反向代理, 这个服务器可以是caddy
, nginx
或apache
等.
但是, 经过反向代理之后, 从Request
上下文中获得的源IP地址与源传输协议(HTTP
/HTTPS
)一般都会为127.0.0.1
(或反向代理服务器的地址)与http
, 这会导致基于IP的请求熔断器无法正常工作, 如果启用了HttpsRedirection
, 还会导致进入无限重定向循环中.
为了解决这个问题, 反向代理服务器一般会通过X-Forwarded-For
与X-Forwarded-Proto
两个Http头来传递实际的请求IP与请求协议, 因此只要配置服务器使用这个请求头中的数据替换原始的源IP及协议即可.
对于只有一层反向代理服务器的情况来说, 解决这个问题的方式非常简单.
ASPNETCORE_FORWARDEDHEADERS_ENABLED
为true
即可. 这一般可以通过修改systemd
服务配置等方法实现.如果配置了这个环境变量, Asp.Net Core应用会无条件信任来自所有源的请求中的X-Forwarded-For
与X-Forwarded-Proto
头. 这有可能导致X-Forwarded-For
头欺诈的情况发生, 从而导致IP熔断器失效. 因此必须保证Kerstrel
服务器的监听端口不可被不受信任的来源访问, 建议通过配置防火墙等方式实现, 或改用下面的方法.
ForwardedHeaders
中间件相关的配置代码实现:1 | // add at ConfigureServices() if you are using classic template |
这段配置代码默认只会信任localhost
, 如需信任其它服务器来源, 可通过修改KnownProxies
实现.
配置其它外部CDN后, Http请求会经过两层反代才会到达Kestrel
服务器. 但是默认配置下, ForwardedHeaders
中间件最对只会处理一种反向代理的情况. 如果有多层反向代理, 它会将最后一层反代服务器所设定的值作为源IP与源协议值.
要改变这一行为, 只需要更改ForwardLimit
的值即可(默认为1
)
下面的配置代码可以从配置文件读入ForwardLimit
值:
1 | builder.Services.Configure<ForwardedHeadersOptions>(options => |
然后在appsettings.json
中添加…
1 | { |
为了防止X-Forwarded-For
头欺诈, Caddy服务器默认不会信任外部请求所提供的X-Forwarded-For
与X-Forwarded-Proto
请求头. 因此需要为Caddy配置Cloudflare的信任IP:
Cloudflare会通过文档与api公布它们的CDN IP地址范围, 将这部分地址加入到Caddyfile的trust_proxy
中即可.
1 | # ... |
此处的Cloudflare IP地址仅作为配置示例且可能已经过时, 请以从Cloudflare中获取的最新地址为准.
Cloudflare的IP地址会不定时更新, 如果你不想手动维护这个信任地址列表的话, 可以参考下面的方法
这里我使用一个python脚本自动维护IP列表. 创建/etc/caddy/update_cloudflare.py
:
1 | #!/usr/bin/python |
完成后添加运行权限sudo chmod +x update_cloudflare.py
, 然后以sudo权限执行一次
然后修改/etc/caddy/Caddyfile
:
1 | reverse_proxy 127.0.0.1:5000 { |
然后配置计划任务, 以sudo权限运行crontab:
1 | sudo crontab -e |
添加下面这一行即可.(下面这行代码会在每天0点从api更新cloudflare ips)
1 | 0 0 * * * cd /etc/caddy && ./update_cloudflare.py |
此节摘自Authelia docs
当传入请求中已经存在X-Forwarded-For
头时, cloudflare会直接在原有的请求头中追加一个IP. 这意味着用户可能可以通过伪造X-Forwarded-For
头来伪造IP, 即X-Forwarded-For
欺诈. 因此, 强烈建议在Cloudflare中配置删除X-Forwarded-For
头的操作.
方法:
Rules
Transform Rules
Create transform rules
Modify Request Header
Rule name
更改为Remove X-Forwarded-For Header
或其它名字Field
设置为X-Forwarded-For
Operator
设置为does not equal
Value
留空Then
操作设置为Remove
Header name
设置为X-Forwarded-For
Save
考虑下面这样的一段代码:
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
上面这段代码在G++与clang等平台均可以正常运行。但是若在msvc中运行,程序会出现异常并退出。但是如果不使用前向声明(Forward declaration),就不会出现这样的问题。
在其它编译器中,成员函数指针的size是固定的(2个指针长度)
但是在msvc中,成员函数指针的size会根据对应类继承关系的不同而不同。在前向声明中,编译器并不能判断对应类的继承关系,因而会错误地推断成员函数指针的size,并影响后续声明的类的size。进而在不同代码中访问对应内存会导致越界等异常。
这个错误非常隐蔽,即使在调试过程中没有产生异常,也应该修复这个错误
对于msvc的项目,如果必须同时使用成员函数指针与前向声明,需要在前向声明语句中加入继承模式关键字来避免潜在的bug, 其中:
Keyword | 适用于 |
---|---|
__single_inheritance | 单继承或无继承关系 |
__multiple_inheritance | 多重继承关系 |
__virtual_inheritance | 虚继承关系 |
例如,对于上面的示例,可以将Foo.h
中的L7的前向声明改为以下行进行修复:
1 | class __single_inheritance Bar; |
这个关键字是Microsoft专用关键字,并不在C++规范内。如果您正在构建跨平台应用,需要使用不同的编译器编译同一份代码,建议通过宏进行区分。
详细的错误issue请参考:https://developercommunity.visualstudio.com/t/Unexpected-exception-when-using-a-combin/10017095?viewtype=all
Microsoft docs: https://docs.microsoft.com/en-us/cpp/cpp/inheritance-keywords?view=msvc-170
]]>简中版Windows下控制台默认代码页为936(GBK), 如果直接显示UTF8内容会乱码, 此时需要用以下代码将代码页修改到兼容UTF-8的代码页.
首先如果你使用msvc开发应用,必须确保启用编译器的utf8模式
如果你使用Visual Studio项目进行构建, 你需要在项目属性中找到Configuration Properties > C/C++ > Command Line
, 在Additional Options
中添加/utf-8
参数(详见此文档)
如果你正在使用cmake进行构建,添加下面这段代码到CMakeList.txt
中
1 | add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>") |
此时编译器将使用UTF8模式编译应用.
接下来在Main函数开头执行下列之一函数:
1 |
|
(实测此方法在输出效率上会优于Method1 (待验证))
1 |
|
启用虚拟终端模式后可以在Windows中使用在Linux/Mac中可用的转义字符序列控制终端行为
经测试虚拟终端功能仅支持win10及更新的系统.
可参考相关文档
1 |
|
使用以下方法可以快速获取/修改光标位置,或者按照相对距离移动光标
1 |
|
修改字符颜色建议使用VT模式完成
下面代码首先需要启用VT模式
1 |
|
除此之外,部分终端还支持设置自定义的RGB颜色
详见Microsoft docs
1 | void clearScreen() |
此方法执行效率略低于Method1(待验证)
1 | void clearScreen() |
使用io库操作标准输入时, 用户的输入都会被存储在缓冲区
如需直接对键盘输入进行处理, 可以使用conio.h
中的_getch()
与_kbhit()
函数
_getch()
可用于获取键盘输入的一个字符(不会回显), 当缓冲区内没有待处理的键盘输入时, 将阻塞程序
_kbhit()
可用于判断键盘是否有输入, 若缓冲区内没有待处理的键盘输入时, 将返回false
一个典型的键盘处理方法如下
1 |
|
When writing some console app, we sometimes have requirements to interactive with the console screen directly. One example is clearing the console screen.
In this article, you will learn how to clear the console screen properly in C++ code.
To clear the console screen, one of the approach is directly using the system console command:
1 |
|
Yeah… It works. However, there are some problems.
clear
command could just unavailable, which can break your program.Fortunately, almost all terminals now follow a standard. Which allow us to have a universal way to clear the console.
Try:
1 |
|
In this approach, the first escape code \033[2J
can clear the screen, and the second escape code \033[1;1H
can move the cursor to (1,1).
This approach is only available on Windows! If you have the requirement to target to Linux/UN*X system, just use the previous code directly.
Although the previous example work well on Windows, there is one obvious shortcoming: after clearing the screen, you can still see the scrollbar exist, and if you scroll up, you can see the old log is still there.
Unfortunately, to resolve this problem, we have to use a native approach.
1 |
|
众所周知, linux系统启动的时候默认是会打出详细的启动日志的(就是一堆OK的那一个).
但是在Manjaro中默认并不会打印出这部分日志, 因为Manjaro默认在启动参数中添加了quiet
来隐藏启动日志, 要想恢复只需要修改grub配置文件即可
打开终端, 运行以下指令修改grub config:
1 | kate /etc/default/grub |
如果你希望使用其它文本编辑器来编辑(如vim), 你可能需要使用sudo
运行,否则无法保存.
找到类似以下的一行:
1 | GRUB_CMDLINE_LINUX_DEFAULT="quiet apparmor=1 security=apparmor udev.log_priority=3" |
将其中的quiet
删除, 然后保存.
最后别忘了要更新grub, 才可以应用刚刚所作的更改. 在终端上运行:
1 | sudo update-grub |
重启即可看到熟悉的日志效果了.
~可以把电脑拿去星巴克装逼了~
在开始前强烈建议运行以下命令确保所有软件包与软件源已更新到最新:
1 | sudo pacman -Syu |
运行以下命令安装必要的BootSplash组件, 主题与配置工具
1 | sudo pacman -S bootsplash-systemd bootsplash-manager bootsplash-theme-manjaro |
安装完成后, 运行以下命令, bootsplash-manager
就可以帮你完成剩余的所有设置了.
1 | sudo bootsplash-manager -s manjaro |
执行上面的命令会自动执行mkinitcpio
和update-grub
当然你也可以安装其它的bootsplash-manager
主题, 只要在pacman -S bootsplash-theme-
后按Tab键即可查看所有的主题. 在AUR仓库中可能有更多的主题可供下载.
BootSplash主题基本上就是不同的logo加一个Win10的ProcessRing, 其中bootsplash-theme-vendor
可以将主板品牌logo作为图标(需要UEFI固件支持)
]]>如果你不想用这样的Win10风开机动画的话, 可以考虑安装Plymouth只要参考这篇文章即可, 此处不作展开Plymouth有非常丰富的动画主题可以下载, 参考 https://github.com/adi1090x/plymouth-themes总之比这个win10风好看多了 (
Adobe Photoshop 2021 v22.5.0 理论上应该适用于所有较新版本的ps。
原图:
结果:
Shift + Ctrl + U
Ctrl + I
1
,模式方形
颜色减淡
,此时插图已还原为线稿滤色
,即可应用渐变线稿的效果方法来自此视频:BV1Uf4y1n7zK
示例所用图片: pixiv id 63093148 侵删
]]>Updated 2022/08/23:截至2022/08/23, 该问题似乎已经得到修复.在 win11 22H2(build 22622)
及 Logitech GHub 2022.7
中已无法复现此问题.
我在最近买了一台使用Modern Standby作为睡眠模式的笔记本, 并配合我的G304
使用, 安装了Logitech G Hub
软件。
但是, 在使用一段时间后发现,我发信我的电脑完全无法进入睡眠状态,无论是使用睡眠按钮还是等待屏幕超时,电脑总会在屏幕熄灭10min左右后重新亮起,然后再次熄灭, 以此循环
MS提供了sleepstudy工具用于分析待机状态,管理员权限运行以下指令获得待机报告
1 | powercfg /sleepstudy |
一看待机报告, 好家伙, 电脑在按下睡眠按钮后完全没有进入睡眠模式,而是在Active
和Screen Off
中循环。而Screen Off
的EXIT REASON
均为Mouse Input
,即检测到鼠标动作(此时显然我是没有动鼠标的)。
经过测试,即使我关闭无限鼠标和触摸板, 系统仍然在Screen Off
和 Active
之间鬼畜, 无法进入Sleep
状态。只有在拔出无限鼠标接收器后才可正常睡眠。
后来经过查阅,是G Hub在电脑即将从Screen Off
转至Sleep
状态时持续通过虚拟鼠标持续给予电脑输入,导致电脑再次被唤醒。
电脑睡眠模式是否为Modern Standby可由以下指令查询
1 powercfg -a若S0低电量待机处于激活状态且S3待机处于不支持/禁用状态,那么你的电脑即使用Modern Standby
Modern Standby (即S0低电量待机)是微软在win10中推广的新睡眠模式根据官方文档的介绍, 现代待机可以选择性地使电脑保持唤醒(Screen off 或 Connected Standby)状态和睡眠状态(Disconnected Standby, 类似S3睡眠),使得关键应用能按需在后台保持运行(例如闹钟、音频播放、Windows更新等)
听起来牛批坏了,不是吗? 嗯…当一样东西听上去牛批坏了,那么它可能真的是坏的。
目前Modern Standby仍不能很好的解决外设唤醒的逻辑。特别是与鼠标。即使你在设备管理器中禁止鼠标唤醒电脑,它却仍可在Modern Standby中唤醒。
我以前有禁止鼠标唤醒电脑的习惯(因为鼠标太容易误触了),但是切换到Modern Standby后, 在设备管理器中禁止完全不起作用,照样能唤醒
为了实现鼠标宏功能, G Hub会向系统注册一个虚拟鼠标(Logitech G HUB Virtual Mouse
),由进程lghub_agent控制。
上文提到导致系统一直无法进入睡眠模式的原因是G Hub的虚拟鼠标发出指令, 那么一种解决办法就是直接禁用掉这个虚拟鼠标
打开设备管理器, 在鼠标和其它指针设备
中找到位置为Logitech G HUB Virtual Mouse
的鼠标(如图所示),在驱动程序页面中选择禁用即可.
这样做的缺点是, 禁用之后与点击鼠标有关的宏(如连点宏)就直接用不了了= =, 有以上使用需求的可以使用方法2处理。
要在不禁用虚拟鼠标的情况下阻止它在睡眠时发出唤醒信号, 那么只能限制lghub_agent的行为了.
我们可以通过配置一个计划任务,让系统在息屏时杀死lghub_agent
进程, 然后再唤醒时重新启动lghub_agent
进程。
打开任务计划程序, 新建一个计划任务,并按照如下设置。
System
,源:Kernel-Power
, 事件ID: 506
(即进入现代睡眠事件)taskkill
, 参数: /f /im lghub_agent.exe
源:Kernel-Power 部分必须从列表中选择,不能手动输入,否则不能生效
接下来创建用于恢复lghub_agent
运行的计划任务, 流程参照上部分
System
,源:Kernel-Power
, 事件ID: 507
(即退出现代睡眠事件)"C:\Program Files\LGHUB\lghub_agent.exe"
(可按照自己的lghub安装目录选择)完成后,你的电脑应该可以正常进入睡眠和使用鼠标宏了。
这个反人类现象的原因显然是罗技G Hub与Modern Standby不兼容造成的, 希望罗技能更新G Hub以兼容Modern Standby。作为一个硬件厂商,一个好用的驱动程序也是用户体验的重要一环。
同时也希望MS可以优化Modern Standby的唤醒选项,允许通过设备管理器禁用外设唤醒系统的功能。
Git bash 是 git 在windows下提供的类bash环境, 把很多熟悉的linux命令与应用带到了windows, 例如curl
, vim
, grep
, ssh
, sed
, xargs
等等, 非常适合UN*X用户使用.要安装git bash, 只要安装Git即可.
PowerShell
是 Windows 加入的功能强大的Shell环境, 在这个shell中你可以使用部分常见的linux命令(ls
, cat
, curl
, 具体参数用法与在linux中有所不同, 毕竟只是对应的powershell命令的别名), 因此无论你习惯用windows还是linux都能很快适应这个终端. 同时powershell具有极高可扩展性, 能直接与.Net
交互.
现代windows已经预装了基于.Net Framework
的 powershell
, 你也可以在此处安装基于.Net Core
的跨平台PSCore
参考: PowerShell入门
终端Terminal决定了控制台窗口的外观. Windows下默认的终端是comhost
, 这个终端丑就算了, 在中文环境下(代码页936)还无法使用不带中文字符集的字体, 这意味着无法使用像Consolas
, Cascadia Code
, Source code pro
等字体. 同时comhost
也不支持emoji显示, powerlines, otf字体显示等功能.
事实上中文环境无法使用英语字体的问题可以通过修改编码至utf-8编码来解决, 在
设置 > 区域 > 其它区域设置 > 区域 > 管理 > 非Unicode区域设置
勾选Beta版: ...
即可但是这样做会导致系统自带指令输出变为英语, 但是至少我不介意=.=, 学学英语有啥不好的.另外, 这样设置后会导致中文版Adobe After Effects
拒绝启动, 如果要用ae的话就别这样设了.
这些问题最好的解决办法就是更换更好的Terminal, 这里我推荐两个终端:
pros:
- UWP原生应用, 响应速度较快
- M$自家作品, 很有可能在未来会被直接预装在Windows 10中cons:目前配置仍然较为麻烦, 且功能不及Terminus多
pros:配置较为方便, 兼容性广cons:
- Electron应用, 启动较为缓慢
- 目前Fluent Effect会出现拖动延迟问题
这里我推荐两个字体
这两个字体其实是非常相似的, 它们都支持 code-specific ligatures, emm, 什么意思看看下面这张gif就明白了:
它们之间的区别是基础字形稍微有些不同, 下面是它们的比较:
可以明显看出, jetbrains Mono更加瘦长一点, 斜体的角度也更易于阅读此外, Jetbrains Mono为尽量提高小字号下的辨析度去掉了一些不必要的字母细节, 但这样也导致了大写U
和小写u
比较难以区分.
Prompt是一段文字, 用于指示此时正在接受命令。 它从字面上提示用户采取措施–wikipedia
git bash的默认prompt是:
1 | USER@PC MINGW32 ~/your/path/ (git_branch) |
这段prompt其实已经比较完善了, 如果你仍然希望修改也非常简单。
git bash的prompt是通过一段bash
脚本实现的, 其位置在/etc/profile.d/git-prompt.sh
, 如果你不清楚这个文件的具体位置, 可以__以管理员权限__运行:
1 | # 备份现有的脚本 |
可以参考我修改的git prompt
1 | TITLEPREFIX=bash |
效果:
1 | PS C:\test\path> |
Powershell的prompt可以说是…非常简陋, 相比起git bash既丑, 提供的有用信息也少。
好在powershell可以通过安装插件的方法来更改prompt, 这里我推荐oh-my-posh插件
使用下面的命令即可安装:
1 | Install-Module posh-git -Scope CurrentUser |
然后使用下面命令可以启用oh-my-posh:
1 | # Start the default settings |
其中Set-Theme命令后可跟不同的prompt主题, 各个主题的效果可参见Themes
你也可以自己制作主题, 方法参见Create your own theme
值得注意的是, 为了能让posh正常显示, 必须使用带powerline
的字体, 建议使用比较新的等宽编程字体, 例如Cascadia Code
或者JetBrains Mono
, 如果你仍然希望使用不兼容Powerline
的字体, 例如Source code pro
, 可以在这里下载它们的带powerline
版本。
另外不要尝试在windows自带的conhost下用这个主题, 不支持的=。=, 建议用我上文提到的Windows Terminal Preview
或Terminus
为了让每次启动powershell时都应用oh-my-posh, 需要修改配置文件, 执行下面命令:
1 | if (!(Test-Path -Path $PROFILE )) { New-Item -Type File -Path $PROFILE -Force } |
在visual studio code
中输入以下内容
1 | Import-Module posh-git |
嗯, 这样修改后的powershell还是比较好看的:
]]>下面的内容是我在尝试构建RailgunMediaEncoder
中尝试使用的方法, 我无法保证下面的方法绝对符合"最佳实践".
USE IT AT YOUR OWN RISK.
如果有任何问题及建议,欢迎提出.
一个标准的Electron的应用由两部分组成: 用于在后台运行的主线程项目和在前台运行的ui线程项目. 这两部分是相对独立的, 其间的通讯只能通过ipc(线程间通讯)完成. 在开发时, 这两部分也应该作为两个独立的项目来管理.
这里我们主线程使用纯TypeScript完成主线程项目, 使用Angular + TypeScript完成ui线程项目.
下面的例子中我们希望的源代码目录结构:
首先确保你已经全局安装了Angular CLI,如果没有, 使用下面的命令安装:
1 | npm install -g @angular/cli |
安装后,首先使用以下命令来创建一个空白项目(不包含app)
1 | ng new --createApplication=false --newProjectRoot="./" HelloElectron |
完成后,建议使用vscode打开项目目录(这里为HelloElectron
)来继续我们的下一步操作.
1 | cd HelloElectron |
继续执行以下命令来创建前端应用
1 | ng generate app ui |
在 cli 询问 ? Would you like to add Angular routing? (y/N)
时, 输入y来添加路由, 其它选项按需选择.
以上命令跑完后, 运行ng serve --open
应该可以在浏览器中看到angular的hello world页面.
接下来,打开angular.json
修改生成设置.
outputPath
为dist/app/ui
outputHashing
为none
打开ui/src/index.html
, 修改base href:
1 | <base href="/"> |
安装以下必备库
npm install --save-dev electron
npm install --save ngx-electron
npm install --save-dev @types/node
npm install --save-dev electron-builder
PS: 如果你深受The Girl Friend Wall
困扰的话, 安装Electron时post-install部分可能会卡非常非常非常久(npm需要下载90MB左右的Electron包). 此时可以参考http-proxy设置代理.
首先, 创建目录core/
, 在之中创建tsconfig.json
, 内容参考如下
1 | { |
创建tslint.json
,配置可自行按需设定,或直接复制ui/tslint.json
中的内容.
创建index.ts
作为整个Electron应用的入口点, 内容如下
1 | import * as path from 'path'; |
打开package.json
, 将script节替换为以下内容:
1 | "scripts": { |
首先请确保你已经安装了electron-builder在package.json中添加build
节
1 | "build": { |
有关以上json的更多信息,可参见Configuration.
然后在script节添加publish:
1 | "publish": "cp package.release.json dist/app/package.json && electron-builder", |
接下来,创建package.build.json
, 内容参考如下
1 | { |
在dependencies
中,添加需要打包到最终应用的node库.有关双package.json结构, 可参考此文档.
运行以下命令即可打包:
1 | npm run clean |
打包结果会保存在dist/pack
创建一个服务,名为NodeService, 内容如下:
1 | import {Injectable} from '@angular/core'; |
接下来,就可以通过注入NodeService
并以nodeService.fs
来调用node中的fs了.
这部分目前我还没有什么好的解决方案,如果米娜桑有解决方案欢迎在下面提出QAQ
]]>ModernMessageBoxLib is a WPF library in .Net 4.5By using ModernMessageBoxLib, you can create a ModernMessageBox with a single code.
We are strongly recommend you to use Nuget to import the package.Run this command in Package Manage Console:
1 | PM> Install-Package ModernMessageBoxLib |
(See more in Nuget)
Or you can download it on Release Page.
Before start using, you should specify Language and Background and Foreground.See
QModernMessageBox.MainLang
QModernMessageBox.GlobalBackground
QModernMessageBox.GlobalForeground
Example:
1 | QModernMessageBox.MainLang = new QMetroMessageLang() { |
In this example, The button text of the ModernMessageBox set to Chinese and Background set to white with 60% opacity and Foreground set to Black.
Those setting will use as default in ModernMessageBox.
The default Background in MessageBox is Black, 60% Opacity and the Foreground is White
The default lang is in English
In background setting, you can use a color with not fully solid.In this way, the window will have a Gaussian Blur background in Win10 1803+In win7/8/8.1 or early version of win10, it will still use the solid color as background.If you don’t want a gaussian blur, just set the color solid.
In common cases, you can create a MetroMessageBox with the following code
1 | QModernMessageBox.Show("The quick brown fox jumps over the lazy dog.", "hello world",QModernMessageBox.QModernMessageBoxButtons.YesNoCancel,ModernMessageboxIcons.Warning); |
Or using the QT way:
1 | QModernMessageBox.Warning("The quick brown fox jumps over the lazy dog.", "hello world"); |
Customize:
1 | var msg = new ModernMessageBox("The quick brown fox jumps over the lazy dog.\n", "hello world", ModernMessageboxIcons.Info, "CSharp", "Java", |
Before start using, you should specify Background and Foreground.See:
IndeterminateProgressWindow.GlobalBackground
IndeterminateProgressWindow.GlobalForeground
Usage:
1 | var win = new IndeterminateProgressWindow("Please wait while we are installing the virus into your computer. . ."); |
See more in the XML document comment.
Using this library means you agree the MIT Licence.Build with ❤ By Saber0905 in SakuraTrak Studio
]]>Github Release下载 Download from Github Release
你也可以从ci下载最新的非正式发布版本
you can download the newest developing version from our CI.
Saber’s Colorful Startmenu Version:1.2 (release 1.2)
作者:EdgeNeko
by EdgeNeko
仅支持Win10操作系统
Only Windows 10 is supported.
本程序可以通过修改快捷方式文件下的visualelementsmanifest.xml对开始菜单图标进行定制
This program can change the app logo in start menu by changing the visualelementsmanifist.xml file.
本程序部分图标取自 Windows 9 Icons 作者: dtafalonso
Icon resource is from WIndows 9 Icons (by dtafalonso)
See also: dtafalonso.deviantart.com/art/Windows-9-icons-359505915
背景:取自b站,如果你知道原作者可以在github反馈。
Background is from bilibili and you can tell me if you know the author.
基于C# WPF .Net Framework 4.6.2 使用Visual Studio 2017 Community编译
Base on C# WPF .Net Framework 4.6.2. Build with Visual Studio 2017 Community
本程序开放源代码,任何人可以免费散布/重新编译本程序,如需下载源代码,请前往Github页面。
本程序使用MIT许可协议.
Licensed under MIT License.
开发不易,请作者喝瓶肥宅快乐水吧.
Support us!(●’◡’●)
支付宝 | 微信 |
---|---|
更详细的About Me页面在计划中先看看GitHub Profile中的介绍吧()
1 | import {EdgeNeko} from 'Earth/Nekos'; |
📔 A grade-2 college student in SCUT Software Engineering Academy.
⌨ A member in AiursoftWeb, an organization focusing on open platform and open communication.
✉ Email Me | 💻 Official Website | ☁ GitHub | 📺 Bilibili | ✈️ Discord | 🗨 Kahla | 🐸More
Cover PixArt: pixiv 73492057
]]>