关于 elmagnifico | 云浅雪

程序员,架构师,无人机集群表演设计师,嵌入式工程师,maya插件开发者,多智能体研究者,独立游戏爱好者。

RSS 地址: http://elmagnifico.tech/feed.xml

请复制 RSS 到你的阅读器,或快速订阅到 :

elmagnifico | 云浅雪 RSS 预览

PHP

2024-09-06 00:00:00

Foreword

传闻中天下第一的语言,试一下服务器部署,没想到这么困难,老古董还是有点难啊

PHP

部署

先安装PHP,2021 年开始,Ubuntu 官方不再支持 PHP 5.6 版本的维护和更新,因此如果需要在 Ubuntu 上安装 PHP 5.6,则需要使用第三方的 PPA(个人软件包归档)来进行安装

sudo add-apt-repository ppa:ondrej/php
sudo apt-get update
sudo apt-get install php5.6
php -v
PHP 5.6.40-78+ubuntu24.04.1+deb.sury.org+1 (cli) 
Copyright (c) 1997-2016 The PHP Group

好像fpm不这么装也行,5.3.3以后集成了fpm,本身是用来管理的

apt-get install php5.6-fpm
systemctl status php5.6-fpm

检查apache服务启动

systemctl status apache2.service 

内网地址,可以看到页面了

http://10.10.2.24/

替换一个PHP的index看下

<!DOCTYPE html>
<html>
<body>

<h1>我的第一个 PHP 页面</h1>

<?php
echo "Hello World!";

?>

</body>
</html>

到这里已经可以正常显示启动了

数据库

sudo apt install php5.6-mysql
docker pull mysql:5.6
docker run --name user_database -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 -d mysql:5.6
<?php
// 准备连接参数
$servername = "localhost";
$servername = "127.0.0.1";
$username = "root";
$password = "123456";
$dbname = "user_database";
 
// 创建数据库连接
$connect = mysqli_connect($servername, $username, $password, $dbname);
 
// 检查连接
if (mysqli_connect_error()) {
die("连接失败: " . mysqli_connect_error());
}
 
// 选择数据库
if (mysqli_select_db($connect, $dbname)) {
echo "数据库连接成功";
} else {
echo "数据库连接失败";
}
 
// 关闭连接
mysqli_close($connect);
?>

测试是否可以连接到数据库,目前没有问题了

Apache2

Apache2和之前的不太一样,配置文件都改变了

ports.conf中是apache监听的端口

# If you just change the port or add more ports here, you will likely also
# have to change the VirtualHost statement in
# /etc/apache2/sites-enabled/000-default.conf

Listen 80

<IfModule ssl_module>
        Listen 443
</IfModule>

<IfModule mod_gnutls.c>
        Listen 443
</IfModule>

默认apache的虚拟主机是/etc/apache2/sites-available/000-default.conf

<VirtualHost *:80>
        # The ServerName directive sets the request scheme, hostname and port that
        # the server uses to identify itself. This is used when creating
        # redirection URLs. In the context of virtual hosts, the ServerName
        # specifies what hostname must appear in the request's Host: header to
        # match this virtual host. For the default virtual host (this file) this
        # value is not decisive as it is used as a last resort host regardless.
        # However, you must set it for any further virtual host explicitly.
        #ServerName www.example.com

        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html

        # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
        # error, crit, alert, emerg.
        # It is also possible to configure the loglevel for particular
        # modules, e.g.
        #LogLevel info ssl:warn

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        # For most configuration files from conf-available/, which are
        # enabled or disabled at a global level, it is possible to
        # include a line for only one particular virtual host. For example the
        # following line enables the CGI configuration for this host only
        # after it has been globally disabled with "a2disconf".
        #Include conf-available/serve-cgi-bin.conf
</VirtualHost>

类似nginx的config文件,设置域名和端口等等相关代理设置

apache2.conf中的是apache的全局设置,比如是否支持SSL,映射目录是什么

Summary

一个奇怪的问题php里localhost和127.0.0.1竟然不一样,识别不了localhost,查了一下大概是由于php.ini中缺少了默认sock的方式,localhost是一种特殊传递数据的方式,并不会经过socket

Quote

https://www.runoob.com/w3cnote/php-basic-summary.html?source=1

https://blog.csdn.net/m0_52985087/article/details/132132219

https://blog.csdn.net/weixin_71993565/article/details/140336762

https://blog.tag.gg/showinfo-13-35867-0.html

再破吉尼斯世界纪录

2024-09-05 00:00:00

Foreword

再破一次吉尼斯世界记录,然而还不止于此。吉尼斯也会撞车,这谁敢信?不仅仅撞车,某一个类似的记录在连续一个月内被连破五次,这是巧合还是故意的?

吉尼斯

image-20240906010618517

Most Unmanned Aerial Vehicles (UAVs) airborne simutaneously

现在已经无法回查到4年前的那条记录了,应该是出现了冲突,所以所有此条记录都不存在了,只有曾经的官方新闻证明曾经破过。

Most remote controlled multirotors/drones airborne simultaneously

现在是使用这条记录进行平替,以前的描述和标准其实都有点太过轻松了,而且也有很多不合理的点,特别是大架次以后还要人数,这个就非常扯蛋,以前三五千人数也就算了,这都快破万了,人数已经很不靠谱了。

https://www.guinnessworldrecords.cn/search?term=%2A

通过吉尼斯的查询入口,可以查到大部分记录,有一部分需要注册登录以后才能查询

这次破的是:

the largest image formed by multirotor/drones

image-20240906010421956

如果有相似团队或者个人挑战同一个记录,特别是商业目的的,吉尼斯会锁定这个词条大概一个月左右的时间,给予充分的宣传时间,如果是挑战不同记录,那就没啥错峰的操作了

还好这次破纪录可以反向逆推,数没起飞的就行了,实际数量也可以直接参考地面站的数值,不需要弄一堆第三方志愿者来数飞机了,太傻了。

四年前预言压力在网络上,大概极限是在7500左右,这次直接就破到了7598,刷新了最大架次,而事实证明这个数量还不是极限,还能再往上顶。

image-20240906010741842

7598之后,就是7998,这也算是最短的记录了,破完第二天别人就又破了,起了个大早赶了个晚集

image-20240906011313776

再接着8100,很烦,本来这个东西在这个级别再比起来就没啥意思了,但总有人在卷,你就得更卷,所以下次就是五位数了

image-20240906011437255

Summary

迭代了2代产品,才勉强打过别人3年前出的产品,进步的速度肉眼可见的慢。

拿着4年后的产品跟别人三年前的产品比较,确实有所进步,总算领先了那么一点点,但也仅此而已了

Git LFS

2024-08-28 00:00:00

Foreword

之前选过一些资产管理软件,但是都不够好,当时遗漏了Git LFS,这里再补充测试一下

Git LFS

https://github.com/git-lfs/git-lfs

Git LFS的客户端和Git不同,但是可以使用相同的命令完成Git操作,其实LFS的底层原理挺简单,就是通过Git的时候进行回调,如果是LFS匹配的文件就进入到了LFS提交流程

将所有stp结尾的文件,加入到追踪中

git lfs track "*.stp"
git lfs track "*.CATDrawing"
git lfs track "*.CATPart"
git lfs track "*.dxf"

lfs文件追踪是加在.gitattributes文件中的

git add .gitattributes
git commit -m "track *.stp files using Git LFS"

lfs文件追踪是加在.gitattributes文件中的

git add .
git commit -m "add stp"

查看追踪文件

git lfs track

下载包含lsf的仓库时也需要加上lfs的标签

git lfs clone xxxx

迁移

把原来git代码中大文件变成lfs中存储

git lfs migrate import --include="*.stp" --everything

问题

$ git push -u origin master
Remote "origin" does not support the LFS locking API. Consider disabling it with:
  $ git config lfs.https://e.coding.net/xxxx/gitlfs/gitlfs.git].git/info/lfs.locksverify false

可能会出现以上提示,这个是服务端不支持文件锁定,所以需要配置一下让服务端关闭即可

测试

image-20240829225227600

经过测试,1.11GB的文件,比较大的文件加入lfs以后,git add 命令会快很多

上传和下载就取决于网络和服务端限制了,正常使用似乎问题不大。

coding似乎5分钟左右就能完成2.28G的仓库上传,40秒不到就能把整个仓库完全拉下来,完全够用了

大部分硬件仓库和结构仓库,不包含一些七七八八的东西的话,用Git lfs管理足够。

image-20240830100229470

配合SourceTree 给小白使用也非常简单

LFS服务器

Git LFS,coding里是标配了20G空间,不占用原有代码空间,Gitee里只有1G基本等于没有,必须要私有部署才行

GitLab也支持LFS,不过有一些要求

开源的LFS存储服务器,据说Github也是基于这个二次开发的

https://github.com/git-lfs/lfs-test-server

修改.lfsconfig文件,增加lfs服务器地址

  [lfs]
    url = "http://localhost:8080/"

弹性LFS,使用一些对象存储或者是云盘实现LFS服务

https://github.com/zhxxch/git-lfs-one

Gitea

image-20240830164326561

https://gitee.com/gitea/gitea

Gitea更像是一个简化版的Gitlab,界面干净一些

Gitea和其他DevOps的对比

https://docs.gitea.com/zh-cn/installation/comparison

SVN

https://www.visualsvn.com/

如果只是普通的SVN本地管理是免费的,但是SVN的服务端是收费的

VisualSVN Server

https://www.visualsvn.com/server/

image-20240830170158664

VisualSVN是按照用户数收费的,买断制,所以可以根据人员决定价格,服务器自己出就行了,不过一次性付费只有12个月的更新和维护时间,后续再更新需要再次付费。

VisualSVN也有社区版本,社区版可以给15个人使用

Summary

大部分情况LFS+Gitlab可以解决多数问题

Quote

https://coding.net/help/docs/admin/pay/newprice.html

https://coding.net/help/docs/repo/git/lfs.html

https://zhuanlan.zhihu.com/p/511750788

https://zhuanlan.zhihu.com/p/146683392

https://gitee.com/help/articles/4235#article-header4

https://forcemz.net/git/2017/04/16/Moses/

https://forcemz.net/git/2018/07/15/GitLFSRethinking/

https://cloud.tencent.com/developer/article/1010589

https://www.escapelife.site/posts/92ef32ff.html

https://juejin.cn/post/6844903791855140872

https://blog.inkroom.cn/2023/02/27/10J1G9S.html

东北见闻

2024-08-19 00:00:00

Foreword

记录一下东北见闻

长春

image-20240819213804870

长春是吉林的省会,很奇怪为什么不是吉林,吉林其实离长春很近,只有一百多公里。吉林历史上确实是吉林的省会,后来伪满洲大力发展长春,让长春成了省会的潜在竞争者,1953年长春成了直辖市,吉林还是省会,从1954年开始长春成为了吉林省会,自此就再也没变过了。

长春比较有名的景点:

image-20240819215119517

东北的衰败,来到长春,确实很明显,特别是还刚巧去了长春的老城区,人民广场附近。地图上看起来像是市中心,其实实际到了以后,有点黑灯瞎火。周围没有很多高楼,更多的是黑灯的老楼,像是很久都没有人住了。

附近的门店也有很多关门很久很久了,人烟稀少。出租车司机说新城区人多一些,老城区基本没啥人了。到达的比较晚,也没啥吃饭的门店了,只有路边的烧烤,确实符合东北的风格,价格很低。

延吉

image-20240819220745267

延吉城区比较小,繁华路段基本就集中在2-3公里的一条长街上。印象最深刻的就是打车贼便宜,5块的起步价,到哪里都是5块。可能正好处于旅游旺季,逆天的酒店价格,比深圳贵1.5倍左右。房价几千到一万多,在这样的小城市里也算是有点高的,招牌上基本都是中韩双语,路上遇到的人说韩语的也非常多。

延吉的景点都比较一般,甚至说有点寒酸:

大概太阳下山后,中心老城区里非通行的广场上,摆摊、跳舞、烧烤、踢毽子、按摩,生活气氛浓郁。但总体都是老头老太太了,甚至还能看到营业的练歌房,老头老太太刚吼完出来,年轻人也不知道去了哪里。

百货大楼、地下街、防空洞,旋转大门,这些曾经老旧的东西,在这里还能看到

延吉作为距离长白山最近的城市,导致很多人去长白山玩,顺道被忽悠来延吉逛一逛,顺带带动了延吉的酒店。

延边大学

延边大学从正门进入需要提前预约,预约也很简单,微信搜索延边大学小程序-校内通行信息登记系统即可,简单就能预约到了,扫人脸进门

延边大学如果是从侧面进入是不需要预约信息的,跟学生一样走进去就行了

image-20240831220816978

延边大学9.7号才开学,但是新生军训8.17已经提前开始了,操场上很多训练的方队。看了一下开学时间,延边大学也有小学期,暑假也是8月份才放的

学校里自习桌还挺高级的,自带小米50w无线快充,挺高级的

image-20240831220837330

学校里可以参观的比较少,一个博物馆,一个抗联馆,前者是类似校史馆,后者是红色文化宣传教育馆。人稍微多一点的是游泳馆,似乎是对外开放的,买票就能进,而且很大。

学校食堂挺便宜的,都正常开放了,偏远角落还有一个咖啡文化馆,不过基本没啥人。

总体来说学校不是特别大,一下午就足够逛完了,大部分地方都没啥看点,再加上学生没返校,路人很少,只能追忆一下以前的校园生活。

长白山

长白山分为西坡和北坡,无论是哪边,都需要在天气好的情况下去,否则有可能封山

长白山如果隔天去,可能会遇到买不到票,然后去咸鱼找黄牛,黄牛说要明天19点以后给票或者当天19点以后给(巨大坑点),一张票加个40左右。

官方票务显示都没有票,但是真的等到了第二天大概18点以后,就会发现官方放票了。大多数票应该是提前被旅行社或者黄牛拿走了,导致官方一直显示是0,等时间到了,一放出来几千近万张票就来了,完全没必要加钱。

冬季去西坡,夏季去北坡,从延吉出发去长白山还是挺远的,有个大概100多公里。长白山本身所在就是二道白河镇(基本就是为长白山旅游住宿的小镇),实际去北坡行程是先到到了二道白河镇,买了北坡门票,然后乘坐官方大巴上山,大概50分钟左右到达山腰吧。转乘15分钟的小车,可以到达山顶,观赏天池。

image-20240828152805941

山上观看天池的地方很小,人很多,除了看、拍照以外基本没有啥额外的娱乐活动了

image-20240828152829256

隐约可以看到对面这条小路,应该就是朝鲜了

image-20240828153018367

山腰下来以后的其他景区,基本没啥看头,温泉只有一点点,没啥给你接触的机会;大瀑布不开放;岳桦栈道,也一般,纯走路没啥内容;小天池,还没村里的鱼塘大,去不去都那样;

绿渊谭,也是个小水池+小瀑布,观赏性实在是太低了,至于其他的人造景区、人造园林,那就更没意思了。

总的来说长白山也就天池值得一看,其他地方都太一般了,人工痕迹过重了,长白山大部门门票基本都是给了车票,全程都是景区内车接车送,当天景区内一共坐了6次车,在不同景点直接往返。

图们

从延吉到图们不到30公里,一小时不到就能到了。图们,曾经可以去朝鲜,是和朝鲜贸易的口岸,不过目前已经被废弃了,除了看看,没啥可玩点了,想去到朝鲜从这里也是完全不可能的了。

image-20240901235208851

口岸界碑

image-20240901235659983

25买个门票,就可以登上口岸顶

image-20240901235232715

遥望对面的朝鲜,还是相当破败的,楼房里烧柴火,玻璃都没有,用塑料布当玻璃,正中大楼上还挂着将军一家的头像,很是嘲讽

image-20240901235302623

图们口岸广场上玩门球的大爷和大妈,看了一场精彩的逆转,门球还挺少见的

珲春

珲春,一眼望三国,朝鲜+俄罗斯,珲春距离海参崴(曾经地理课本里经常出现的地方)很近了,可以直接从珲春出关进入俄罗斯,听说可以在俄罗斯打靶玩,目前还是免签的,很容易就可以到对面去看看了,不过除此以外珲春好像就没啥了

Summary

东北衰败,挺可惜的,人都没了,还谈什么振兴呢。看到了这样的小城市,再对比深圳的灯火通明。而小城市里的闲适、慵懒,在深圳怎么也找不到。如果不是为了欲,不是为了追求,为了卷,在小城市里work-life balance也许是不错的选择,不过那样的生活有点没意思,一眼就能望到头。

一路看下来,整体消费还是比较低的,深圳满街的咖啡奶茶店,在这里就很少,唯一常见的就是蜜雪冰城。

快要接近8.20了,小小延吉,一个联名咖啡瞬间就没了,hhhh

回到深圳以后,同比深圳12点还灯火通明,延吉8点就没啥人了,街边店铺都关了,人才是发展的动力啊

在线画图工具

2024-08-06 00:00:00

Foreword

测评一下在线画图工具,看还有没有比Draw.io更好用的,能否有更好的替代品

Draw.io

image-20240806233222128

https://app.diagrams.net/

https://www.drawio.com/

优点太多了

问题

本地部署

# 创建 Draw.io 数据存放目录
mkdir /docker/Drawio -p && cd /docker/Drawio

# 使用 Docker-Cli 运行 Drawio 容器
docker run -dit --name=drawio -p 8080:8080 \
-v drawiojs:/usr/local/tomcat/webapps/draw/js/ \
--restart=always jgraph/drawio

这种方式更好一些,直接把配置文件存在了本地

docker run -dit --name=drawio \ 
-p 本机端口:8080 \ 
-v /docker/Drawio/PostConfig.js:/usr/local/tomcat/webapps/draw/js/PostConfig.js \ 
-v /docker/Drawio/PreConfig.js:/usr/local/tomcat/webapps/draw/js/PreConfig.js \ 
--restart=always jgraph/drawio

访问路径,测试

http://服务器IP地址:8080

确认没问题,再套上caddy,自动SSL就行了

draw.xxxx.com {
    reverse_proxy 127.0.0.1:8080
}
https://app.diagrams.net/?lang=es

改进入语言需要加一个后缀,否则改不掉

配置修改

如果要修改服务器默认配置可以通过修改Preconfig.js文件实现

先把原配置复制出来

docker cp drawio:/usr/local/tomcat/webapps/draw/js/PreConfig.js ./

image-20240809193901354

添加默认中文

urlParams['lang'] = 'zh'; //设置默认中文

同样的如果想修改默认配置,也可以通过添加属性来实现

window.DRAWIO_CONFIG = {"language":"zh","configVersion":null,"customFonts":[],"libraries":"general;uml;er;bpmn;flowchart;basic;arrows2","customLibraries":["L.scratchpad"],"plugins":[],"recentColors":[],"formatWidth":240,"createTarget":false,"pageFormat":{"x":0,"y":0,"width":827,"height":1169},"search":true,"showStartScreen":false,"gridColor":"#d0d0d0","darkGridColor":"#424242","autosave":false,"resizeImages":null,"openCounter":4,"version":18,"unit":1,"isRulerOn":false,"ui":"","darkMode":false,"pages":true,"defaultGridEnabled":false,"defaultPageVisible":false};

如果需要修改默认导出的url,可以修改BASE_URL

window.DRAWIO_BASE_URL = 'https://xx.com';

反向复制回去

docker cp ./PreConfig.js drawio:/usr/local/tomcat/webapps/draw/js/PreConfig.js

客户端修改

默认配置可以随便修改,这种只会修改个人的配置,根据浏览器缓存绑定,并不会修改服务端

https://www.drawio.com/doc/faq/configure-diagram-editor

{
  "language": "zh",
  "configVersion": null,
  "customFonts": [],
  "libraries": "general;uml;er;bpmn;flowchart;basic;arrows2",
  "customLibraries": [
    "L.scratchpad"
  ],
  "plugins": [],
  "recentColors": [],
  "formatWidth": 240,
  "createTarget": false,
  "pageFormat": {
    "x": 0,
    "y": 0,
    "width": 827,
    "height": 1169
  },
  "search": true,
  "showStartScreen": false,
  "gridColor": "#d0d0d0",
  "darkGridColor": "#424242",
  "autosave": false,
  "resizeImages": null,
  "openCounter": 4,
  "version": 18,
  "unit": 1,
  "isRulerOn": false,
  "ui": "",
  "darkMode": false,
  "pages": true,
  "defaultGridEnabled": false,
  "defaultPageVisible": false
}

比如上面的就是默认中文,关闭默认的网格显示,关闭页面视图,这样看起来就无限大了

私有化存储

Draw.io有一些私有化存储的方案

不过这种都是个人存储,团队私有化的话,比较适合使用gitlab作为存储库,还有一种MinIO作为存储端,这种是DIY的方案

https://github.com/mathcoder23/drawio-minio-oss?tab=readme-ov-file

国内

国内的基本没有免费,除了钱还是钱

PDDON

image-20240806232659144

https://pddon.com/

国产画图工具,但是加载速度是真的慢,基本不具有可用性

MindMaster

亿图图示,国内的在线制图,除了广告,就是弹窗,收费、收费、VIP,单用户1080的天价,打扰了

水平拉连接点会出现bug

image-20240806222308467

ProcessOn

国内的在线制图,问题和MindMaster基本一样,除了广告就是弹窗VIP,免费版本只能在线创建9个图

技术上比MindMaster好一点,界面也清爽一些,剩下的差不多,价格也便宜一些,不过我期望的是免费,这里就不提了。

国外

国外的在线画图,都有一个统一的问题,国内访问困难

Excalidraw

image-20240806223602427

https://excalidraw.com/

Excalidraw 准确说不像是个画图工具,更像画板工具,自由度很高,可以随便画

问题也比较明显,素材库每个人都不一样,没法对齐每个人的,免费功能还是有限

素材种手绘的样式比较多,很可爱,如果要正式场景下就有点难顶,素材库每次导入就是导入所有,而不能部分,有些别扭

私有化部署+修改存储方案

https://github.com/alswl/excalidraw-collaboration

Plant UML

https://plantuml.com/zh/

用代码画图,有一套完整的语法,早期我自己也用,后来发现想让别人理解太难了,可惜,画图而已,不想浪费生命,还是拖拽更好一些

Visio

老牌工具,没啥大问题,但是安装麻烦,体积太大,跟不上时代了

OneModel

image-20240806231322248

https://www.onemodel.app/diagrams/my-diagrams

国外的制图网址,免费版限制很少,可以无限量画,只对工作空间人数有限制

图样的参数相对比较少,可用素材也比较少,素材风格相对比较统一

Tldraw

image-20240806231733749

https://www.tldraw.com/

开源、免费的白板,支持多人共享,类似Excalidraw,但是没有素材库,也完全没有收费的版本

Figma

image-20240806230940263

https://www.figma.com/

Figma更像UI规范的工具,画图也可以,整体简洁清爽,不过还是一样收费才能无限图,否则只能1个图文件

Summary

能打的画图工具太少了,wolai中也不支持draw.io嵌入,但是wolai已经有意向在之后加入draw.io了

Quote

https://blog.alswl.com/2022/10/self-hosted-excalidraw/

https://www.cnblogs.com/wuhanjiayou/p/18145848/Drawio

https://www.erballoon.vip/2024/01/14/dockerbszxhtdrawio/

https://musicfe.com/drawio/

Trilium体验

2024-08-05 00:00:00

Foreword

去年选择了wolai作为团队知识管理工具,之前已经使用过了obsidian,但是对非程序员不够好用,其次没有完善的权限管理,做共享比较麻烦,给出去就是源码,无法做后续管控,wolai基本都能解决这些问题。

但是也有一些不够好的点,性能上对比Typora或者一般的编辑软件确实弱了一些,文档书写为了普适性,更适合一般人用,而没有更专业的模式,或者说更适合程序员使用的模式,这点不够好。

其次wolai价格不便宜,偶尔还是有一些小bug

Trilium的效果有点出乎意料

Trilium

image-20240805220947547

https://github.com/zadam/trilium

无意间发现了Trilium,这不就是一个obsidian+git+vps+图床+drawio的一个应用嘛,是不是可以取代wolai

image-20240805221040465

image-20240805221103952

特点

试用

image-20240805220923061

https://github.com/zadam/trilium/releases/tag/v0.63.7

建议先从windows开始,比较简单,解压就能用了

语言包

https://github.com/Nriver/trilium-translation/releases

默认Trilium是英文的,而且没有其他语系可以切换

如果已经打开过原版,需要删除缓存才能切换到中文版

你运行过原版的Trilium程序,系统里有英文版的缓存,请关闭trilium, Windows系统删除这个目录C:\Users\用户名\AppData\Roaming\Trilium Notes, Linux系统删除这个目录~/.config/Trilium Notes/ 。再启动Trilium就是中文的了。

image-20240805222234053

image-20240805222435755

这个前置块按钮和wolai好像

不过这个markdown好像不标准,没有一级标题,只有二级到六级,wolai是没有五六级,咋就是不完美呢

主题

仔细用了一下trilium这个默认主题也太难看了

image-20240805223356287

特别是把原本的文章转过来,默认的这个markdown渲染,这都什么玩意

修改主题,使用SinkeyTheme,总算是舒服一点了

https://github.com/sinkey100/trilium-theme/blob/main/README_CN.md

image-20240805223848171

难受的点就是目录里的这个123456是什么鬼啊,很不想要

转换blog

https://www.ankia.top/3LdIi2f30Pan

https://github.com/dvai/Ankia-Theme

使用Ankia的博客主题,直接开启分享就可以看到效果了

image-20240805224742680

image-20240805224646201

这渲染出来的效果还不错哎

image-20240805224826120

已有文章拖进去,立马就能看到了

集成draw.io

https://www.shmaur.com/drawioInstall.html

https://github.com/SiriusXT/trilium-drawio

img

这简直跟VS Code一样了,直接集成各种JS应用

更多探索

https://github.com/Nriver/awesome-trilium

这里有更多主题、插件等等介绍

问题

其他

dokuwiki,作为wiki好像也打不过Trilium

Joplin,缺少树型结构,文档编辑类似论坛发文章的东西,没有什么亮点

tiddlywiki,无markdown,论坛式的,虽然支持双链、图片,但是交互逻辑过于老气了

Summary

Trilium通过小小的DIY,已经超出预期了,有点心动的感觉,唯一的缺点在于编辑方式比Typora差太多了

Quote

https://sspai.com/post/85515

https://post.smzdm.com/p/avp2w9m4/

https://www.ankia.top/sfDk7s6iFuno

https://post.smzdm.com/p/ao95lw4n/

https://www.ankia.top/

VS Code插件入门二

2024-07-31 00:00:00

Foreword

第二步,通过API实现一点点小功能

VS Code插件入门

VS Code的API目录,可以先按照大类查找,然后再找下面具体的接口

https://code.visualstudio.com/api/references/vscode-api

VS Code的API例子在下面的地址中,相关的接口可以直接看一下例子里是怎么用的,效果怎样

https://github.com/microsoft/vscode-extension-samples

具体使用进入到对应的例子目录下,然后安装包,就可以启动了

npm install
F5

获取文件路径

首先是通过插件获取到当前打开文件路径在哪里

vscode.window.activeTextEditor.document.uri.path

image-20240731220418647

试了一下,切换文件,显示没有问题,如果没有打开路径倒是会报错,需要异常处理一下

		if(vscode.window.activeTextEditor == undefined)
		{
			console.log("cant find active text editor")
		}
		else
		{
			console.log(vscode.window.activeTextEditor.document.uri.path) 
		}

还有一种路径,可能是需要当前打开的工程路径,可以通过下面这种方式获取

console.log(vscode.workspace.workspaceFolders[0].uri.fsPath)

创建一个新的显示区域

workbench-contribution

在创建新的显示区域之前,先要知道一下VS Code本身有哪些区域可以用来自定义

最左侧的是Tree View Container,这个就比较像快捷菜单

接着就是左侧的树型大纲视图,这里一般以大纲或者目录的形式显示一些辅助信息

最底下的就是状态栏,可以添加一些当前工程或者插件的状态信息,比如进度条等

最右侧较大范围的就是Webview

Webview,页面视图,简单理解就是HTML中的一个iframe,可以嵌入一个页面进来,但是这个嵌入的页面是个相对安全的沙河,只有从外部控制Webview的内容,而Webview反向控制就比较困难。

所以一般可以通过Webview调用markdown、gpt、copilot等等第三方的交换界面

Webview在VS Code中,可以反向hook editor event,比如撤销、重做、保存,这样就让你在VS Code中实现一个某种编辑器成为可能。

Webview一般有三种用法:

这里参考vscode-extension-samples\webview-sample的例子,看他是如何让小猫在webview中写代码的

image-20240801000910003

export function activate(context: vscode.ExtensionContext) {
	context.subscriptions.push(
		vscode.commands.registerCommand('catCoding.start', () => {
			CatCodingPanel.createOrShow(context.extensionUri);
		})
	);

注册命令主要就是调用了这个CatCodingPanel的实例化

image-20240731235837019

先缩起来看一下,CatCodingPanel这个类主要的几个方法,很明显的是CatCodingPanel使用的是vs的内部pannel对象vscode.WebviewPanel

		// Otherwise, create a new panel.
		const panel = vscode.window.createWebviewPanel(
			CatCodingPanel.viewType,
			'Cat Coding',
			column || vscode.ViewColumn.One,
			getWebviewOptions(extensionUri),
		);

停在接口上,就能很清晰看到4个参数的作用

function window.createWebviewPanel(viewType: string, title: string, showOptions: vscode.ViewColumn | {
    readonly viewColumn: vscode.ViewColumn;
    readonly preserveFocus?: boolean;
}, options?: vscode.WebviewPanelOptions & vscode.WebviewOptions): vscode.WebviewPanel
Create and show a new webview panel.

@param viewType — Identifies the type of the webview panel.

@param title — Title of the panel.

@param showOptions — Where to show the webview in the editor. If preserveFocus is set, the new webview will not take focus.

@param options — Settings for the new panel.

@return — New webview panel.

发现这个函数好像根本没有说具体内容是怎么显示出来的

那就看一下构造函数的内容

	private constructor(panel: vscode.WebviewPanel, extensionUri: vscode.Uri) {
		this._panel = panel;
		this._extensionUri = extensionUri;

		// Set the webview's initial html content
		this._update();

		// Listen for when the panel is disposed
		// This happens when the user closes the panel or when the panel is closed programmatically
		this._panel.onDidDispose(() => this.dispose(), null, this._disposables);

		// Update the content based on view changes
		this._panel.onDidChangeViewState(
			e => {
				if (this._panel.visible) {
					this._update();
				}
			},
			null,
			this._disposables
		);

		// Handle messages from the webview
		this._panel.webview.onDidReceiveMessage(
			message => {
				switch (message.command) {
					case 'alert':
						vscode.window.showErrorMessage(message.text);
						return;
				}
			},
			null,
			this._disposables
		);
	}

可以看到显示内容是靠update初始化的,最终调用到_getHtmlForWebview,这个里面基本上就是封装了一个HTML页面

image-20240801003101086

onDidChangeViewState就可以认为是页面改动触发的刷新,比如分屏显示,缩小或者放大webview大小

onDidReceiveMessage添加了一个事件回调,收到某些命令时进行弹窗显示

Webview的生命周期

Webview是有一个生命周期的,并且Webview的句柄是需要你自己保存的,否则这个东西就没人可以控制了。

而Webview同样也需要正确释放,否则就会造成额外的错误

Debug

Developer: Toggle Developer Tools可以看到这个webview的界面,就能清楚的看到这里其实嵌入式了iframe

image-20240801220306490

内部的网页就是cat coding

image-20240801220330253

加载本地资源

function getWebviewOptions(extensionUri: vscode.Uri): vscode.WebviewOptions {
	return {
		// Enable javascript in the webview
		enableScripts: true,

		// And restrict the webview to only loading content from our extension's `media` directory.
		localResourceRoots: [vscode.Uri.joinPath(extensionUri, 'media')]
	};
}

需要注意在getWebviewOptions中的localResourceRoots中会限制可以读取的资源路径,比如这里就限制必须是在插件路径的media文件夹内才可以


		const scriptPathOnDisk1 = vscode.Uri.joinPath(this._extensionUri, 'giphy.gif');
		//const scriptPathOnDisk1 = vscode.Uri.joinPath(this._extensionUri, 'media', 'cat.gif');

		const scriptUri1 = webview.asWebviewUri(scriptPathOnDisk1);

如果后续读取使用的是非media路径,webview会显示不了对应的gif

通信

	context.subscriptions.push(
		vscode.commands.registerCommand('catCoding.doRefactor', () => {
			if (CatCodingPanel.currentPanel) {
				CatCodingPanel.currentPanel.doRefactor();
			}
		})
	);	
	public doRefactor() {
		// Send a message to the webview webview.
		// You can send any JSON serializable data.
		this._panel.webview.postMessage({ command: 'refactor' });
	}

插件可以通过postMessage发送消息给实例化的webview,进而实现一些控制

    // Handle messages sent from the extension to the webview
    window.addEventListener('message', event => {
        const message = event.data; // The json data that the extension sent
        switch (message.command) {
            case 'refactor':
                currentCount = Math.ceil(currentCount * 0.5);
                counter.textContent = `${currentCount}`;
                break;
        }
    });

media/main.js中可以看到对应事件的响应代码

反过来,webview也可以通过vs插件接口发送消息给插件

    setInterval(() => {
        counter.textContent = `${currentCount++} `;

        // Update state
        vscode.setState({ count: currentCount });

        // Alert the extension when the cat introduces a bug
        if (Math.random() < Math.min(0.001 * currentCount, 0.05)) {
            // Send a message back to the extension
            vscode.postMessage({
                command: 'alert',
                text: '🐛  on line ' + currentCount
            });
        }
    }, 100);

media/main.js中可以看到webview加载的本地js直接调用了vs的api,进行post信息

显示markdown

非常简单直接使用内置的markdown命令实现显示当前激活文档的markdown渲染视图

vscode.commands.executeCommand("markdown.showPreviewToSide", vscode.window.activeTextEditor.document.uri.path);

不过这种方式只能显示一个markdown,而且具体markdown能显示啥,不能显示啥,或者说markdown的扩展,就不是我能控制的了

Summary

第二步ok

Quote

https://liiked.github.io/VS-Code-Extension-Doc-ZH/#/

https://code.visualstudio.com/api

https://stackoverflow.com/questions/39569993/vs-code-extension-get-full-path

https://zhuanlan.zhihu.com/p/693769416

https://www.cnblogs.com/liuxianan/p/vscode-plugin-webview.html

https://code.visualstudio.com/api/extension-guides/webview

VS Code插件入门一

2024-07-30 00:00:00

Foreword

一直有一个插件或者工具的想法,只是有初步的一些点,但还不确定具体能做到什么程度,先拿VS Code的插件来实验一下是否可行

VS Code插件入门

VS Code本身是基于Electron的,所以插件的开发基础自然也就是nodejs+js

先搞懂VS Code的基础架构和插件接口,就可以考虑实现一个小demo看看效果

基于插件入门的文档,预备阶段需要一些TS知识就先跳过,写的时候再学也可以

https://liiked.github.io/VS-Code-Extension-Doc-ZH/#/

看了一下插件API可以实现的功能,以下两点大概是我目前最在意的

构建插件

来一次Hello World准是没错的

https://code.visualstudio.com/api/get-started/your-first-extension

准备

首先安装好代码生成

npm install --global yo generator-code

image-20240730221515733

Hello World

调用脚手架生成代码

yo code

image-20240730221621854

回答一系列问题以后,hellow就生成了,然后根据提示打开一个新的VS Code

image-20240730221718705

提示安装一下插件测试器,并且提示刚才构建的插件过于老了,没关系先玩玩看

image-20240730222854237

自动打开刚才新建的工程,但是此工程实际上可能跑不起来,需要先修改两个内容

直接F5,启动调试,可以看到新起了一个VS Code,尝试看是否有Hello World命令,测试应该是没有的

此时查看测试VS Code的版本号,发现是1.90.2

image-20240730223024752

核对一下package.json中的包代码,发现不一致

  "engines": {
    "vscode": "^1.90.2"
  },
  
    "devDependencies": {
    "@types/vscode": "^1.90.2",

将依赖的包版本修改为对应的VS版本后重启

如果是热修改,VS Code也支持热重启,在调试启动的VS Code使用Ctrl+R就会重新加载修改后的插件,立马就能验证插件了

image-20240730223204740

已经有Hello World命令,并且消息提示正常

主工程的VS Code中可以看到对应的log提示

image-20240730234212706

代码解析

工程结构,相对比较简单

.
├── .vscode
│   ├── launch.json     // 插件加载和调试的配置
│   └── tasks.json      // 配置TypeScript编译任务
├── node_modules        // nodejs需要引用的各种模块
├── test                // 单元测试相关内容
├── .vscode-test.mjs    // 单元测试相关内容
├── .gitignore          
├── .vscodeignore       // vscode工程的忽略文件
├── .eslintrc.json      // 应该是es编译器相关配置
├── jsconfig.json       // js相关配置
├── .gitignore          
├── README.md
├── extension.ts        // 插件源代码
├── package.json        // 插件配置清单
├── tsconfig.json       // TypeScript配置

其他文件基本都是配置或者环境相关文件,主要实现还是在extension.js

// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
const vscode = require('vscode');

// This method is called when your extension is activated
// Your extension is activated the very first time the command is executed

/**
 * @param {vscode.ExtensionContext} context
 */
function activate(context) {

	// Use the console to output diagnostic information (console.log) and errors (console.error)
	// This line of code will only be executed once when your extension is activated
	console.log('Congratulations, your extension "hellow" is now active!');

	// The command has been defined in the package.json file
	// Now provide the implementation of the command with  registerCommand
	// The commandId parameter must match the command field in package.json
	const disposable = vscode.commands.registerCommand('hellow.helloWorld', function () {
		// The code you place here will be executed every time your command is executed

		// Display a message box to the user
		vscode.window.showInformationMessage('Hello World from hellow!');
	});

	context.subscriptions.push(disposable);
}

// This method is called when your extension is deactivated
function deactivate() {}

module.exports = {
	activate,
	deactivate
}

插件注册流程也比较简单,就是激活和反激活,在这两个时间可以做一些注册命令或者安装或者清理环境之类的工作

activate
deactivate

整个插件模块可以暴露的接口,也是可以自定义设计的

module.exports = {
	activate,
	deactivate
}

主要就是调用了两个接口,一个注册命令,一个显示消息

vscode.commands.registerCommand
vscode.window.showInformationMessage

简单理解为向VS Code的上下文中注册了这个接口

context.subscriptions.push

package.json需要重点说明一下,这里面描述了入口是谁,并且插件的版本和他对vscode的版本的要求,这里都是最低版本要求,同时插件的命令也在这里进行了说明

{
  "name": "hellow",
  "displayName": "hellow",
  "description": "",
  "version": "0.0.1",
  "engines": {
    "vscode": "^1.90.2"
  },
  "categories": [
    "Other"
  ],
  "activationEvents": [],
  "main": "./extension.js",
  "contributes": {
    "commands": [{
      "command": "hellow.helloWorld",
      "title": "Hello World"
    }]
  },
  "scripts": {
    "lint": "eslint .",
    "pretest": "npm run lint",
    "test": "vscode-test"
  },
  "devDependencies": {
    "@types/vscode": "^1.90.2",
    "@types/mocha": "^10.0.7",
    "@types/node": "20.x",
    "eslint": "^8.57.0",
    "typescript": "^5.4.5",
    "@vscode/test-cli": "^0.0.9",
    "@vscode/test-electron": "^2.4.0"
  }
}

Summary

第一步ok

Quote

https://liiked.github.io/VS-Code-Extension-Doc-ZH/#/

https://code.visualstudio.com/api

Windows系统异常失焦

2024-07-29 00:00:00

Foreword

遇到一个奇怪的现象,有时候开机以后,会出现失焦的情况,打字经常被中断,各种按键操作突然就失去焦点了

现象

打开任何程序,最明显的就是打开一个记事本,然后按住一个键,默认会一直输入,如果存在失焦,就会被中断,这里只是单纯的失去焦点,并不会切换回桌面或者某个很明显的程序

比较奇怪的是好像都是每天第一次开机会出现,重启一下必然会好。

前面以为是我的键盘、HUB、鼠标等等存在掉驱动和重连接,而就算我全关闭或者全断开这个情况依然会出现

失焦分析

找了半天看到有一个失焦分析的小软件,刚好拿来试试

image-20240729201906432

失焦监控工具放到这里了,防止有一天找不到

https://github.com/elmagnificogi/MyTools/tree/master/LoseFocus

打开以后,如果有程序主动切换焦点,就会被hook到,然后显示具体的句柄和窗体名称,这样就能抓到具体是哪个程序了。

image-20240801214008949

image-20240729203252037

不幸的发现,我抓到的竟然是Chrome,就算完全关闭Chrome也不行。并且这个程序的句柄值一直在变动,相当于是他启动,然后关闭,过一会又再次启动,发现问题,又关闭,如此往复。

Chrome_WidgetWin_0,这个东西基本上是所有用了Electron架构的应用都会产生的窗体,类似网易云音乐、QQNT、VScode等等,这就有点麻烦了

怀疑是最近的chrome升级可能出现了问题,再加上深信服的VPN之前卸载可能没弄干净,重新卸载一下,发现chrome的google账号有需要重新登陆了,重登以后似乎没有问题了

image-20240801214715515

逐一退出右下角程序,发现Autodesk的启动项竟然影响到了这个,这是万万没想到的,这程序已经放了好几年了,第一次遇到。估计可能和哪个程序产生冲突了,才引起来的

其他失焦原因

刚开始大部分看到的都是svchost.exe导致的,这种多数是中病毒了或者是被某些莫名其妙的程序优化修改了注册表,可以通过以下办法恢复

开始-运行-regedit进入注册表,找到HKEY_CURRENT_USER\Control Panel\Desktop下的ForegroundLockTimeout项,把这个值改成10进制的任何6位数以上(系统默认200000毫秒/十六进制30d40)

还有一种比较常见的失焦,是WPS的广告程序,不知道是什么原因导致他无法正常显示了,所以在后台来回切广告页面,导致的失焦。这种卸载WPS或者在设置中取消相关广告权限即可

Summary

万万没想到自动桌,你个浓眉大眼的竟然搞小手段

Quote

https://blog.csdn.net/wuruiaoxue/article/details/46774229

https://www.bilibili.com/read/cv4626259/

https://www.zhihu.com/question/33537889

Jenkins迁移

2024-07-23 00:00:00

Foreword

迁移Jenkins

腾讯云镜像导出

如果腾讯云镜像是windows,无法下载到本地,无论怎么弄都不行,所以只能手动迁移

image-20240723182041459

如果腾讯云轻量镜像是Linux,可以通过几个间接的办法把整个镜像下载下来

  1. 选择轻量服务器,制作镜像
  2. 轻量服务器的镜像菜单中的共享镜像,共享给云服务器CVM
  3. 进入云服务器的镜像菜单,同地域复制,随便复制到一个地方,它就变成了自定义镜像
  4. 此时就可以通过自定义镜像进行下载

image-20240723182058595

Windows Jenkins迁移

首先确保Jenkins版本一致,如果不一致迁移会导致很多错误,还不如直接重建

image-20240723112329435

版本一致以后,看一下老的Jenkins存储路径在哪里

image-202407231122490273

停止jenkins服务,将其整个打包,复制粘贴到新的路径下

找了半天的在线直传,只有这个比较好用

https://www.ppzhilian.com/receiver

image-20240723144628490

启动新的jenkins,理论上和以前是一样的了,可以直接进入,所有配置都一样

配置迁移

如果选择不复制,而是导入导出配置,可以通过jenkins-cli.jar工具包完成

java -jar jenkins-cli.jar -s http://你的服务器:8080/ get-job auth> auth.xml
java -jar jenkins-cli.jar -s http://你的服务器:8080/ get-job auth < auth.xml

还有一种办法,直接复制jobs

linux下目录

/root/.jenkins/jobs
$JENKINS_HOME/jobs

https://www.ppzhilian.com/receiver

Linux Jenkins迁移

Linux 就更简单了,路径比较稳定,直接复制粘贴就行了

Summary

Jenkins自己没有导出或者迁移相关的选项还是挺奇怪的,不过也有可能是docker用多了,迁移起来也不麻烦吧

Quote

https://blog.csdn.net/u010715243/article/details/118518797

https://blog.csdn.net/WatcherNight/article/details/135552420

https://blog.csdn.net/m0_53889456/article/details/132804105