Spiritの小站 https://spiritx.xyz Fri, 26 Mar 2021 00:54:41 +0000 zh-CN hourly 1 https://wordpress.org/?v=6.1.1 使用Rsync整机迁移VPS https://spiritx.xyz/1044.html https://spiritx.xyz/1044.html#comments Thu, 25 Mar 2021 05:55:03 +0000 https://spiritx.xyz/?p=1044
重装时没有lnmp一键jio本?那为何不试试直接迁移所有数据]]>

去年把小站服务器系统换成了ArchLinux,一直正常运行着,我时不时ssh上去 sudo pacman -Syu 一下,后来准备更换小站服务器的服务商,但因系统配置太过麻烦遂搁浅。前几天给手机刷机操作失误,清空了我所有的数据,不过幸好我还有备份的习惯 :机智: :机智:

qqq
在恢复数据时看到我的移动备份硬盘,想着能不能用 rsync 直接把所有数据迁移到新的机器,尝试了一下,还真能实现,步骤也很简单:

两台机器都登录上,装上 rsync,新机器的操作系统不限

新机器准备

mkdir /mnt/new_server/
mount /dev/vda2 /mnt/new_server/
mount /dev/vda1 /mnt/new_server/boot/

/dev/vda 可能在不同主机商那不同,自行 df -h 查看

老机器迁移

rsync -aHAXSz --delete --numeric-ids -e "ssh" --rsync-path="rsync" --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/lost+found","/etc/fstab","/etc/udev/rules.d/*","/etc/network/*","/etc/modprobe.d/*"} / root@新机器i:/mnt/new_server/

使用 -aHAXS 基本包含了所有的文件信息,-z 会在传输数据时压缩,--numeric-ids 不将用户和组id匹配名称
不同系统排除的目录不一样,在--exclude后面自行修改排除目录,也可以尝试 --one-file-system 选项(我没有试过

新机器配置引导和网络

mount --bind /proc /mnt/new_server/proc
mount --bind /sys /mnt/new_server/sys
mount --bind /dev /mnt/new_server/dev
mount --bind /run /mnt/new_server/run
chroot /mnt/new_server
grub-install --target=i386-pc --recheck --force /dev/vda
grub-mkconfig -o /boot/grub/grub.cfg
vim /etc/systemd/network/default.network # 修改为新主机的ip
systemctl restart systemd-networkd

之后重启即可

]]>
https://spiritx.xyz/1044.html/feed/ 8
使用Trilium构建个人知识库 https://spiritx.xyz/1042.html https://spiritx.xyz/1042.html#comments Tue, 02 Jun 2020 00:38:56 +0000 https://spiritx.xyz/?p=1042
筛选了那么多软件,终究还是它打动了我:开源、简洁、高效]]>

信息时代知识的获取变得十分容易,在庞大信息流的冲击下,旧的知识尚在消化中,新的知识已源源不断地涌来,如果没有把获取到的知识整理的习惯,那么很容易迷失在这五彩斑斓的世界里。

前我是没有记笔记的习惯的,就算会记我也不一定会回过头查看我记了什么,我对自己的记忆能力充满自信,这也使我吃过不少亏。算起来,我真正开始记笔记的时间应该是去年开学的时候。我把自己所学到的、值得记录的东西用手机自带的便签记下了,也是那时候,我开始写日记,不是写什么故事,只想记录下生活那些平平淡淡的点滴。渐渐的,我发现便签不适合我,我便开始了寻找……

在体验过众多笔记软件/平台后,我选择了 TiddlyWiki,这也是我用得最久的一款软件,TiddlyWiki 的的确确是一款优秀的程序,但我对于它的一些方面始终不是很满意,所以我并未停止寻找替代品,直到最近发现了 Trilium 。与其它同类软件相比,它具有以下优点:

  • 完全开源,可以自行编译或部署,具有多平台支持
  • 不只是分层级,更可以无限嵌套
  • 加密、历史版本、多媒体……这些该有的都有
  • 有网页剪藏软件(我可以放弃Wallabag了
  • 日记功能,这对我来说是一个重要的功能
  • 可以自定义插件和模板
  • 强大的Attributes 系统
  • ……


惯例,我先上图:

预览

这是一张官方的示例图片,截自客户端内,同时,也是第一次打开时看到的页面,其中包含了一系列使用文档。从图片就可以看出 Trilium 非常简洁、具有很高的辨识度。左边是一棵无限嵌套的文档树,中间是笔记编辑区域,右边是当前笔记的信息,包括笔记标签和关联笔记图表等。

开源,易于部署

开源的优点不用多说,在写这篇文章的时候,恰逢Notion个人版免费了,我也去了解了这款软件,相比之下,我还是喜欢开源的 Trilium 。

release页面上有已经打包好的 Windows、Macos、Linux 以及 Linux Server 软件包,只需下载即可安装,Linux Server 版的 Trilium 是用来同步的,同时也提供了网页写作的前端,我个人是比较偏好于网页端写作的,这也是我选择 Trilium 的一个主要原因。如今我将他部署在了我的树莓派上,如果你的托管服务器也是使用的 aarch64 的系统,可以用我编译的镜像: docker run -d --name trilium -p 8080:8080 -v ~/volume/trilium/trilium-data:/root/trilium-data --restart unless-stoped spirit1431007/trilium-arm ,回车之后数据便永久保存在了 ~/volume/trilium/trilium-data

关系管理

作为知识库,关系可谓是其最重要的一部分,而 Trilium 在这方面做到了极致。

层级

开头提到了,Trilium 支持无限层级,这其实不算是 Trilium 独有,不过它做的很很出色。每一级的文件夹都能写笔记,如果留空的话,就会默认显示该目录下的“子笔记”,不得不说,这种结构非常适合知识库,就像这样:

层级

之前用 TiddlyWiki 虽然也能做到,不过那样得自己新建一个目录列表,且目录列表样式固定,不如 Trilium 来的快。顺带一提,Trilium 是支持随意拖动的,这就方便了我们对每条笔记进行分类整理。

克隆

除此之外,Trilium 还支持一个很赞的功能:Cloning notes。简单来讲,就是我可以把同一条笔记链接到不同的目录里面,而不用在一条条去复制了,在编辑这条笔记时,所有的克隆版本都会更新,删除时也能选择是否全部删除。

引用

知识之间是有联系的,作为知识库,免不了知识之间的引用和参考。与其他笔记应用中复杂的引用过程相比,Trilium 引用笔记十分方便——只需简单地输入一个 @ ,之后会在 @ 后面打字就会搜索并插入通往其他笔记的链接

引用

不止如此,在链接了其他笔记之后,Link Map 组件也会实时更新,可以在右侧栏目看到

Link Map

可以随意拖动,直到看起来满意为止。

关系图

Relation Map 是 Trilium 的一种笔记形式,有点类似于思维导图

Relation Map

每个节点对应一则子笔记,鼠标悬停时可以预览,点击即可编辑。另外,比较有特色的是可以给关系加上标注。

属性

Attributes 是每一个Trilium note的属性,分为4类:

  • Labels(标签) - 简单的键值
  • Relation(关系) - 指定到另一条笔记的关系(链接)
  • Label and relation definition(前两者的定义) - 提升属性

要查看或修改属性,点击笔记右边栏目的show dialog

属性

标签

标准的标签用于分类,方便在回顾时更方便地找到。例如,在对书籍进行分类的时候,可以像这样添加标签:@dateOfBirth=1921-06-10 。查找的时候也非常方便,点击左上方的放大镜或者使用快捷键ctrl+s ,直接输入标签名字或者指定标签值,相关的笔记就会出现。当然,在Trilium中,标签也被赋予了其他的意义,比如定时任务可以用run标签,排序可以使用sortd 标签,自定义外观时可以用cssClass  和 iconClass 标签。顺便一提,icon库是 boxicons。在 Trilium 中,标签是可以继承的,子笔记继承上一级笔记的标签,要如此,只需勾选 inheritable 栏的选框,同时,子笔记也可以拥有其他属性,且继承不影响它的兄弟姐妹笔记。

标签

关系

关系其实就是一种链接,用于将不同的笔记链接在一起,之前写到的引用也是一种关系,不过 Trilium 中的关系和其他笔记软件不太一样,除了能表示具体的关系,如之前的家庭关系图:笔记 "Prince Phillip" isPartnerOf 笔记 "Queen Elizabeth II.",此外,它经常与模板结合在一起使用。与继承类似,在使用模板(template )创建子笔记(child:template)、孙笔记(child:child:template)时,创建的笔记会继承模板的属性,同时,创建的笔记会复制模板的内容,之后如果模板的属性更改了,更改会自动应用到所有使用该模板的笔记中。

关系

提升属性

提升属性使得标签或者关系更利于管理,它允许直接将相关的属性显示在笔记正文UI上,而不用每次修改或增加属性时都得点击一下show dialog 按钮。要做的这样,只需勾选属性中的 Promoted 项。

提升属性

内容管理

前面讲述了最重要的关系管理,已经可以看出 Trilium 的强大了,但我要说的是,它的内容管理做的同样出色。

编辑器

Trilium 使用的是CKEditor 5 作为主编辑器,这是一款富文本编辑器。经过这段时间的使用,我觉得这是一款不错的编辑器,不过比起它我更喜欢使用 Editor.md。当然了,作为知识管理工具富文本比纯文本编辑器在某些时候更加方便。CKEditor同时也支持Markdown,这也是我觉得它不错的一个原因,对于我这种Markdwon老手来讲,几乎不会感受到转换的痛苦,不过对于md新手就有点不适了,因为它是所见即所得的md模式,这一点对于新手可能有点不友好。另外,编辑器支持导入导出Markdown,方便迁移其他平台的笔记。CKEditor的确不错,但有两点是我觉得不好的:不支持数学公式和代码高亮,这两个功能应该算是常用功能,但CKEditor没有,只能期待后续的更新了。

媒体和文件

与常规存储方式不同,Trilium 把媒体和文件存储在数据库中,说实话我对这种做法不是很赞同,不过它也有一个显著的好处,那就是不用考虑引用资源的路径问题,还有因为是 sqlite ,所以在不同平台的同步和迁移时比较方便。图片和其他媒体资源可以在笔记里直接嵌入,作为子笔记来管理,同时,Trilium 还支持保存代码文件,可以选择代码语言并且支持高亮,这个功能很赞!

图片存储

代码存储

备份和历史版本

历史版本

历史版本是一个我又爱又恨的功能,Trilium 会在设定的时间内自动保存一份当前笔记的快照到数据库,可以在右边栏目中的 Note Revisions 查看,这有效防止了笔记的丢失,不过笔记的历史版本可能会占据较大空间,这也是我恨的地方,关闭又怕丢,不关又一大堆历史版本,所以每次我完成都会删除历史版本。如果要关闭某条笔记的定时快照功能只需在笔记属性里添加 disableVersioning 标签即可。

版本

备份

Trilium支持下面几种备份方案来备份数据库:

  • 一天一次
  • 每周一次
  • 每月一次
  • 在将数据库迁移到较新版本之前

各个操作系统上数据目录的路径如下:

  • Linux: ~/.local/share
  • Windows: %appdata%
  • MacOS: /Users/$(user)/Library/Application Support

恢复备份只需要把当前db文件替换成备份的文件,再重启 Trilium 即可

加密笔记

其实对于一款个人知识库软件来讲,加不加密无所谓,不过老外似乎很在意这方面的问题,所以,加密笔记也下了功夫,主要是以下两点:

  • 根据用户的密码使用加密密钥对笔记进行加密。
    • 这意味着,如果没有密码,加密的笔记是无法解密的,即使有人设法窃取了Trilium 数据库,也无法读取受保护的笔记。
  • 有时间限制地访问受保护的笔记
    • 类似于阅后即焚,不过 Trilium 把 “焚” 换成了加密,如需继续阅读,需要输入密码

需要注意的是:加密的不包括一些元数据比如修改日期、属性等;加密后的笔记其他没有密码的人也可以进行删除操作;搜索结果会自动排除加密的笔记。

模板和插件

日记本

这是我选择Trilium的主要原因,之前用WP写了一段时间的日记,也想过写一套WP主题来作为日记本,不过后来发现wordpress不太适合这项工作。在 Trilium 中,设置 Day Notes 只用将父笔记加上 calendarRoot 标签,需要注意的是,在整个文档树(即整个root目录)中此标签只能出现一次。点击右上方的Today 按钮即可自动新建一则今天的日记,同时,右边的侧栏也会显示一个日历表,点击表中日期即可快速跳到那一天的日记,标有下划线的日期即为今天。

日记本

在 Trilium中,日记类型的笔记与文字笔记没什么不同,所以像引用,标签,属性这些东西都完美支持。那么有意思的来了:我可以在日记中记下某个知识,再在其它笔记中直接引用它,或者直接创建一条克隆笔记,效率极其高!如此我便再也不用费心管理日记和笔记之间的关系了。

书单

写读书笔记这件事我从没做过,不过 Trilium 提供了一个很好的思路,写完某一个章节的笔记后可以在父笔记中直接查看(支持折叠),能比较系统的回顾书中内容。另外,我发现在阅读人物关系比较复杂的小说中,结合前文所提到的关系图能比较清晰地梳理人物关系。

书单

其他&自定义

前文所提到的关系图也属于模板之一。另外,Trilium 还有两个完善度较高的模板:Task manager和Weight Tracker,不过这两个我偶尔使用,所以不做过多说明,相比之下,这两个功能手机端使用的多些,而且更方便。

Trilium 中的插件使用js编写,并且原生提供接口供用户使用。接口分为

  • Frontend API,详看:https://zadam.github.io/trilium/frontend_api/FrontendScriptApi.html
  • Backend API,详看:https://zadam.github.io/trilium/backend_api/BackendScriptApi.html

前面说的日记本的 Today 按钮本质也是一个插件,调用的 Frontend API ,同时结合了日记本模板的特性,所以做出了一个新建名字为日期的子笔记,在 Trilium Demo 中有插件的源代码,比较容易理解:

api.addButtonToToolbar({
    title: 'Today',
    icon: 'calendar',
    shortcut: 'alt+t',
    action: async function() {
        const todayNote = await api.getTodayNote();

        await api.waitUntilSynced();

        api.activateNote(todayNote.noteId);
    }
});

官方API文档十分简洁明了,可以直接上手操作,如果要自己编写插件,推荐直接对照着文档开发。

网页剪藏插件

网页剪藏基本是优秀笔记软件的标配,可以这么说,在信息时代,如果一款笔记软件没有这个,那体验肯定是差其他软件一大截的。Trilium 原生支持API,所以有一个配套的 网页剪藏插件

插件可以连接本地的软件或者远程的同步服务器,具有有以下功能:

  • 保存整个页面
  • 截图并保存
  • 选中文字剪藏
  • 选中图片剪藏

插件保存整个页面时,是直接发送当前网页的内容,同时会将图片也一并保存到新的笔记,与 Wallabag 发送链接后台抓取的保存方法有所不同。对于这个功能,我也不太好评价Wallabag与Trilium的好坏,毕竟两个程序的定位不同。另外提一句,新创建的笔记默认放在当日的日记下面,可以将要保存的位置的父笔记加上 clipperInbox 标签,该笔记就会变成剪藏笔记的根目录。同一天在同一个网址剪藏的文字都会放在同一个笔记下。

]]>
https://spiritx.xyz/1042.html/feed/ 15
树莓派4B开箱及archlinuxarm环境配置 https://spiritx.xyz/1041.html https://spiritx.xyz/1041.html#comments Sat, 09 May 2020 04:10:08 +0000
终于,心心念念的树莓派4B到手上了]]>


买了一块树莓派3B+,一年的使用下来,虽然不怎么吃灰,但使用却逐渐偏离了GPIO的主题。果然印证了那句“买前IoT,买后路由器” :笑哭: 。最近觉得作为软路由来使树莓派3B+的性能已经达不到我的要求了,加上眼馋树莓派4很久了,于是入手了一个树莓派4B 4G版。为什么不买矿难板子或者其他派?作为一个学生党,我不得不考虑功耗和便携性,再加上树莓派相关生态的完善,我选择了这块作为软路由看起来性价比不算最佳的机器。至于NUC,没钱警告 :耐克嘴: 。话不多说,先上图

开箱

树莓派4代的更换了包装,大小和33代一样,不过外观改变了,讲道理,我觉得3代的盒子更好看一些

P00508 112607

树莓派4B主板目前有两个版本 Rev 1.1 和改进版 Rev 1.2 ,新版改进了电源部分电路,对pd2.0充电头兼容性更佳。但价格是一样的。幸运的是,我买到的是 Rev 1.2 版本的,如下图我画出的红色框所示,多了个电源管理模块。

1588865438551

来几张3B+和4B的外观主要区别对比图,上为3B+,下为4B

P00505 154326

3B+和4B主要是HDMI接口换为了2个micro HDMI,网口和USB接口位置对调了

P00505 153834

P00505 155516

P00505 153841
我的3B+亚克力板子那一面翻过来刚好可以用 :掩面笑: ,3B+的两个 USB 2.0 接口换为了 USB 3.0

P00505 155525

性能方面,我使用了archlinuxarm的32位和64位系统,当然我没安装图形界面,体验下来感觉就是一个词:流畅,值得一提的是树莓派4B支持4K 60HZ/4K 30HZ×2 输出,用作流媒体挺好,性能方面我是十分满意的,就是这功耗不敢恭维,低负载加上风扇的情况下,CPU 的温度一直保持在 50+ ℃ :受虐滑稽: ,后面我会加几个散热片,顺便换个外壳。对了,还有一件事就是电源问题,必须保证在 5V 2.5A 以上(官方推荐是5V 3A),不然系统会运行不正常。

ArchLinux ARM安装

之前用3B+的时候就用的archlinuxarm的aarch64版本,所以直接下载安装了,等我插上卡通电后才发现不对劲,原来archarm目前的包也是32位的......浪费了我好多时间。

PS:如果选择自编译64位系统需要主机环境为Arch Linux

32位

参照 https://archlinuxarm.org/platforms/armv8/broadcom/raspberry-pi-4 ,安装的过程和 3B+的安装 一样。

64位

raspberrypi官方的64位os还处于beta阶段,所以安装32位比较方便,但我3B+都用了aarch64了,4B再不上64位就说不过去了。
64位的系统就需要自己动手啦,不过我也找到了有人 打包好的 ,可以直接刷入,步骤和 之前 一样。需要注意的有:

  • 需要自定义DNS,使用nano(因为没有自带vi)编辑 /etc/resolv.conf,加一行 nameserver 8.8.8.8
  • 需要安装dhcp(pacman -S dhcp)或者自定义IP以正常使用网络
  • 需要自己打开时间同步 timedatectl set-ntp true ,不然每次重启时间会归位

如果对安全性有要求的话还是建议按照如下步骤自己打包:

下载rootfs

ArchLinuxARM 官网 上下载 多平台镜像 http://os.archlinuxarm.org/os/ArchLinuxARM-aarch64-latest.tar.gz ,注意下载后校验文件。
进入到工作文件夹,新建 rootboot 文件夹
解压备用:bsdtar -xpf ArchLinuxARM-aarch64-latest.tar.gz -C root

配置虚拟容器

## 先安装静态库
 ~/w/r/pi  yay -S qemu-arm-static
## 进入容器
 ~/w/r/pi  systemd-nspawn -D root
 ## 显示进入容器了
[root@root ~]# 

不知道为什么,DNS一直不能用,于是我直接修改的hosts

## 根据自己的需要换源
[root@root ~]# vi /etc/pacman.d/mirrorlist
Server = http://mirrors.tuna.tsinghua.edu.cn/archlinuxarm/$arch/$repo
[root@root ~]# vi /etc/hosts
101.6.8.193 mirrors.tuna.tsinghua.edu.cn

先安装依赖

[root@root ~]# pacman-key --init
[root@root ~]# pacman-key --populate archlinuxarm
[root@root ~]# pacman -Syy
[root@root ~]# pacman -S base-devel fakeroot libffi xmlto docbook-xsl inetutils bc

编译kernel

## 下载 PKGBUILD
 ~/w/r/pi  git clone https://github.com/esotericnonsense/linux-raspberrypi4-aarch64.git boot/home/alarm/
## 进入容器
 ~/w/r/linux-raspberrypi4-aarch64   master ±  systemd-nspawn -D root
## 修改编译的cpu核心数,我改成8核了,根据自己的电脑配置修改
[root@root ~]# vi /etc/makepkg.conf
MAKEFLAGS="-j8"
## 切换为普通用户
[root@root ~]# su alarm
[alarm@root root]$ cd ~/linux-raspberrypi4-aarch64/
## 编译
[alarm@root linux-raspberrypi4-aarch64]$ makepkg -si

需要注意的是,这里编译的是 https://github.com/raspberrypi/linux 4.19 分支提交的内核,PKGBUILD 的版本是 commit edc6ef437bd690772d7a562adeea6c85daf11440 ,版本是4.19.89。

当然也可以选择其他版本,我选择的是 5.2分支 的版本。 只需要修改 PKGBUILD 中的 _commit 为最新commit-id,pkgver 为5.2就行了。考虑到网络环境的问题,我选择提前下载内核文件:https://github.com/raspberrypi/linux/archive/commitid.tar.gz ,下载后修改文件名为 commit-id.tar.gz,之后编译时跳过检验就好了:makepkg --skipinteg,编译时间很长,在我的低压U本子8核全满上跑了近4小时,感觉这个改不改核心影响不大,因为我之后在树莓派上常规编译跑了5个小时。

## 切换回普通用户
[alarm@root linux-raspberrypi4-aarch64]$ exit
[root@root ~]#  cd /home/alarm/linux-raspberrypi4-aarch64/
## 安装编译好的内核文件
[root@root linux-raspberrypi4-aarch64]#  pacman -U linux-raspberrypi4-aarch64-headers-5.2-1-aarch64.pkg.tar.xz linux-raspberrypi4-aarch64-5.2-1-aarch64.pkg.tar.xz

安装依赖

[root@root ~]# pacman -S pacman-contrib  # for pactree
[root@root ~]# pacman -Sw $(pacman -Qqn)
[root@root ~]# pactree -l pacman | pacman -S -
[root@root ~]# pacman -Qqn | pacman -S -

安装系统

先按照 步骤 进行分区,然后就可以把配置好的系统打包到 SD 卡了,我使用的是rasyc,当然也可以使用dd。

  ~/w/r/pi  sudo mount /dev/sdd2 boot 
  ~/w/r/pi  sudo mkdir -p boot/boot 
  ~/w/r/pi  sudo mount /dev/sdd1 boot/boot
  ~/w/r/pi  sudo rsync --archive --numeric-ids --acls --xattrs --human-readable --verbose --progress --stats --itemize-changes --exclude='/home/alarm/*' root/ boot
  ~/w/r/pi  umount -R boot

之后插卡通电就能使用

后续配置

之后的操作与一般linux无异,如果要升级内核的话,还需自己编译,不过建议树莓派上makepkg,配合 Distcc 使用,晚上挂上,早上起床估计就能安装了 :滑稽:

2020.08.11 更新

今天逛论坛发现aarch64的镜像发布了 (http://os.archlinuxarm.org/os/ArchLinuxARM-rpi-aarch64-latest.tar.gz) ,但重新安装系统未免太费时间,而且树莓派上的数据迁移比较麻烦,所以我直接更换了内核。
要切换Linux为主线内核其实非常简单,只需要以下几句:

paman -S linux-aarch64
pacman -S linux-api-headers

但会发现启动不了,所以还需要修改引导

pacman -S raspberrypi-bootloader
pacman -S uboot-raspberrypi

由于分区改变了,需要更新 fstab

sed -i 's/mmcblk0/mmcblk1/g' /etc/fstab

之后便可以重启使用了
需要注意的是如果更改了/boot/config.txt需要运行 /boot/mkscr来应用更改,为此需要安装 uboot-tools 软件包

参考:
- esotericnonsense:linux-raspberrypi4-aarch64

]]> https://spiritx.xyz/1041.html/feed/ 2 使用VirtualBox启动本地硬盘上的Win 10系统 https://spiritx.xyz/1037.html https://spiritx.xyz/1037.html#comments Sun, 01 Mar 2020 15:49:58 +0000 https://spiritx.xyz/?p=1037
从 Arch Linux 启动 Windows 10分区]]>

前言

了更好的性能,当初装系统时选择了双系统的方式,又为了满足我对于几款win平台软件的需求,安装了一台 Win 7 虚拟机(前不久换成了 Win 8.1)。近来发现,Windows 10虽然作为我的必备系统,但我打开她的频率不是太高,而且Windows虚拟机由于需求越来越多,磁盘剩余逐渐变小。于是我想到把我“闲置”的Win 10系统利用起来,一方面,经过我几年的使用和配置,肯定比虚拟机用得顺手,同时也免去了开机切换系统的麻烦;另一方面,当初装系统时给 Win 10 分配的空间比Arch Linux多很多,如果利用起来的话,我Arch上的一些替代软件就可以删除了,这样可以给我腾出不少空间。
PS: 本文所用的这种方式启动的Windows肯定是存在问题的,最明显的就是驱动的问题了,建议三思后再尝试!

从 Arch Linux 启动 Windows 10

查看分区情况

首先,看看我的分区情况

 ~  sudo fdisk -l
...
设备                起点      末尾      扇区   大小 类型
/dev/nvme0n1p1      2048    206847    204800   100M EFI 系统
/dev/nvme0n1p2    206848    468991    262144   128M Microsoft 保留
/dev/nvme0n1p3    468992 395255172 394786181 188.3G Microsoft 基本数据
/dev/nvme0n1p4 395257856 500118158 104860303    50G Linux 文件系统
/dev/sda1  *     2048 488394751 488392704 232.9G  7 HPFS/NTFS/exFAT
...

前3个就是我所需的的分区了,其中我电脑的Win 10系统就在/dev/nvme0n1p3分区

获取读写分区的权限

为了避免使用 root 运行 VirtualBox,所以需要给自己访问磁盘的权限,因为我的Win 10使用UEFI 启动,所以 UEFI 分区的权限也是需要的

## 为当前用户获取硬盘分区读写权限
 ~  sudo setfacl -m u:${USER}:rw /dev/nvme0n1p{1,2,3}
## 为当前用户获取硬盘读写权限
 ~  sudo setfacl -m "u:${USER}:rw" /dev/nvme0n1

创建 VirtualBox 的硬盘映射文件

创建之前需要先获取整块硬盘的读写权限,要注意的是nvme SSD的设备名称是nvme0n1

## 创建磁盘映射文件 windows.vmdk
 ~  VBoxManage internalcommands createrawvmdk -filename windows.vmdk -rawdisk /dev/nvme0n1 -partitions 1,2,3 -relative
## 创建完成后可以撤销对 nvme0n1 的权限
 ~  sudo setfacl -b /dev/nvme0n1

使用-partitions 1,2,3选项的话,只有这三个分区能在虚拟机里访问,别的分区读的时候是全零,写入操作会被忽略。-relative选择使用分区设备名(nvme0n1p1、nvme0n1p2、nvme0n1p3),这样创建好之后 VirtualBox 不再需要对整块硬盘 nvme0n1 的权限了。另外会附带创建一个名字以 -pt.vmdk 结尾的文件。它是单独的分区表。

配置bios dmi(可选

这一步主要是为了配置一些主板额外的信息,参考Configuring the BIOS DMI Information。注意:如果你和我一样是使用UEFI启动的话,代码语句里面的pcbios应换为efi。示例如下:

## 可能需要
 ~  sudo pacman -S dmidecode
## 获取dmi type0的信息
 ~  sudo dmidecode -t0
## Windows 10 即为虚拟机名字,10/23/2018就在刚获取的dmi信息中
 ~  VBoxManage setextradata "Windows 10" "VBoxInternal/Devices/efi/0/Config/DmiBIOSReleaseDate" "10/23/2018" 

使用虚拟机

打开 VirtualBox,按照常规步骤创建虚拟机,硬盘就选刚创建的磁盘映射文件,创建完成后记得在设置-系统-主板里勾选 启用EFI,然后就可以开机了。注意:重启后必须重新为当前用户获取硬盘分区读写权限!sudo setfacl -m u:${USER}:rw /dev/nvme0n1p{1,2,3}
话不多说,先上图

win10

美中不足的是打开发现数字许可证失效了orz,而且指纹和pin解锁不能使用,经过一番Google,应该是TPM失效的缘故,而 VirtualBox 不支持vTPM......看来我只能将就用了。值得一提的是,如果你是通过主板硬件来激活 Windows 的话,那么可以尝试下下面这个方法(虽然我也没试过,不过理论上来讲没问题~~ :流汗滑稽:

## 查看key
 ~  sudo cat /sys/firmware/acpi/tables/MSDM
## 如果没有的话就放弃吧~_~
## 把key导出
 ~  sudo dd if=/sys/firmware/acpi/tables/MSDM of=/home/spirit/VirtualBox VMs/msdm.bin
## 导入虚拟机
 ~  VBoxManage setextradata "Windows 10" "VBoxInternal/Devices/acpi/0/Config/CustomTable" "/home/spirit/VirtualBox VMs/msdm.bin"

后记

既然可以从Linux启动Win,那能不能从Win启动Linux呢,我试着创建了一个磁盘映射,答案是可以的,不过需要注意的是操作均需在管理员权限下执行。Win+x,点击磁盘管理,查看硬盘序号,我的系统盘是磁盘1,所以硬盘选择了\\.\PhysicalDrive1

## 列出磁盘分区
C:\Users\spirit\Documents> "C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" internalcommands listpartitions -rawdisk "\\.\PhysicalDrive1"
Number  Type   StartCHS       EndCHS      Size (MiB)  Start (Sect)
1       0x00  0   /0  /0   0   /0  /0            100         2048
2       0x00  0   /0  /0   0   /0  /0            128       206848
3       0x00  0   /0  /0   0   /0  /0         192766       468992
4       0x00  0   /0  /0   0   /0  /0          51201    395257856
## 创建磁盘映射linux.vmdk
C:\Users\spirit\Documents> "C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" internalcommands createrawvmdk -filename linux.vmdk -rawdisk "\\.\PhysicalDrive1" -partitions 1,4

之后和前面一样,创建虚拟机,注册虚拟磁盘,不过需要注意的是以管理员身份运行 VirtualBox

参考文章:

]]>
https://spiritx.xyz/1037.html/feed/ 5
我为什么不将微信作为常用软件 https://spiritx.xyz/1031.html https://spiritx.xyz/1031.html#comments Fri, 06 Dec 2019 14:10:48 +0000
“加个微信吧!” “抱歉,我用QQ。”]]>

只一次遇到别人惊讶:“你居然没用微信!” 作为一名学生,虽然我对QQ的一些方面也不大满意,但我觉得QQ已经满足我所有的需求了,我非常不想在我的手机上安装两个功能重叠的app,但碍于一些原因,我也不得不在手机上安装一个微信,但每次打开微信时各种订阅号、公众号推送让我很是心烦。屏蔽吧怕错过一些重要消息,不屏蔽吧待处理消息分分钟99+。我的家长亲戚中很多人都用微信,在得知我居然在用QQ,他们都会诧异道:“什么年代了,你居然还在用QQ!” 也许我就是那个落后于潮流前沿的人吧 :doge笑哭: :doge笑哭:

我常用的IM和IRC软件为:QQ > Telegram > yaaic/HexChat > 微信。QQ的功能十分完善,但也有不少臃肿的东西,比如会员,Q钻什么的,这点不如微信;至于Telegram,就不用多说,详见这篇文章这篇文章;相较于IM软件,IRC软件就比较简陋,但作为聊天来使用却是十分合适,没有太多无用信息刷屏,操作方式带有极客范儿,不过由于年代久远,服务器数目已经大不如前,目前我主要在freenode的服务器上。微信的话,我将在接下来提到。

理念
在微信之前的时代,网民们的网络身份通常是电子邮件地址。而微信的出现,改变了这一点:把手机号以做成了第一身份认证手段。把手机号做成了凌驾于身份证之上的认证手段。这与一些要求手机号绑定但手机号并非第一认证手段的app,是不相同的。我第一个微信号时在初中时创建的,当时的注册方式是一张未实名的移动卡,在手机掉了之后,那个微信号就随之消失了,也不知道被谁注册到了那个手机号,然后再通过手机号登上了我的微信 :捂脸: 。虽然我非常不喜欢这种通过手机号认证的方式,奈何有几个常用的App无法舍弃,只得老老实实去用手机号注册。现在用的微信号是我初二的时候通过关联QQ号注册得到的,那时候的微信有个很方便的功能:收发QQ消息。为了尝鲜,我使用了一段时间,然而有一天,点击接收的QQ消息后,它却告诉我不再支持此功能了(???黑人问号脸),把QQ用户骗到这里来,然后就不管了??
啥也干不了的PC端
使用过PC端微信的人,都会遇到一个蛋疼的问题:扫码登录。不知道微信的策划是怎么想的,难道怕用户记不住密码吗 :doge笑哭: ,之后还有“密码不如扫码安全”的逻辑,对此,我敢苟同。只能说各有各的好处,但并没有直接证据可证明扫码比密码安全,只能说这是一个很蛋疼的设计。受此荼毒,企业邮箱现在也是扫码登录,所以,我选择迁移到了Yandex。此外,微信的PC端功能很少,许多操作只能在手机上完成,就连红包功能也是最近才加入PC端的。
辣鸡的相册
微信的Android端在选取图片时,并没有调用系统相册,反而是自己造了个轮子,关键是还不如系统自带的相册好用,反而多出来一大堆预览图缓存,占用手机的存储空间
备份麻烦的聊天记录
腾讯微信官方一直不提供导出聊天记录到CSV或TXT文件的功能,用户的数据安全无法得到保障。即使其表明用户聊天数据点对点加密服务器不留底不储存,所以聊天记录只能保存在双方设备上,然而由于聊到敏感话题被封禁甚至被拘留这种新闻屡屡可见,那么问题来了,证据是从哪收集到的 :喷2: 我想说:既然立了牌坊就别去当**
不成熟的群聊
QQ群在功能上碾压微信群聊——发公告发通知,永久保存群文件,传文档,下表格,共享资源,回复功能,压缩包,管理员组织能力,碾压微信。更别说QQ还自带邮箱和网盘了。 至于QQ空间的日志相册评论转发等多媒体功能更是碾压微信朋友圈。
烂大街的公众号
开通公众号门槛极低,所以导致了一大堆辣鸡公众号天天发一些震惊、养生、鸡汤,也不管信息可信,只管发,为了引入流量,真什么都敢写...如果你加了长辈群,那么群里一定充斥着震惊养生造谣鸡汤等等,我本人特讨厌鸡汤还有那种没什么质量的短视频,长辈们居然觉得很不错。

以上所述即为我不用微信的几个理由,但世事无绝对,我只能说在现在的情况,因为谁也不能保证未来一切尽在掌握,也许有一天微信填补了它所有的缺陷,也许有一天我因为特殊原因不得不24小时开着微信...... :傲慢:

近年来移动端发展迅速,社交软件中微信可以说是首当其冲了(简陋的电脑端、必须扫码、文件大小限制等),似乎微信设计之初就没有将PC端作为其主要战场,而是将这片土地留给了它的兄弟QQ,但是它在移动端领域却是有取代QQ之势,反观手机QQ却一直没有碰微信的市场的意思,虽然推出了办公使用的Tim(一年没更新了),但没有触及到微信的核心利益,QQ、微信各有不可替代的作用和定位,作为同一家公司的软件,我想,如果要将功能都做得相同在技术上很容易实现,但这样结果必定不会好。毕竟,利益最大化才是问题关键。

]]>
https://spiritx.xyz/1031.html/feed/ 26
Posting file via wp_remote_post https://spiritx.xyz/1029.html https://spiritx.xyz/1029.html#comments Tue, 26 Nov 2019 08:47:41 +0000 https://spiritx.xyz/1029.html send an HTTP POST request using wp built-in function]]>

For several reasons I don't want to use curl, and I have known that WordPress has methods for HTTP request, so I choose wp_remote_post(), which allows you to send an HTTP post request, and return an array. Here's the code example:

<?php
$upload_url = "URL_YOUR_UPLOAD_FILE_TO";
$local_file = "PATH/TO/FILE";
$filename = basename($local_file);
$name = $local_file;  //name of Form Control
$Boundary = wp_generate_password();  //split signal, see: https://www.ietf.org/rfc/rfc1867.txt
$bits = file_get_contents($local_file);

$args = array(
    "headers" => "Content-Type: multipart/form-data; boundary=$Boundary\r\n\r\nAuthorization: Basic $client_id\r\n\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97",
    "body" => "--$Boundary\r\nContent-Disposition: form-data; name=\"$name\"; filename=\"$filename\"\r\n\r\n$bits\r\n\r\n--$Boundary--"
);

$response = wp_remote_post($upload_url, $args);
if (!is_wp_error($response)) {
    $reply = $response["body"];  //the remote server's reply
    var_dump($reply);
}
?>

reference: https://www.jianshu.com/p/29e38bcc8a1d

]]>
https://spiritx.xyz/1029.html/feed/ 4
WordPress评论支持Markdown https://spiritx.xyz/1026.html https://spiritx.xyz/1026.html#comments Sun, 17 Nov 2019 12:09:22 +0000 https://spiritx.xyz/?p=1026
WordPress评论免插件支持Markdown]]>

缘由

之前有过一篇记一次小站评论功能的修改,目的是为了防止xss攻击,当时我使用的评论 Markdown 解析器是 WP-Editor.md 插件,最近更新WP发现插件有冲突,遂禁用了它,换用代码实现,如果你和我一样使用的是同一款主题的话,commit 已提交,快去更新吧~

引入Markdown解析器

原理很简单,与 WP-Editor.md 类似,在评论提交时,首先检查评论的合法性,再将评论转换为 HTML 并写入数据库,同时,原 Markdown 评论也储存进数据库,为了这样,我在 wp_comments 里增加了一个字段 comment_markdown,在读取评论打印的时候,直接显示转换好的html,这样做有个好处就是不用每次都转换评论,节省了不少资源,同时,原格式的评论有一个存档,虽然增加了数据库的一点点体积,但我认为不错。
用到了下面这个程序

这里下载源码,我们所需要的是压缩包里面的 Parsedown.php ,将它放入主题目录的任一位置
functions.php 里面引入它:

...
include path/to/Parsedown.php
...

之后,就可以在想要使用的地方像下面这样来使用啦~

$Parsedown = new Parsedown();

echo $Parsedown->text('Hello _Parsedown_!'); # prints: <p>Hello <em>Parsedown</em>!</p>

转换评论

使用WP的 preprocess_comment 在评论写入数据库之前拦截它

function markdown_parser($incoming_comment) {
    global $comment_markdown_content;
    $comment_markdown_content = $incoming_comment['comment_content'];
    include 'path/to/Parsedown.php';
    $Parsedown = new Parsedown();
    $incoming_comment['comment_content'] = $Parsedown->text($incoming_comment['comment_content']);
    return $incoming_comment;
}
add_filter('preprocess_comment' , 'markdown_parser');

储存原评论

原评论也很重要,因为kses的关系,部分评论可能会被转义,这时候就需要原评论啦~

新建字段

global $wpdb;
$myCustomer = $wpdb->get_row("SELECT * FROM wp_comments");
if (!isset($myCustomer->comment_markdown)) {
    $wpdb->query("ALTER TABLE wp_comments ADD comment_markdown text NOT NULL AFTER comment_content");
}

存入数据

在之前我定义了一个全局变量 $comment_markdown_content,现在就要用到它啦,do_action("comment_post") ,写入数据库立即触发

//保存Markdown评论
function save_markdown_comment($comment_ID, $comment_approved) {
    global $wpdb,$comment_markdown_content;
    $comment = get_comment($comment_ID);
    $comment_content = $comment_markdown_content;
    $wpdb->query("UPDATE wp_comments SET comment_markdown='".$comment_content."' WHERE comment_ID='".$comment_ID."';");
}
add_action('comment_post', 'save_markdown_comment', 10, 2);

打开评论HTML标签限制

为了安全,除管理员外wp的评论都会经过kese,甚至有时候管理员的评论也会过滤,这就需要我们来打开这个限制

function allow_more_tag_in_comment() {
    global $allowedtags;
    $allowedtags['pre'] = array('class'=>array());
    $allowedtags['code'] = array('class'=>array());
    $allowedtags['h1'] = array('class'=>array());
    $allowedtags['h2'] = array('class'=>array());
    $allowedtags['h3'] = array('class'=>array());
    $allowedtags['h4'] = array('class'=>array());
    $allowedtags['h5'] = array('class'=>array());
    $allowedtags['ul'] = array('class'=>array());
    $allowedtags['ol'] = array('class'=>array());
    $allowedtags['li'] = array('class'=>array());
    $allowedtags['td'] = array('class'=>array());
    $allowedtags['th'] = array('class'=>array());
    $allowedtags['tr'] = array('class'=>array());
    $allowedtags['table'] = array('class'=>array());
    $allowedtags['thead'] = array('class'=>array());
    $allowedtags['tbody'] = array('class'=>array());
    $allowedtags['span'] = array('class'=>array());
}
add_action('pre_comment_on_post', 'allow_more_tag_in_comment');

为了更加安全,可以更进一步

...
$allowedtags['pre'] = array(
    'class' => true,
    'id' => true,
);
$allowedtags['code'] = array(
    'class' => true,
);
...

或者采用我的方法,直接禁止HTML代码

后记

大功告成啦,这次修改又学到了好多东西,后续我可能会把前端的评论给改了,加个编辑器

]]>
https://spiritx.xyz/1026.html/feed/ 1
失误 https://spiritx.xyz/1022.html https://spiritx.xyz/1022.html#comments Fri, 11 Oct 2019 09:02:35 +0000 https://spiritx.xyz/?p=1022
一直以来享受dd操作的便利性,没想到这次却翻了车]]>


一直以来我都觉得dd很方便,之前看到网友戏称 dd=disk destroyer 还觉得我怎么可能会出错,对之不屑一顾,没想到这次却因为我小小的输入失误损失了如此多的数据。前天下午,在烧录树莓派镜像时错把备份镜像烧进了移动硬盘,虽然我及时终止了dd操作,但还是损坏了我的分区表,在此操作前我还特意用了fdisk -l查看磁盘号,可惜输入错误。我移动硬盘只有一个大小为4TB的NTFS分区,经过两天的各种尝试(包括TestDisk和DiskGenious),没能恢复分区表。万般无奈下只能在Windows下尝试使用恢复软件进行恢复,直至目前还在扫描中......这块希捷STDR4000301移动硬盘陪伴了我几年了,里面存了不少东西,我还往里面放了一个大小为1T的VeraCrypt的虚拟磁盘文件,用于加密我的一些重要数据,没想到这次却。。
目前还不能保证能恢复多少数据,但损失是不可避免的,罢了,也算是一次教训吧,之后的dd相关操作我都将使用/dev/disk/by-id的方式,避免出错,写下这篇文章提醒我自己,也提醒我的访客们,涉及到数据的操作一定得谨慎谨慎再谨慎!!!切记!切记!特别是像dd命令这样的高风险操作!!

]]>
https://spiritx.xyz/1022.html/feed/ 8
记一次小站评论功能的修改 https://spiritx.xyz/997.html https://spiritx.xyz/997.html#comments Thu, 18 Jul 2019 16:30:52 +0000 https://spiritx.xyz/?p=997
Markdown yes! HTML no!]]>

缘由

久没上我的测试站点,发现多了不少评论(明明我从来没公开过链接,却还是被扫到了 :黑线: ),其中一条引起我的注意: ***<script>alart(*****);</script>;*****<script>window.location.href='http://*****';</script>******,打开评论所在页面一看,果然是 xss攻击 。测试站点没有装Wordfence,所以才让攻击者有可承之机,但我平时不会开放测试站的访客访问,多装一个Wordfence很浪费资源,于是我决定修改下评论功能。小站评论框上方一直有这样一句话 Markdown Supported while </> Forbidden,但实际上评论html也是可以解析的,我觉得从这入手比较好,正巧Sakura主题评论插入图片的方式使用的是安全的BBCode,如果再加入仅允许Markdown评论的功能,那绝大多数XSS就直接被干掉了 :酷2: 。话不多说,下面记录下我的修改过程。

评论使用Ajax

此条为必须,采用Ajax提交评论可以在评论内容写入数据库之前再对评论进行一次检查。Sakura已自带Ajax评论,所以此步省略,Ajax评论引入也很简单,如需了解更多,参考这位大佬写的 WordPress Ajax 提交评论的实现,简单易懂。

过滤无效邮箱

WordPress自带了一个检查评论者邮箱是否为正常邮箱的功能,所以我不再重复添加了。这里主要是验证邮箱是否有效,用到的是 checkdnsrr() 函数,查询评论者邮箱的所属域名有没有MX记录,使用方法如下:
以Sakura主题为例,检查Ajax传入的评论参数 $incoming_comment ,得到评论邮箱 $incoming_comment['comment_author_email'] ,使用 explode()array_pop() 函数得到邮箱域名,再用 checkdnsrr() 函数函数检查域名DNS解析中有无 MX 记录。代码如下:

function spirit_comment_check($incoming_comment) {
    if(checkdnsrr(array_pop(explode("@",$incoming_comment['comment_author_email'])),"MX") === false)
        siren_ajax_comment_err('邮箱写错啦(→_→)<br>Oops,Invalid email!');
    return( $incoming_comment );
}
if(!is_user_logged_in())
    add_filter( 'preprocess_comment', 'spirit_comment_check' );

禁止html代码

我使用的WP-Editor.md插件,支持评论Markdown,所以无需再引入其他文件来解析评论中的Markdown,那么重点就在如何禁止评论使用HTML标签。PHP自带了一个 strip_tags() 函数,可以把字符串中的HTML标签全部过滤掉,于是就有了下面的代码。

function spirit_comment_check($incoming_comment) {
    if(checkdnsrr(array_pop(explode("@",$incoming_comment['comment_author_email'])),"MX") === false) {
        siren_ajax_comment_err('邮箱写错啦(→_→)<br>Oops,Invalid email!');
    }else{
        if($incoming_comment['comment_content'] != strip_tags($incoming_comment['comment_content'])){
            siren_ajax_comment_err('评论只支持Markdown啦,见谅╮( ̄▽ ̄)╭<br>Markdown Supported while <i class="fa fa-code" aria-hidden="true"></i> Forbidden');
        }
    }
    return( $incoming_comment );
}
if(!is_user_logged_in())
    add_filter( 'preprocess_comment', 'spirit_comment_check' );

但这又有个问题,如果评论者输入的代码块中,包含了 < 的HTML标签,那么就不能提交,于是我又想到一个办法,去掉评论内容中的代码块之后再检查有无HTML标签,下面是修改版:

function spirit_comment_check($incoming_comment) {
    $re = '/```([\s\S]*?)```[\s]*|`{1,2}[^`](.*?)`{1,2}|\[.*?\]\([\s\S]*?\)/m';
    if(checkdnsrr(array_pop(explode("@",$incoming_comment['comment_author_email'])),"MX") === false) {
        siren_ajax_comment_err('邮箱写错啦(→_→)<br>Oops,Invalid email!');
    }else{
        if(preg_replace($re,'temp',$incoming_comment['comment_content']) != strip_tags(preg_replace($re,'temp',$incoming_comment['comment_content']))){
            siren_ajax_comment_err('评论只支持Markdown啦,见谅╮( ̄▽ ̄)╭<br>Markdown Supported while <i class="fa fa-code" aria-hidden="true"></i> Forbidden');
        }
    }
    return( $incoming_comment );
}
if(!is_user_logged_in())
    add_filter( 'preprocess_comment', 'spirit_comment_check' );

正则解释如下:
```([\s\S]*?)```[\s]*过滤掉代码片段,`{1,2}[^`](.*?)`{1,2}过滤掉行内代码,\[.*?\]\([\s\S]*?\)过滤掉链接,因为有时候链接标题也会带 < 字符。开始我也担心过滤掉链接会增加被XSS攻击的风险(类似于 [Click Me](javascript:alert(***)) 这样的语句),但发现WordPress的kses会自动转义这样的语句,所以就放心使用啦~

打开评论HTML标签限制

完成之后我使用访客模式打开了小站,测试评论功能时发现一个问题,评论部分Markdown格式不能转换,比如:

/**
* nth element in the fibonacci series.
* @param n >= 0
* @return the nth element, >= 0.
*/
function fib(n) {
  var a = 1, b = 1;
  var tmp;
  while (--n >= 0) {
    tmp = a;
    a += b;
    b = tmp;
  }
  return a;
}
document.write(fib(10));

正常情况下会解析为

<pre><code class="language-javascript ">
/**
* nth element in the fibonacci series.
* @param n >= 0
* @return the nth element, >= 0.
*/
function fib(n) {
  var a = 1, b = 1;
  var tmp;
  while (--n >= 0) {
    tmp = a;
    a += b;
    b = tmp;
  }
  return a;
}
document.write(fib(10));
</code></pre>

但WP-Editor.md将其解析为了

<code>
/**
* nth element in the fibonacci series.
* @param n >= 0
* @return the nth element, >= 0.
*/
function fib(n) {
  var a = 1, b = 1;
  var tmp;
  while (--n >= 0) {
    tmp = a;
    a += b;
    b = tmp;
  }
  return a;
}
document.write(fib(10));
</code>

这样的话代码高亮就失效了,体验很是不好。此外还有标题、表格、列表等也不会解析...我反复检查了插件,又翻了不少WordPress的Hook,把插件改了又改,始终没有修复这个Bug(主要还是我太菜了 :捂脸: ,最终只能从修改WordPress限制入手了,将下面代码加到functions.php

//打开评论HTML标签限制
function allow_more_tag_in_comment() {
    global $allowedtags;
    $allowedtags['pre'] = array('class'=>array());
    $allowedtags['code'] = array('class'=>array());
    $allowedtags['h1'] = array('class'=>array());
    $allowedtags['h2'] = array('class'=>array());
    $allowedtags['h3'] = array('class'=>array());
    $allowedtags['h4'] = array('class'=>array());
    $allowedtags['h5'] = array('class'=>array());
    $allowedtags['ul'] = array('class'=>array());
    $allowedtags['ol'] = array('class'=>array());
    $allowedtags['li'] = array('class'=>array());
    $allowedtags['td'] = array('class'=>array());
    $allowedtags['th'] = array('class'=>array());
    $allowedtags['tr'] = array('class'=>array());
    $allowedtags['table'] = array('class'=>array());
    $allowedtags['thead'] = array('class'=>array());
    $allowedtags['tbody'] = array('class'=>array());
    $allowedtags['span'] = array('class'=>array());
}
add_action('pre_comment_on_post', 'allow_more_tag_in_comment');

我添加了部分常用的标签,如果后续遇到不能解析的可尝试在里面继续加入更多标签。最后关闭Wordfence的xss防护,防止不能提交带有 <script 的代码块。
以上就是本次的修改历程,你有什么看法或者是对文中功能的优化吗?欢迎在评论区与我探讨。 :喝茶:

]]>
https://spiritx.xyz/997.html/feed/ 8
使用Wallabag自建稍后阅读服务 https://spiritx.xyz/993.html https://spiritx.xyz/993.html#comments Sun, 07 Jul 2019 06:52:43 +0000 https://spiritx.xyz/?p=993
我把它当作稍后阅读的生产力工具,因为数据在我自己手上]]>

前言

果你使用过Firefox,那么你对Pocket一定不陌生。与Pocket类似,Wallabag是用来保存网页的开源自托管应用,主要功能就是将要阅读或者一时没有读完的文章同步到Wallabag服务器,供使用者在以后阅读。更多信息请访问官网 https://wallabag.org/ 。当然如果你没有自己的服务器,可以考虑使用 wallabag.it 托管解决方案。
我平时在网上阅读到有意思或者没读完的文章时,一般会保存在Chrome的书签或者直接收藏在Telegram,虽然同步是可以同步,但感觉还是有点别扭,Google一番终于找到了这个神器,我已经将它作为稍后阅读的生产力工具使用。同时,也可以将书签存在上面。虽然Wallabag在配置难度、界面体验上与一些商业软件相比略有逊色,但依然值得一试。
Wallabag具有以下特性:

  • 开源 PHP 程序,易托管,github地址:https://github.com/wallabag/wallabag
  • 界面美观,易于阅读
  • 浏览器插件 - 一键保存网页到服务
  • 开放的 API - 可以根据 API 自由编写客户端
  • 迁移 - 从 Pocket, Readability, Instapaper 或 Pinboard 服务导入数据
  • 导出 - 可以导出文章到 epub, mobi, pdf 等格式
  • 随处可用 - 由于是 Web 服务,可以在使用浏览器的系统上使用,同时支持 Android 客户端
  • RSS 阅读器兼容
  • 保存网页不受源限制,源网页删除后依旧可以阅读

先来一张完成图:

ps:搭建Wallabag之前请配置好相关环境,博主所用系统为Debian 9 ,已安装了 OneinStack

安装comopser

curl -s https://getcomposer.org/installer | php

之后可以就通过 php composer.phar 来运行composer了

OneinStack安装php扩展

请阅读 文档 以查看 Wallabag 安装依赖。
我是用的 OneinStack,与apt不同,这里以安装tidy为例

apt install libtidy-dev ## 必须库
cd /root/oneinstack/src
tar zxvf php-7.3.5.tar.gz  ## 解压已经安装的php版本
cd php-7.3.5/ext/tidy
/usr/local/php/bin/phpize
./configure --with-php-config=/usr/local/php/bin/php-config
make && make install
cd /usr/local/php/lib/php/extensions
ls  ## 看到no-debug-non-zts-20180731类似文件夹
cd no-debug-non-zts-20180731
ls  ## 查看有没有 tidy.so,如果有,证明编译成功
加载 tidy
echo 'extension=tidy.so' > /usr/local/php/etc/php.d/ext-tidy.ini

开启被禁函数

/usr/local/php/etc/php.ini 中搜索 disable_functions
删除以下函数:

  • shell_exec()
  • proc_open()
  • exec()
  • proc_get_status ()

为Wallabag创建数据库和用户

常规操作,phpmyadmin和命令行都行,这里使用命令行

mysql -u root -p
MySQL [(none)]> CREATE DATABASE wallabag;
MySQL [(none)]> CREATE USER wallabag@localhost;
MySQL [(none)]> SET PASSWORD FOR wallabag@localhost= PASSWORD("123456");
MySQL [(none)]> GRANT ALL PRIVILEGES ON wallabag.* TO wallabag@localhost IDENTIFIED BY '123456';
MySQL [(none)]> FLUSH PRIVILEGES;
MySQL [(none)]> \q

下载Wallabag

首先在 Github 下载 Wallabag

git clone https://github.com/wallabag/wallabag

checkout最新分支,我安装时是2.3.8:

$ cd wallabag/
$ git checkout 2.3.8
Note: checking out '2.3.8'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at 9bbafdaa... Release wallabag 2.3.8

配置Wallabag

在目录中继续输入

SYMFONY_ENV=prod php composer.phar install --no-dev -o --prefer-dist

SYMFONY_ENV=prod 告诉symfony我们正在生产环境中安装Wallabag。该 --no-dev 标志确保在生产环境中不安装任何开发包。composer将下载并安装所有必需的依赖项。--prefer-dist 表示下载zip包而不是直接clone。
之后会要求配置一些东西,根据提示操作就好:

数据库

我用的mysql

Creating the "app/config/parameters.yml" file
Some parameters are missing. Please provide them.
database_driver (pdo_mysql): ## 我用的mysql,直接回车
database_host (127.0.0.1): localhost## 自定义
database_port (null): ## 自定义
database_name (wallabag): ## 数据库名
database_user (root): ## 数据库用户名
database_password (null): ## 数据库密码
database_path (null): ## 路径
database_table_prefix (wallabag_): ## 前缀
database_socket (null): ## 自定义
database_charset (utf8mb4): ## 自定义
domain_name ('https://your-wallabag-url-instance.com'): https://mark.spiritx.xyz ## 域名

邮箱设置

看需求,我是个人使用,没配置邮箱

mailer_transport (smtp): 
mailer_user (null): 
mailer_password (null): 
mailer_host (127.0.0.1): 
mailer_port (false): 
mailer_encryption (null): 
mailer_auth_mode (null): 
locale (en): 
secret (CHANGE_ME_TO_SOMETHING_SECRET_AND_RANDOM): 
twofactor_auth (true): 
twofactor_sender ([email protected]): 
fosuser_registration (true): 
fosuser_confirmation (true): 
from_email ([email protected]): 

杂项设置

默认就好

rss_limit (50): 
rabbitmq_host (localhost): 
rabbitmq_port (5672): 
rabbitmq_user (guest): 
rabbitmq_password (guest): 
rabbitmq_prefetch_count (10): 
redis_scheme (tcp): 
redis_host (localhost): 
redis_port (6379): 
redis_path (null): 
redis_password (null): 
sentry_dsn (null): 

安装Wallabag

完成前面的步骤后,开始Wallabag的安装,输入下面命令

php bin/console wallabag:install --env=prod

之后如下:

Wallabag installer
==================

Step 1 of 4: Checking system requirements.
------------------------------------------
 ------------------------ -------- ---------------- 
  Checked                  Status   Recommendation  
 ------------------------ -------- ---------------- 
  PDO Driver (pdo_mysql)   OK!                      
  Database connection      OK!                      
  Database version         OK!                      
  curl_exec                OK!                      
  curl_multi_init          OK!                      
 ------------------------ -------- ---------------- 

 [OK] Success! Your system can run wallabag properly.                                                                   

Step 2 of 4: Setting up database.
---------------------------------
 It appears that your database already exists. Would you like to reset it? (yes/no) [no]:
 > 
 Creating schema...
 Clearing the cache...
 Database successfully setup.
Step 3 of 4: Administration setup.
----------------------------------
 Would you like to create a new admin user (recommended)? (yes/no) [yes]:
 > 
 Username [wallabag]:
 > spirit ## 输入用户名
 Password [wallabag]:
 > ## 输入密码(不会显示)
 Email [[email protected]]:
 > ## 输入邮箱(随便啦,反正我没配置邮件服务器
 Administration successfully setup.
Step 4 of 4: Config setup.
--------------------------
 Config successfully setup.

 [OK] Wallabag has been successfully installed.                                                                         


 [OK] You can now configure your web server, see https://doc.wallabag.org                                               

装完把Wallabag移动到域名目录,别忘了 chown -R www.www ./* ,防止出现api访问错误

配置Nginx

完成后访问 web 目录下的 app.php 就能使用了,但我觉得这样不好看,于是重新写了下Nginx
index index.php; 修改为 index app.php;
root /data/wwwroot/mark.spiritx.xyz; 修改为 root /data/wwwroot/mark.spiritx.xyz/web;
增加一个块

  location / {
    try_files $uri /app.php$is_args$args;
  }

重庆Nginx之后直接访问域名 mark.spiritx.xyz 就能使用啦 :哦吼吼:

使用Wallabag自建稍后阅读服务使用Wallabag自建稍后阅读服务https://chrome.google.com/webstore/...
Opera addon: https://addons.opera.com/en/extensions/details/wallabagger/?display=en
Android: via F-Droid / via Google Play
iOS: https://itunes.apple.com/app/wallabag-2/id1170800946?mt=8
Windows Phone: https://www.microsoft.com/store/apps/wallabag/9nblggh11646

]]>
https://spiritx.xyz/993.html/feed/ 7