/avatar.png

只是虚无的博客

本站提供的所有内容仅供学习、交流和分享用途,只供参考

Flutter远程开发环境记录

ArchLinux环境下的Flutter远程开发环境配置记录文,如有参考请注意时效性 Flutter 安装 安卓需要jdk8和jdk17,所以提前安装 pacman -Sy jdk8-openjdk jdk17-openjdk

btrfs parent transid verify error的玄学修复记录

/btrfs_parent_transid_verify_error/寒くて袖に手を入れてるミクちゃんが見たい_113620158.png

错误排查

小伙伴大半夜找我说暗影大人的视频无法播放了,我去确认了一下,jellyfin转码烧录mks字幕确实出问题了,但是让客户端不转码直接本地播放是可以播放的,就没在意,直到第二天一觉醒来,他又来说问题了,这次不是视频无法播放,而是jellyfin打不开了

我第一反应是ddns寄了,或者我路由网络又出毛病了(昨晚才处理好的Clash DNS解析啊),但是一个测试发现并没有,只是所有web服务都无法访问了,ssh看了下docker,好家伙docker寄了

好端端的docker怎么会寄,考虑到docker容器所在的分区曾经寄过,我dmesg看了下,嗯,磁盘分区寄了,症状和上次类似,只是这一次寄得更彻底了。

首先,寄了的问题磁盘分区是ArchLinux上的sdb1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Disk /dev/sdb: 1.75 TiB, 1920383410176 bytes, 3750748848 sectors
Disk model: SDLF1CRR-019T-1H
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: B9A58F50-EE49-49CF-825C-A96C869F0C67

Device          Start        End    Sectors  Size Type
/dev/sdb1        2048 2702172847 2702170800  1.3T Linux filesystem
/dev/sdb2  2702174208 3750748159 1048573952  500G Linux filesystem

而这是dmesg记录的一部分日志,因为这是事后回忆整理,我留下的记录并不是很多,悲

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[204772.045179] BTRFS warning (device sdb1): checksum verify failed on logical 114737152 mirror 1 wanted 0xa1e021a8 found 0x0944aebf level 0
[204772.045592] BTRFS warning (device sdb1): checksum verify failed on logical 114737152 mirror 2 wanted 0xa1e021a8 found 0x0944aebf level 0
[204772.045632] BTRFS: error (device sdb1: state A) in __btrfs_update_delayed_inode:1065: errno=-5 IO failure
[204772.045662] BTRFS info (device sdb1: state EA): forced readonly
[204772.045670] BTRFS: error (device sdb1: state EA) in __btrfs_run_delayed_items:1156: errno=-5 IO failure
[204772.045690] BTRFS warning (device sdb1: state EA): Skipping commit of aborted transaction.
[204772.045696] BTRFS: error (device sdb1: state EA) in cleanup_transaction:1997: errno=-5 IO failure
[210074.918333] BTRFS error (device sdb1: state EA): level verify failed on logical 771833856 mirror 1 wanted 1 found 0
[210074.918670] BTRFS error (device sdb1: state EA): level verify failed on logical 771833856 mirror 2 wanted 1 found 0
[210074.919073] BTRFS error (device sdb1: state EA): level verify failed on logical 771833856 mirror 1 wanted 1 found 0
[210074.919330] BTRFS error (device sdb1: state EA): level verify failed on logical 771833856 mirror 2 wanted 1 found 0
[210074.919657] BTRFS error (device sdb1: state EA): level verify failed on logical 771833856 mirror 1 wanted 1 found 0
[210074.920055] BTRFS error (device sdb1: state EA): level verify failed on logical 771833856 mirror 2 wanted 1 found 0

尝试找到错误文件

可以看到错误首先是114737152这个inode对应的文件校验错误,那么首先应该找到它,好在分区虽然寄了,但是因为forced readonly所以依旧能挂载并且可读,先一个find ./ -num 114737152尝试找到它,结果并没有像以前寄的时候那样找到对应的文件,而是直接打印了一大堆的报错

1
cannot access filename: Input/output error

通过btrfs工具查看错误

btrfs虽然是以不成熟和不稳定且性能一般闻名于世,不过还是提供了一些工具来尝试解决常见问题

通过谷歌搜索,我找到了一个类似问题的疑难解答页面,本来以为是人家单独列出来肯定是常见好救的,结果它建议我备份数据,这是一个永久性错误,并且原因不明

这不能够啊!

这个文档里虽然没有提供任何修复方案,但是记录了btrfs的各种命令用法,倒也不算没有一点用处

确认一下btrfs记录到多少个错误

btrfs dev stats /dev/sdb1跑一下,上一次分区错误的时候,这里记录了几百个错误,但是没有处理好,我最后格式化分区了,出乎意料的,这次一个错误都没有发现

1
2
3
4
5
6
> $ sudo btrfs dev stats /dev/sdb1
[/dev/sdb1].write_io_errs    0
[/dev/sdb1].read_io_errs     0
[/dev/sdb1].flush_io_errs    0
[/dev/sdb1].corruption_errs  0
[/dev/sdb1].generation_errs  0

虽然不知道这意味着什么,但没有错误记录,也许还有救,在网上找一找前人的经验,比方说StackOverflow上的帖子

尝试usebackuproot

按照帖子里的一个答案,只读挂载时带上usebackuproot
mount -t btrfs -o ro,usebackuproot /dev/sdb1 /home/cache
如果能够成功挂载,则去掉只读的ro重新挂载,能挂载上说明修复了

我尝试只读挂载成功并没有问题,毕竟我本来就能只读挂载,此时再次进入/home/cache目录尝试读取文件,依旧是Input/output error,抱着侥幸心理,我尝试不指定只读挂载,即mount -t btrfs -o usebackuproot /dev/sdb1 /home/cache,不出意料的发生了错误,但是错误信息我没保留下来,所以没法展示了

格式化前的死马当活马医

前文说过,我这个分区不是第一次出现这种错误,上一次我尝试了各种btrfs的命令也没修复成功,但成功把数据给备份出来了 而这一次我讲数据复制出来都会发生错误,其实并没有什么动力去研究,毕竟有一次失败在前,而且这次连备份都做不到,甚至产生放弃btrfs,格式化回ext4的想法

就在我即将运行mkfs.ext4 /dev/sdb1时,我突然想到这次btrfs dev stats并没有报错,虽然出现了上次没有出现的Input/output error,但是btrfs本身的情况也许没那么糟糕,上次用过的命令可以试试

btrfs有不少的子命令工具可以做一些诸如重建树或者擦除

先跑一个btrfs scrub status /home/cache看看结果

1
2
3
4
5
6
> $ sudo btrfs scrub status /home/cache
UUID:             74cd7002-8aaf-4421-b4f4-4320ee12850c
        no stats available
Total to scrub:   256.06GiB
Rate:             0.00B/s
Error summary:    no errors found

没有错误

btrfs有一个不建议使用的命令可以尝试修复错误,即btrfs check --repair /dev/sdb1,我上一次也执行过,但并没有修复我的问题

但这次既然没有错误,也就是有尝试的价值

直接运行btrfs check --repair --force /dev/sdb1,果然跟上一次什么变化都没有的输出不同,它输出了很多修复节点的信息,也没有保存下来

运行完成之后,我尝试可读写挂载,问题依旧

峰回路转

失望也带着绝望,我只能格式化了,并且这次格式化我不打算再使用btrfs了,它已经两次在同一个分区上寄了,mkfs.ext4 /dev/sdb1,跟数据和btrfs说拜拜吧 其实我挂载的路径是cache就说明了没有什么重要数据,仅仅是缓存分区,随便格的那种

出乎意料的,格式化没有开始,设备繁忙中

我确认了一下,我已经卸载设备了,并没有挂载到目录,btrfs dev stats也显示设备被占用

也许是check占用了设备没有释放,此时的我也没有心情去关心了,只想快点格了然后重建docker容器恢复服务

关闭docker服务开机自启,关闭systemd的开机自动磁盘挂载,重启设备一气呵成

开机之后,我正要格式化,又想,也许它好了呢?

于是我只读挂载了一下,正常挂载,甚至执行ls的时候都没有Input/output error了,并且dmesg也没有任何错误信息,我心情有点小激动,二话不说systemctl start docker,看看docker能起来不,起不来,依旧是报错,报错信息我都懒得看了

等会,我现在是只读挂载,docker怎么可能起来!!

改成可读写挂载,docker启动了!!服务上线了!!

后续

访问一下jellyfin,发现页面有了,但登录页打不开,F12看一下原因,少了一个js文件,直接重建容器,一切都正常了,也许btrfs check --repair给我移除了无法通过校验的文件

准确说我不清楚我是怎么修复的,我只能靠回忆记录下这个并没有多少操作的过程,其中我如果有那么一次没有想再看看分区是不是好了,或者check之后设备不是繁忙中,我恐怕不敢相信我居然能看到它恢复正常,这大概就是不放弃吧(bushi

记一次Rust静态编译

前景提要 Rust这门语言出了名的难学难懂,我也是前前后后多次企图入坑又多次不了了之,一直到前段时间才真的用Rust写一些东西,在这之前,我接

Aio服务器搭建

个人Aio服务器搭建(未完待续)

以下是碎碎念,建议跳过

百度云限速、360云盘迅雷云盘等相继关闭;QQ音乐、网易云音乐版权竞争,歌单里的歌三天两头灰色,独占的独占,曲库缺失的缺失,为了听歌还要每个平台都开会员,并且体验依旧割裂;爱奇艺异军突起、腾讯视频独霸江湖、优酷抱紧了老剧,哔哩哔哩看个纪晓岚标注着1080P事实上并不达标;广电要求影视作品一律先审后播,b站在抽帧黑幕圣光之后直接连追番都不行了,没法同步上映……与此同时,网上一大堆家庭NAS方案层出不穷……

所以我不禁开始思考,已经在上班的我,是时候回收一下中学的梦想————想要一台自己的服务器。

常年的网易云会员,b站会员现在也都已经过期了,促使我不再续费的原因,不外乎网易云越来越多的灰色,哔哩哔哩越来越少且不一定能同步更新的番,老实说,会员不贵,但体验实在是太割裂了。只能去特定平台才能看到特定的东西,对于视频其实还好,切一个app,但是音乐咧,我只想随机我所有的歌,我没法把几个平台的歌放在一起随机。

总之,作为正版流媒体平台的受害者,我选择离开流媒体平台,支持正版的方式有非常的多,比方说买专辑,买光碟,但是,我需要一个允许我在任何地方在线播放的平台。

所以,我需要一个NAS。

但显然不够,作为一个coding玩家,我还需要一个开发环境,我需要一个运行环境等等等等

所以,All In One,好巧不巧,我家有公网IP,而我又有域名,Cloudflare又可以白嫖DDNS,走起~

平台和硬件选择

低功耗 or 高性能

确定了要AIO,那自然需要考虑一个严重的问题,传统NAS上肯定是追求低功耗的,并且不要求多高的性能,树莓派都可以胜任,甚至还有路由器刷op挂一个samba直接用的。

当然了,NAS其实还有很多现成的方案,群晖啊,威联通啊什么的,而硬件上,也有之前的矿机什么星际蜗牛啊,最早的J1900到后来的J3455,可以说是五花八门了。

不过都有一个共同特点,恰好都不是我现在入手能捞到实惠的东西,车那是一去不复返,鱼塘全涨价了。

还有一个很重要的点,我不打算花很多钱,我预算1000以内弄完除硬盘以外的东西,然后花500左右整硬盘。

并且我需要足够高的性能,J1900这些是不太行了,J3455绝对就超预算了。

最后选择了闻名江湖的E5神教!

配置单

1
2
3
4
5
6
7
8
9
主板:华南X79豪华板
CPU:E5 2650L V2
网卡:Intel 82576
电源:500W银欣(型号忘了)
散热:酷冷至尊(未知型号)
显卡:黄伟达 GTX 1050(真实型号估计是GTS 450)
内存:16*2 + 8*2 总计48G的四通道DDR3 ECC
固态:影驰 铁甲战将 240G SATA3
机械:HGST 矿盘 3T*2

除掉硬盘,算上邮费,总共花了750,邮费就84了, 两块HGST,赶上了涨价,花了454, 所以总共1204,还可以吧,预算内

这一套下来满载上200W了,不过考虑到大部分时间是基本上空载的,当然算不上省电,根据网友的测试,空载不到20W,一个月十几块钱电费吧(-_-

系统和软件

一般人就是直接黑群晖了,但咱是一般人嘛,咱是折腾佬啊

想都没想就是手搓KVM虚拟化,从此踩坑无数后续章节慢慢补坑

正片

一、Arch物理系统安装

首先贴上Arch的官方wiki的中文安装文档

好了,本章完结

以下注意事项

  1. fdisk工具不支持gpt格式,也不支持2T以上容量的分区操作,所以我建议用parted代替,当然这个工具也是安装在Arch的livecd里了
  2. /etc/locale.gen文件一定要编辑,然后用locale-gen生成信息,并且在/etc/locale.conf文件中至少写上LANG=en_US.UTF-8,否则将无法在终端显示中文,即使你安装了中文字体
  3. 在重启到安装好的系统之前,网络工具一定要装,这里推荐一下networkmanager,安装命令sudo pacman -Sy networkmanager,然后设置开机启动sudo systemctl enable NetworkManager
  4. 安装好系统之后,文档里有简单的提了一下安装引导的事情,如果你不想开不了机,就记得点一下GRUB进去看一下关于引导的安装
  5. 包管理器我建议使用yay而不是pacman,它们的命令是基本上一样的,但yay支持从archlinuxcnAUR下载软件包,这显然比pacman更方便,以下的命令我将使用yay而不是pacman

因为AIO服务器的重点并不在物理机的系统安装上,而且网上有太多的同类教程可供参考,所以我就略过了,只标注了我认为需要注意一下的东西

二、KVM虚拟化

安装好物理机之后,接下来就是虚拟化,显然现在有非常多的懒人解决方案,集成度非常的高,效果也不错,有基于Debian的各种系统,也有不基于任何平台的单纯WEB管理的各种虚拟化管理页面,but,本着不对外提供服务的东西不需要可视化界面的原则,以及对KVM虚拟化的好奇,我不使用各种WEB或GUI管理工具。

同样,我会在开头,将ArchWiki的文档放在这里,使用Arch的好处就是相当完善的文档,并且中文支持不错,当然我还是建议尽可能的查看英文文档,毕竟更新及时.

检查虚拟化支持

纯软件虚拟化不是不行但是效率实在实在太低了,所以现在都是从硬件平台上就开始支持各种虚拟化技术,也就是说,你需要先在主板的BIOS上打开虚拟化的开关,然后在系统里确认对虚拟化的支持状态。

  1. 在终端执行LC_ALL=C lscpu | grep Virtualizationgrep -E --color=auto 'vmx|svm|0xc0f' /proc/cpuinfo,输出什么东西并不是太重要,重要的是不能没有输出,如果没有任何东西输出的话,你就需要去主板检查一下bios是不是没有正确打开虚拟化的开关

    /aio-server/kvm-lscpu.png

  2. 在确定了硬件支持之后,就需要确定软件是否安装了,执行zgrep CONFIG_KVM /proc/config.gz查看Linux内核的虚拟化模块是否安装,如果输出的结果不是y或者m,则说明虚拟化模块没有安装到位。因为我没有遇到这个问题,所以我只能将安装模块的文档放在这里,如果你遇到了,请自行解决

    /aio-server/kvm-config-gz.png

  3. 之后需要确定内核模块是否已经加载,执行lsmod | grep kvm,如果执行了之后没有输出东西,但是上一步又确定了已经安装模块,那就需要手动加载同样的,我也没有遇到这个问题

    /aio-server/kvm-lsmod.png

到这里就差不多了,当然还有其他的东西可以使用,比方说VIRTIO模块、嵌套虚拟化之类的东西,可以参考上面的文档自行检查。

安装软件包

在Arch安装软件一直都是一件轻松愉快的事情,archlinuxcn也好AUR也好,可谓是独步天下

不过我这里需要说明的事情是,KVM是一种虚拟化技术,而不是一个虚拟机,我们需要一个虚拟机来应用这种技术,在Linux平台上,那自然是QEMU

同样,文档就放在这了

因为我不启用GUI,也就是不安装桌面,所以我不需要对图形化的支持,在安装qemu的时候我选择qemu-headless,如果你有图形化的需求,则安装qemu

安装命令yay -Sy qemu-headless

QEMU简单跑个win虚拟机

运行Windows虚拟机跟直接跑Linux虚拟机不太一样,所以我单独列了一个小节,如果你不打算运行Windows虚拟机,那可以跳过,注意,本小节旨在将Windows虚拟机运行并完成安装,不会涉及到显卡直通或虚拟化显卡的内容

准备文件
  • 因为微软❤️开源,所以我们没法直接在qemu虚拟机上启动Windows的镜像,我们需要一个辅助镜像virtio-win,Arch可以直接通过包管理下载到,执行命令yay -Sy virtio-win,然后这个镜像会被下载到/var/lib/libvirt/images/virtio-win.iso,将它复制到跟我们Windows系统镜像一个目录下就行了。

  • 下载Windows的系统镜像,比方说我下载的镜像重命名为win10_2004.iso主要是原来的名字太长了

  • 现在启动镜像和系统镜像都有了,我需要创建一个虚拟磁盘,就像装物理机的系统需要一块硬盘一样,虚拟机一样需要能识别到一个磁盘空间,执行命令qemu-img create -f qcow2 win10.qcow2 100G,这里我创建了一个叫win10.qcow2的镜像文件,镜像格式是qcow2,容量大小是100G,不过不用担心你的物理空间没那么大,它不会直接占用100G的空间,是动态占用的,不过你依然至少保留20G的空闲空间。

至此,我们必要的文件就已经准备好了

启动win10虚拟机

qemu跟VMWare和VBox那些不一样,它不具备管理和持久化虚拟机的能力,你需要手动配置每一个参数,然后以命令的形式运行,运行之后不会保存参数,你下次运行依旧需要输入那些参数,所以我们创建一个shell文件来运行,省得敲那么长的命令

并且我们不直接使用qemu命令,因为qemu软件包已经提供了一个不同架构的命令,比方说我们跑64位x86的虚拟机就用qemu-system-x86_64用这个已经很繁琐了,就不用更繁琐的qemu

执行vim win.sh然后复制下面的东西

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
qemu-system-x86_64 \
        -enable-kvm \
        -m 8G \
        -smp 20 \
        -display default \
        -vga virtio \
        -machine q35,vmport=off,dump-guest-core=off,mem-merge=off,hmat=on,usb=off \
        -drive file=win10.qcow2,index=0,media=disk,if=virtio \
        -drive file=virtio-win.iso,index=1,media=cdrom \
        -drive file=win10_2004.iso,index=2,media=cdrom \
        -spice port=5900,addr=0.0.0.0,disable-ticketing=on

别忘了把文件名和路径换成你们自己的,还有一些参数,比方说-smp 20是20核,建议改成你的电脑的真实配置,包括-m 8G是虚拟机分配的8G内存

然后给它执行权限chmod +x win.sh,再运行它就可以启动了,但是因为我们没有图形化,看不到启动,这就需要我们从其他电脑远程了,上面的脚本里我使用了spice来做远程,自行从互联网下载一个支持连接spice的客户端连接即可。

剩下的事情就是正常的安装和重启,就可以看到一个非常卡的win10虚拟机在跑了

Libvirt 管理KVM

qemu非常的强但是不好用,所以我们需要一个能像正常虚拟机一样管理它的,这里就不得不提libvirt,它提供了一些C实现的后端接口,和一个能用的前端virsh

安装软件包

安装依旧很简单,只需要执行yay -Sy libvirt,但是只有这个是不够的,不同于上面小节中简单的启动一个虚拟机,我们需要管理一些东西,比方说网络,所以我们还需要一些其他的东西

执行 yay -Sy libvirt bridge-utils dnsmasq

启动服务

libvirt是一个常驻服务,所以需要启动,执行sudo systemctl start libvirtd,不过这样每次都需要手动启动,执行sudo systemctl enable libvirtd实现开机自启

同时,我们需要启动virsh自带的NAT网络,执行sudo virsh net-start default

可以执行sudo virsh net-list --all查看网络是否启动了,如果有一个defalut网络那就是启动了

使用原生virsh启动虚拟机

创建win10.xml文件,复制下面的内容,修改之后,执行virsh define win10.xml可以增加一个虚拟机,并且受virsh管理。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<domain type="kvm">
  <name>win10</name>
  <memory unit="GiB">8</memory>
  <vcpu placement="static">20</vcpu>
  <os>
    <type arch="x86_64" machine="pc-i440fx-xenial">hvm</type>
  </os>
  <cpu mode="host-passthrough">
    <topology sockets="2" cores="10" threads="2"></topology>
  </cpu>
  <devices>
    <disk type="file" device="disk">
      <driver name="qemu" type="qcow2" cache="default"></driver>
      <source file="win10.qcow2"></source>
    </disk>
    <disk type="file" device="cdrom">
      <source file="win10_2004.iso" index="2"></source>
    </disk>
    <disk type="file" device="cdrom">
      <source file="virtio-win.iso" index="1"></source>
    </disk>
    <graphics type="spice" port="5900" listen="0.0.0.0" passwd="yourpassword"></graphics>
  </devices>
</domain>

虽然这是核心玩法,但是手写xml文件真的太麻烦了,而且参数实在太多了,所以还是需要一个东西,能帮我们手动生成一些模板配置,只需要在这个基础上简单修改我们的参数,这就是virt-install了。

安装virt-install

一样直接安装即可yay -Sy virt-install

安装这东西让我纠结了非常久,因为我本来是不想在物理机上装任何执行环境,哪怕是Python,但是手写xml真的太麻烦了……这之间我发现了有另一个libvirt-go的项目,我在想如果有一个virt-install-go的项目就好了,这样不需要依赖也能直接用,不过目前是没有的,虽然可以自己实现,我自己稍微写了一下,这个周期实在太长了,而且libvirt-go本身也还有问题,文档也非常的缺,只能先用virt-install这个py的版本了……

使用virt-install创建win10虚拟机

执行

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
virt-install \
--name Win10 \
--memory 8192 \
--vcpus sockets=1,cores=10,threads=2 \
--os-type=windows \
--os-variant=auto \
--cdrom=win10_2004.iso \
--disk virtio-win.iso,device=cdrom,bus=ide \
--disk win10.qcow2,bus=virtio,size=100,format=qcow2 \
--graphics spice,listen=::,password=yourpassword \
--hvm \
--autostart \
--virt-type kvm

然后就可以用spice连接过去看了,本地的窗口运行可以Ctrl+C关闭了

virsh管理虚拟机

注意: virsh命令不需要root权限

  • 查看虚拟机列表: virsh list --all
  • 关闭虚拟机(不删除): virsh destroy name
  • 删除虚拟机(不关闭): virsh undefine name
  • 设置虚拟机开机自启: virsh autostart name
  • 取消虚拟机开机自启: virsh autostart --disable name

如果你的虚拟机正在运行,没有先执行关闭就执行了删除,虚拟机不会被马上删除,会等到关闭之后才删除

Linux触屏旋转

说明 其实这是一个回忆记录贴,前几天朋友提到了这件事,所以想记录一下 起因是这样的: 我收了一个x86的板子,酷比IWork10 Pro 旗舰版,具体型号

博客搭建指北

指北说明(个人记录) 根据国际惯例,记录一下搭建(踩坑)过程,虽然全程不会涉及什么技术向的东西,但希望读者对 GitHub 和 git 有所了解 该博客使用 hugo 生成,搭