准备使用 ventoy 制作一个多功能启动盘。
“Ventoy 是一个制作可启动 U 盘的开源工具”,项目主页上如是说。下载 GUI 版本的安装工具,
直接运行安装即可。安装过程会重新格式化我的 U 盘,我在安装前设置了空余一部分硬盘空间自用。
安装完成后,第一个分区是 fat32 分区,可以作为普通 U 盘使用,也可以放入 ISO 等映像文件,
Ventoy 启动的时候会自动找到可启动映像加入菜单,选择即可运行映像中的操作系统。支持大部分
的操作系统,一般使用非常方便。
之前空余的空间自然是用来安装一个正常的 void 发行版。我分了两个分区:一个 ext2 格式用来
做 boot 分区,一个 btrfs 用来一般使用。btrfs 分区设置了两个子卷,@void 用来作为根目录,
@home 用来作为个人目录。
直接使用下面命令安装基本系统:
# xbps-install -S -r /mnt -R "$REPO" base-system
其中 /mnt
是我挂载的根分区,$REPO
是我使用的镜像地址。安装完成后将我本地的 /etc/rc.conf
和 /etc/default/libc-locales
文件复制过去,手写一个 /etc/fstab
文件。使用 xchroot
命令
进入新文件系统,设置 root 的密码,使用 xbps-reconfigure -f glibc-locales
生成 locale 信息。
安装 grub 比较特殊,因为我不能安装到正常的 EFI 分区,那样会影响到 Ventoy 的启动,因此挂载了
boot 分区,将原来 boot 目录中的内容移动过去。建立 /boot/efi/
目录,然后运行下面的命令安装:
# xbps-install -S grub-x86_64-efi
# grub-install --target=x86_64-efi --efi-directory=/boot/efi --removable --no-nvram --force
使用 --force
参数是因为我的 efi 目录根本不是 EFI 分区,安装到这里只是为了将来使用 Ventoy
进行 chainloading。
最后执行 xbps-reconfigure -fa
确定所有的软件包配置成功。
在 U 盘的第一个分区设置一个 ventoy 目录,里面建立一个 ventoy_grub.cfg
文件,内容如下:
set mygrub=/grub/x86_64-efi/grub.efi
menuentry "Enter the Void" {
search --set=root --file $mygrub
chainloader $mygrub
}
这样在 Ventoy 运行时按 F6 就可以看到我的菜单,并启动 U 盘上的系统了。
准备把我的云主机上开放给其他用户,为了限制这些用户的权限,必须选择一个可以
控制权限的 shell。
选择 firejail 主要还是经过对比,感觉它功能丰富,配置也比较简单。它利用 Linux
的命名空间、Seccomp BPF 等技术,隔离应用程序的文件系统、网络和进程。通过配置
文件支持为每个应用程序定制配置文件,定义允许访问的资源。
本来应该可以直接把 firejail 作为用户的登陆 shell,但在应用后,用户登陆时显示
没有指定 shell,连接立即被断开。可是使用 login.user
指定 --shell
参数会提示
这个参数已经 deprecated。用 default.profile
指定 shell 参数也总是说格式不正确。
简单的解决办法是写一个脚本作为用户的缺省 shell,而这个脚本直接使用 firejail 来执行
bash。
#!/bin/bash
exec firejail /bin/bash
这样用户登陆的时候就执行了一个受限的 bash,限制的条件完全通过配置文件来决定。
但这样设置的结果是用户在远程无法通过 scp 或者 rsync 命令传输文件。开始还以为是某些
权限设置的问题,调整了很久都没有效果。深入了解了这些命令才发现,它们实际上是通过
缺省 shell 启动了远程的其它程序。而之前的脚本无法处理这种情况。
比如用户执行了 scp 之后,缺省 shell 实际会收到如下的命令行参数:
-c /usr/lib/openssh/sftp-server
我写的脚本必须要处理这种情况。因此修改起来也比较简单,最后的脚本如下:
#!/bin/bash
exec firejail /bin/bash " $@"
这样带来的问题就是用户登陆后只能使用 bash。想使用其它的 shell,比如 zsh 的话就只能
自己登陆后运行或写到 ~/.bashrc
中。firejail 的主要应用场景是在沙箱中运行不可信的
程序。所以缺省配置中对各种本地的配置文件都做了保护。比如 .zshrc
是无法修改的,这
对于使用 zsh 非常不便。相应的配置在 disable-common.inc
中,而这个文件在 default.profile
中被包含。简单的解决办法是取消这个包含文件,这样大部分的软件都可以正常使用了。
限制一个程序也非常简单。比如要让用户无法使用 ssh,就只需要在配置文件中增加:
一直不是 LSP(Language Server Protocol)的粉丝,总觉得配置比较麻烦,但最近
试用了 kickstart.nvim,LSP 开箱可用,感觉还是有一些帮助的。
kickstart.nvim 是一个单文件的 Neovim 配置文件,包含大量注释和最常用的插件配置。
最方便的在于可以自动安装缺失的插件。只要网络环境允许,安装了它的配置文件之后,
只要启动 nvim 就可以自动完成后续的配置。项目地址:kickstart.nvim 。
在安装了 kickstart.nvim 之后,立刻做了一些自己习惯键位的设置,并调整了部分插件,
的确感觉比较省心。我做的修改可以在我的 github 中找到:my nvim config 。
插件系统使用 Lazy.nvim,需要更新插件的时候可以执行 :Lazy
,根据菜单可以选择更新(Update)、
清理(Clean)等等。LSP 使用 Mason.nvim,也可以执行 :Mason
看到类似的菜单。
一个对新手很有帮助的插件是 which-key.nvim,可以通过浮动窗口提示可用的命令按键。
比如在命令状态下按下 g 键,它就会提示你后续可以按的按键,下面代码是部分提示内容:
d -> LSP: [G]to [D]efinition
D -> LSP: [G]to [D]eclaration
I -> LSP: [G]to [I]mplementation
LSP 的功能也比较强大,比如可以在整个工程内进行变量改名:<leader>rn
,还有一个是 Code Action,
通过 <leader>ca
启动,具体能实现的功能由 LSP 本身来决定。
不同 LSP 的配置还不同。比如在使用 lua_ls 的时候,用 Code Action 功能关闭了对某个建议的提示,
后续找了半天没有找到从哪里恢复设置。结果最后发现保存在了 ~/.config/.luarc.json
这个文件中。
而 pylsp 的设置需要在 nvim 的配置文件中进行修改。具体其它一些用法还要在将来逐渐领会。
让终端可以显示的更美观。
只从更换到 alacritty 作为主要的终端模拟器之后,一直对它很满意,唯一遇到的问题是部分字形无法
显示,例如 💻 是一个电脑的图标,但在我之前的终端上显示不出来。但这种字形平时很少遇到,网页
上显示也都正常,就一直没有管它。究其根源就是这些字形在我目前使用的字体文件中没有定义,所以
无法显示。
最近又试用了 ghostty,它却可以正常显示这些字形,于是萌生了提升 alacritty 体验的想法。经过调研
发现 alacritty 没有字体 fallback 的设置,只能依赖系统的设置。解决的办法就是创建一个字体配置文件:
.config/fontconfig/fonts.conf
,内容如下:
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<alias>
<family> JetBrains Mono</family>
<prefer>
<family> JetBrains Mono</family>
<family> Noto Color Emoji</family>
</prefer>
</alias>
<alias>
<family> JetBrains Mono Bold</family>
<prefer>
<family> JetBrains Mono Bold</family>
<family> Noto Color Emoji</family>
</prefer>
</alias>
<alias>
<family> JetBrains Mono Italic</family>
<prefer>
<family> JetBrains Mono Italic</family>
<family> Noto Color Emoji</family>
</prefer>
</alias>
</fontconfig>
这里定义了我如果使用 JetBrains Mono
字体的时候,如果遇到不能显示的字形,就要使用
Noto Color Emoji
字体来显示。设置之后重启 alacritty 就可以正确显示之前缺失的字形了。
Noto Color Emoji
是我为了这次调整新安装的字体,不知道有什么办法可以知道 ghostty
使用的什么字体,ghostty 甚至不依赖系统的字体设置。
alacritty 对字体的 ligature 没有支持,ghostty 支持的就很好。
云平台上并没有 void 的镜像,本文记录如何在一个新安装的 arch 云主机上,安装并配置 void。
在 arch 主机上使用的是 btrfs 文件系统,这会大大简化分区操作。首先看一下当前配置:
pluto@arch4 ~ > sudo btrfs su l /
ID 256 gen 126 top level 5 path var/lib/portables
ID 257 gen 126 top level 5 path var/lib/machines
ID 258 gen 61 top level 5 path swap
前面两个应该是 systemd 建立,目前都是空的,swap 是虚拟内存空间,需要保留。
由于还准备保留 arch,双系统共用 home 会比较方便,所以建立一个 home 子卷。
pluto@arch4 ~ > sudo btrfs su cr /@home
Create subvolume '//@home'
pluto@arch4 ~ > sudo cp /home/* /@home/ -a
然后设置 /etc/fstab
挂载 home
分区,添加如下内容:
UUID= <your-btrfs-device-uuid> /home btrfs subvol= @home,defaults 0 0
注意如果 /home
目录的权限是 700 的话,普通用户无法访问个人目录,需要改成 755。
重新生成启动配置文件,检查生成的文件是否合理:
pluto@arch4 / > sudo grub-mkconfig -o /boot/grub/grub.cfg
接下来把 arch 的 文件系统做个快照,以后作为 arch 的根目录,同时建立一个 void 的根目录。
pluto@arch4 / > sudo btrfs su sn / /@archroot
Create snapshot of '/' in '//@archroot'
pluto@arch4 / > sudo rmdir @archroot/@home
pluto@arch4 / > sudo btrfs su cr /@voidroot
Create subvolume '//@voidroot'
重启后确认文件系统挂载没有问题,删除原来根文件系统中的内容:
pluto@arch4 / > sudo mount /dev/sda3 /mnt
pluto@arch4 ~ > sudo find /mnt -mindepth 1 -maxdepth 1 ! -name '@archroot' ! -name '@home' ! -name ' @voidroot ! -name swap -exec rm -rf {} +
此时必须重新安装一下 grub
,否则可能进入到 grub rescue 模式(刚刚犯了这个错误)
pluto@arch4 ~ > sudo grub-install --efi-directory= /efi
重启进入 arch 之后,挂载 @voidroot
目录:
pluto@arch4 ~ > sudo mount /dev/sda3 /mnt -o subvol= @voidroot
按照官方安装文档 安装 void。
需要注意的主要有以下几项:
允许 dhcpd 和 sshd 两个服务,否则重启之后可能无法连上主机。
bash-5.2# ln -s /etc/sv/dhcpcd /etc/runit/runsvdir/default/
bash-5.2# ln -s /etc/sv/sshd /etc/runit/runsvdir/default/
不重复安装 grub,使用 arch 的启动管理器,在 /etc/grub.d/40_custom
中
填入如下内容。
menuentry 'Void Linux' {
set root= 'hd0,gpt3'
linux /@voidroot/boot/vmlinuz-6.6.59_1 root= UUID= <your-btrfs-device-uuid> rw rootflags= subvol= @voidroot loglevel= 3 quiet console= tty0 console= ttyS0,115200
initrd /@voidroot/boot/initramfs-6.6.59_1.img
}
由于共享 home 分区,添加用户,注意 uid 和 gid 是否相同。
注意用户的 sudoer 设置,使用户可以获得 root 权限。
双系统使用不同的 ssh key 会让客户端很麻烦,因此将 arch 系统中的 key 复制到 void 系统中。
void 更新了内核之后需要更新 grub 的配置。
在 arch 系统中,可以使用
sudo grub-reboot 'Void Linux'
来让系统在重启之后进入到 void 系统。但由于文件系统是 btrfs,grub 无法直接修改,使得之后每次
启动都会在 void 系统中。解决方法是在 void 中安装 grub 工具,不执行 grub-install
安装。
然后用 grub-editenv
修改 arch 的启动设置。
pluto@void ~ > sudo mount /dev/sda3 -o subvol= @archroot /mnt
pluto@void /mnt/boot/grub > grub-editenv grubenv set next_entry= 'Arch Linux'
这样就可以在重启后进入 arch 系统。
手持拍摄的视频总会抖动,使用 Linux 的现成工具就可以进行修补。
首先将视频转换为图像文件:
$ ffmpeg -i ../INPUT.MP4 DSC_%03d.png
从图像中找到一个子图像用来对比,尽量小一点的图像便于快速定位,但必要要保证
图像有一定的特点,可以在视频中唯一定位。
接下来利用 ImageMagick 进行子图像的定位:
$ compare -metric RMSE -subimage-search big.png sub.png k.png
其中命令中的最后一个参数是具有定位信息的结果图像,在这里可以忽略。
编写一个简单的命令脚本将每次的定位结果写入到文件中:
$ for i in DSC_* ; do compare -metric RMSE -subimage-search $i sub.png k.png 2>> log.txt; echo >> log.txt; done
$ cat log.txt | awk '{print $4}' > pos.txt
pos.txt 中的坐标值就是子图像在每个视频帧的位置,然后编写一个小脚本对视频帧进行
剪裁。这里我用了 python 以增加扩展性,也许将来可以把全部内容写到一个程序中。
最后用 ffmpeg 将图像再编码成视频。
$ ffmpeg -f image2 -i pic%03d.png test.mp4
校园一卡通是 Mifare 卡,一直想了解它的原理……
MIFARE 是 NXP 公司的商标,主要用于利用 NFC 技术通信的低成本ID/IC卡。
网上找相关标准比较复杂,还是从工程的角度入手。淘宝购入 ACR122U 芯片
的读卡器,然后用相关软件对卡进行操作来增加对卡的认识。
读卡器到手之后在 Linux 下面无法正常工作,dmesg 显示错误消息:
NFC: Couldn't poweron the reader (error -11)
以为是内核的问题,更新了 Debian 到最新版之后问题依旧。
换个思路,在 ACS 下载了最新的驱动,并安装相关软件:
# dpkg -i libacsccid1_1.1.5-1~bpo9+1_amd64.deb
# apt-get install pcscd pcsc-tools
结果运行 pcsc_scan 之后,读卡器的红灯亮起,竟然开始工作了。
不过这个软件读到的只是卡的属性,并看不到具体的数据,继续安装了 nfc 软件
# apt-get install libnfc5 libnfc-bin libnfc-dev
使用 nfc-list 也只能读到ATQA(属性),UID(第一扇区前四个字节)和SAK(?)。
还需要下载一个强力的软件 mfoc,通过暴力破解获取数据。下载源码编译之后,运行
就可以将数据完整读出了,但由于是暴力破解,所以需要的时间比较长。感觉
读一张卡片要 10 分钟左右,比 Windows 下面的软件要快一些,也更加稳定。
mfoc 读出数据的过程也把密钥获得了,将密钥保存到文件中,下次读卡的时候就会
快一些:
# ./mfoc -f keys.txt -O mycard.mfd
目前还有一个疑问,不同的校园卡用的密钥竟然不一样,这样如何管理呢?也许
密钥不唯一,暴力破解的时候就有可能得到不同的值,实际密钥会是不同的一个。
另外如果用校园卡做门禁,只要用到 UID 部分就可以,也不需要破解,速度很快。
由于我比较习惯使用 latex 写自己的各种文档,而提交的时候又往往需要 Word 格式,
有一个合适的转换器就变得非常必要了。
将 latex 转换成 Word 格式的需求不断涌现,印象比较深的是 2011 年提交文稿的那次。
当时也是找了很多工具,最后使用了 tex4ht 工具,将文稿转换为 html,然后用自己
写的一些过滤脚本进行处理,最后才导入 Word。整个过程是比较痛苦而且错误百出的,
结果直到今天依然没有非常理想的工具。
最近又有了难以躲过的转换格式需求,pandoc 软件进入了我的视野,通过查看手册
发现 pandoc 简直是一个万能转换器,而我只是尝试了对 doc 的支持。
用它转换文件格式非常容易,不用配置脚本也没有复杂的开关选项。对于转换 latex
到 docx 只要如下的命令:
$ pandoc -f latex -t docx source.tex -o output.docx
不用解释就可以了解这个命令的使用方法,而且给我的第一感觉就是非常的快,甚至
比使用 latex 生成 pdf 文件的速度还快。唯一发现的问题是表格支持不太好,但表格
在我的文档中使用不多,手动调整一下就好了。
这次的主要任务是转换科技论文,pandoc 又一次给我了惊喜,大部分公式和图片都
很好的进行转换,只有几个问题需要关注:
pdf 格式的文件支持不好,必须先转换为 png 格式。
matrix 公式支持不好
公式里面自定义的 argmax 命令不支持
公式和图没有编号
感觉 pandoc 并没有使用 latex 作为后端,而是用自己的解释器来分析文档,因此
稍微复杂一些的 latex 指令就无法支持了。虽然还没有尝试,估计 pgf 系列包都
不会支持的很好。
没有编号的问题比较大,交叉引用全部都失效了,这次我都通过手工修改了。网上看到
好像有过滤器可以做类似的事情,但语法格式都不是标准的 latex,我就只好放弃了。
我开始以为参考文献是不被支持的,结果一个简单的过滤器就可以解决一半问题。
$ sudo apt-get install pandoc-citeproc
$ pandoc -f latex -t docx source.tex --bibliography= mybib.bibtex -o output.docx
这样是可以生成参考文献,但是格式不符合要求。经过网络搜索才知道还需要一个
格式描述文件(citation style language)ieee.csl 。下载这个文件之后用如下命令就可以
搞定参考文献了。
$ pandoc -f latex -t docx source.tex --bibliography= mybib.bibtex --csl= ieee.csl -o output.docx
尝试一下机智云的软硬件环境
机智云是一个比较常用的物联网云平台,由于手上有相关的硬件,因此准备尝试一下。
GAgent 是机智云的固件产品,写入到 ESP8266 wifi 模块后可以简化物联网
wifi 上网的主要功能。烧写固件需要到乐鑫(Espressif)下载工具软件,并从
机智云下载固件映像。按照机智云上的固件烧写说明却无法连接成功。由于我
用的模块来自第三方,猜想是 GPIO0 的管脚位置不同,最后查了淘宝上的一款
ESP-12F 模块,才知道我的 GPIO0 在从指示灯开始数的第五个位置。
第一次烧还是不成功,报 efuse 错误,结果第二次烧就成功了。
使用调试助手和 wifi 模块连接上之后,点击模拟 V4MCU,则可以自动和 wifi 模块
通过串口协议通信。输入 product_key 之后,可以在界面上看到我在机智云上建立
的产品信息。
在手机端安装上机智云的产品调试 APP(登录有问题,用我注册的个人用户帐号好像
无法登录,不过可以跳过登录,不影响使用),在调试助手中打开指令界面,选择
AirLink按钮,然后在手机端输入 AP 的信息并搜索硬件。大概十几秒之后 wifi
模块就可以登录机智云了,在手机段也可以看到我的产品信息。
手机软件根据我设置的产品信息可以看到照明的按钮,我在手机上对这个按钮进行
操作就可以在调试助手中看到照明的数值被改变了,也就是基本实现了我所需要
的功能。
使用 Arduino 连接到串口 wifi 模块,比较麻烦的是每次下载代码必须把 wifi
模块拿掉,否则会干扰下载。按照示例的代码下载了之后,从 DEV 到 APP 的通道
没有问题。但从 APP 到 DEV 就是不行。通过机智云网上的日志可以看到,消息传递
没有问题,应该就是 Arduino 这边的代码问题了。
后来把检测是否有相关命令的 hasBeenSet 调用去掉,直接用 read 读取相应的值,
结果就正常了。顺便说一下机智云自带的调试 APP 和下载参考代码生成的 APP
都可以用,功能类似。(3月17日更新:这个部分后来发现还是我自己的代码问题)
后来想在 ESP8266 模块中写入 AT 固件,自己控制 WIFI 接入,但确多次无法成功。
网上下载的不同固件都无法正常启动,在 minicom 中只能看到乱码。后来看资料
指导启动信息的波特率是 74880,minicom 和 screen 都不支持,最后还是 esptool
中带的 miniterm.py 支持。
看到的错误原因是 csum err,但 verify_image 也没有问题,不知道原因是什么。
网上看到有人说用 dout 方式写入就没有问题了,可用 win 下面的官方写入软件
根本就写不进去,最后下载开源的 esptool 就可以用 dout 方式写入了,结果看到
错误信息不一样了,变成
2nd boot version : 1.7(5d6f877)
SPI Speed : 40MHz
SPI Mode : DOUT
SPI Flash Size & Map: 32Mbit(512KB+512KB)
jump to run user1 @ 1000
mismatch map 5,spi_size_map 4
system_partition_table_regist fail
还是看网上的信息,说 1.7 的固件会有这个问题,但 1.6.2 的就没有问题了。
真是历尽千辛万苦终于获得了 ready 提示信息。
虽然记录的过程看来很简单,但实际经过的尝试复杂的多。
总体感觉机智云上手还是比较容易的,从昨天看资料开始,全部用掉的时间估计在
4 个小时左右。要不是软件这边有一点坑,应该更快的可以完成设计。
Google 现在好像不太支持命令行工具了,android 命令即将废弃,好像
已经没有办法只用命令行工具完成 Android 开发了。
只安装了 SDK 之后其实离开始工作还有很大距离。运行 sdkmanager --list
可以看到能安装的组件,然后就可以用 sdkmanager
安装,例如
$ sdkmanager "emulator;platform-tools"
建立虚拟机可以用 avdmanager 命令,例如:
$ ./avdmanager create avd -n test2 -k "system-images;\
android-25;google_apis;arm64-v8a" -d "Galaxy Nexus"
其中 -d --device
参数在手册里面都没有提,在执行 create avd
命令的时候可以看到相关的提示。而可选的设备列表在 lib/devices.xml
文件中可以找到。
这个命令在执行的时候有可能报告 libGL 的加载失败,可以在运行前指定:
$ export ANDROID_EMULATOR_USE_SYSTEM_LIBS= 1
原来的 android create project
命令已经不被支持,目前只能使用 android
studio 建立工程。