Skip to main content

Posts

Showing posts with the label 评论和记事

My Experience with libvirt

My daily driver setup has been working exceptionally well. If you missed them, you can check out the previous posts for details: Part 1 Part 2 Part 3 Recently, I decided to harden my setup by writing custom AppArmor profiles and nftables rules. During my research, libvirt kept popping up in tutorials. In fact, most “QEMU/KVM” guides simply assume you are using it. Initially, I decided against using libvirt because I wasn’t a fan of its design philosophy. However, I kept hearing that it can automatically generate AppArmor profiles and firewall rules for each VM. Furthermore, this article highlighted several things that libvirt genuinely simplifies. Intrigued, I decided to dive in and get some first-hand experience. The plan was to migrate my existing VM setup (which relies on bare QEMU scripts) to libvirt to see if it was a good fit. I specifically wanted to evaluate the parts of libvirt I was previously skeptical about: Reliance on a highly privileged daemon. Configuration stored...

Linux Daily Driver Setup Part 3: VM Control Panel

Now that I have my VMs running, what if I want to switch between them? What if I want to put the VM or the host to sleep, or shut them down? In this post, I’ll discuss a few options. Just a quick overview of my setup: Only one VM is running at a time. All VMs have GPU passthrough, and the GPU is connected to a display. I have a secondary display, which I prefer not to use unless absolutely necessary. See also: Part 1 Part 2 Option 1: Deep Integration with Guest OS Ideally, I could just click on a “Power off and Switch to VM X” menu from within the guest OS. This isn’t difficult to support on the host side: the guest OS could pass the VM name to the host (e.g., via a serial port), and the host would automatically start the next VM when the current one exits. However, I didn’t find an easy way to implement this menu, especially considering I plan to support multiple operating systems. I also couldn’t find a way to prevent the guest from shutting down without providing the next V...

VM Setup Part 2: QEMU

Previously, I decided to set up a headless VM orchestrator for daily driving and gaming. In general, installing a minimal Debian and QEMU is fairly straightforward, but the devil is in the details. Here are my notes on the process. See also: part 1 Overall Setup The machine is a laptop. The built-in display is connected to the iGPU, and an external display is connected to the dGPU. I prefer to use only the external display; the built-in one is rarely used. I have two VMs: one as a daily driver and the other for gaming. Both have GPU passthrough. Only one runs at a time. Resources Reserved for the Host CPU: 1 core, 2 threads. RAM: 2GB (typical usage is around 500MB). Disk: 32GB. The OS only needs ~2GB, but I need extra space for cache, log, OS images, etc. CPU The main QEMU process and IO thread should be pinned to the host CPUs. vCPU threads should be pinned to the CPUs reserved for the VM. CPU pinning cannot be done through QEMU command-line arguments. I had to talk to the QEM...

Exploring Gaming VM Setup (Part 1)

For years, I've been playing games and doing everything else on the same PC. Hoever, after a recent positive experience with Qubes OS, I no longer feel comfortable keeping my games, passwords, and other stuff all in the same place. Because of this, I decided to change my gaming setup. My requirements are: Performance. Gaming should be functional and playable. Isolation. At a minimum, game binaries should not have access to my other files. Quick Switch. I need to be able to switch between gaming and non-gaming easily. Single Display. All my workflows should be performance well on a single display. I do have a secondary display, but I want to rarely use it. So, here goes my adeventure. Option 1: Dual Boot This is the classic solution, which sounds boring but almost always works. Performance: Good. All operating systems have direct access to physical hardware. Isolation: OK-ish, each OS technically has access to all data from other OSes. Disk encryption and Secure Boot can mitigate th...

Solving LVM Detection Failures in GRUB After a Force Shutdown

After a routine system update and an unfortunate hang that required a hard reset, my Linux machine refused to boot. Instead of the familiar login prompt, I was greeted by a cryptic GRUB error:  error: no cryptodisk module can handle this device. My setup uses LUKS2 + LVM. From the GRUB rescue shell, I could actually decrypt the LUKS container. But once decrypted, GRUB completely failed to detect any LVM volumes. It simply acted as if the LVM structure didn't exist. Meanwhile, if I boot it from a Live Rescue USB, everything worked perfectly. I could open the LUKS container, and the volume group appeared immediately. Tools like  vgck  and  pvck  reported no issues. After a length discussion with AI, eventually I found the magical commands: vgcfgbackup -f lvm_backup.txt <vg_name> vgcfgrestore -f lvm_backup.txt <vg_name> After running these commands and rebooting, GRUB recognized the LVM volumes immediately, and I was back in my system. Supposedly this f...

Writing Sudoku Solvers

After writing a Nonogram solver, I decided to tackle a Sudoku solver to practice Rust. My goal wasn't just to support classic Sudoku rules, but also to handle variants like Thermometer, Arrow, and Cage etc. 1. Brute Force It is fairly easy to write a brute force or backtracking algorithm. This approach is sufficient for most classic Sudoku puzzles, but it becomes unbearably slow as soon as variant rules are introduced. I considered this step a warmup—a baseline to improve upon. 2. Constraint Propagation Here, I tried to introduce "logical thinking" to the algorithm. I used  u16  as a bitmask to represent the possible values of a cell. Whenever a cell's state changes (due to guessing, backtracking, or propagation), the algorithm consults all constraints to eliminate impossible candidates. While Nonogram is technically an NP-Complete problem, in practice, my constraint-propagation solver (without guessing) can solve almost all puzzles found online. I’ve only seen one ex...

Sending Emails with Curl: A Nifty Systemd Workaround

I recently tried to create a simple systemd service to send an email notification, but my initial approach with mail and sendmail failed with a strange permission error. My original service file looked like this: [Service] ExecStart=mail --subject=Subject recipient@example.com The error message was a bit of a head-scratcher: warning: mail_queue_enter: create file maildrop/....: Permission denied . A quick search pointed me to the cause : the postdrop binary has setgid. However, the systemd setting NoNewPrivileges=true prevents this. While I hadn't explicitly used that setting, I was using DynamicUser=true , which implies and enforces NoNewPrivileges=true . This meant my service, running as a temporary user, couldn't get the permissions it needed to interact with the mail queue. Note that this implication cannot be disabled/overriden. I wanted to avoid creating a new, dedicated user for this task. I realized that the problem was how mail and sendmail directly interact wit...

GNU Stow

Just learned about GNU Stow , which is a tool for managing symlink farm. Basically the idea is to store all files in one place, then create symlink all around the system pointing to your files. There are various use cases, like dot files and installing/uninstalling packages. But I mostly use it for tracking system config files, similar to how NixOS works. In fact I wrote my own scripts with "cp -rs", but GNU Stow works much better.

First 3 Days with bootc

I decided to spend some time playing with bootc. Mostly I'm inspired by the following articles:  CoreOS + native container Hand-on demo (the last video), build bootc and auto update from registry bootc desktop bootc for homelab Day 1 To install bootc in a VM I need an image. bootc-image-builder requires root and I don't want to run this on the host. So I chose CoreOS as the inital system and installed it to QEMU. I thought it is a great idea to share a folder from host to guest as podman container storage. However, it was not as smooth as I had expected: virtiofsd on Debian is too old, so I set up NFS. rootless podman doesn't work well with NFS . rootfull podman complains upstream fs of overlayfs missing features, the performance was terrible. I gave up. I guess I'll just use the CoreOS disk, whose size is 10G, not enough. Day 2 I didn't find a way of resizing a qcow2 image online. On the other hand I figured maybe I don't need build a disk image after all. Cor...

UID and GID: The New Order

When I have important data on a device, I back it up to my server using dedicated user accounts. The other day, I checked /etc/passwd on my server and found entries like this: some-backup-user1:x:1003:1004:... some-backup-user2:x:1004:1007:... A few inconsistencies immediately bothered me: UID/GID Mismatches: Many users have UIDs that don't match their primary GIDs. While this technically works and might seem like just an aesthetic concern, I realized that UIDs and GIDs are crucial metadata. I need to preserve them accurately for future system migrations to maintain correct file ownership.ID Ambiguity: ID Ambiguity: The same number (e.g., 1004) could represent a User ID for one account and a Group ID for a completely different group. This overlap is a recipe for mistakes during administration tasks if I'm not paying close attention. Lack of Structure: User and group accounts created for very different purposes – regular logins, backup processes, container management, specifi...

再度音乐寻宝

平时脑子里会无缘无故,不由自主地蹦出一些旋律。这些旋律很熟悉,也肯定不是自己现编的,但是就是想不起来具体的名字,歌手或者哪里听到的。 最简单的情况是记得歌词,或者可以哼唱检索。最难的大概是影视作品的配乐,我觉得成功的配乐会让人记得当时的“感觉”而不是曲子本身的细节。 继上次 音乐寻宝 之后,又一个旋律出现了,令我吃不香睡不着。 经过几天的查找,最终还是找到了,结果是井上昌己的《Up Side Down 永遠の環》,出自圣少女的ED。过程还是挺有趣的。 1. 我大概记得开头intro的旋律,以及歌词的整体节奏,类似词牌。然而试了若干哼唱检索,都没有结果。 2. 我大概记得一些歌词片段,于是去各种网站搜索。然而结果证明我记忆的片段是错误的。 3. 我“感觉”这是一个日本动画的ED, 于是去搜索了80 90年代引进的日本动画, 以及00-08年流行的日本动画的OP ED,然而没有找到。这个比较巧妙,因为圣少女国内引进过,但是节选了OP和ED。我其实也翻了日版动画,大概看了前几集和后几集的OP ED,万没想到结果是中间的。 4. 我“感觉”动画是跟魔法少女有关,所以翻了翻魔卡少女樱和Marybell的乐集,一无所获。当时其实也过了一遍圣少女的乐集,不知为何漏掉了。 5. 后来放宽了条件,搜了一些类型相似的动画乐集,虽然没找到当前这个,但是意外找到了我的女神里的《優しい心》。这个也是以前突然蹦出来的旋律。同时翻到了同作品里的《願い》,感觉跟要找的相似,然而其实没啥相似,除了都是欢快的曲子。 6. 于是放弃了,能试的都试了,只能随缘了。 7. 后来调整了下思维,想到有没有可能是其他类属性。于是翻了一下邓丽君的日文歌集,甚至《梅兰梅兰我爱你》,当然还是无果。 8. 最后真的是随了缘,重翻了一下圣少女的乐集,竟然找到了。 这个过程里我觉得最有趣的是两点: 一是我记忆里的“感觉”,日本动画, ED, 魔法少女。这样的记忆比曲子本身深刻一些。这也让找曲子更困难了一些。 二是我记忆里的不确定因素,包括旋律歌词。我试想过多种可能的乐器组合,以及歌词韵脚,感觉都有可能。最后也证明我这部分记忆都是不准确的。

记忆中的音乐寻宝

编程的各个环节中,我最喜欢的恐怕是调试,尤其是调试不熟悉的代码,比如逆向工程。从某些方面来说,调试就是侦探的工作,慢慢收集线索,整理思绪,利用推理和想象力找到真相。我很享受收集情报,然后逐渐从无序变成有序的过程。 而音乐搜索则对我一直是一大难题,想起一段熟悉的旋律,或者听到陌生而优美的曲子,我总是很急迫的想知道曲子是什么,找到完整的曲子,或者乐谱。但是音乐搜索恰恰又很困难,有歌词还稍微好一点,没有歌词有主旋律也可以试试哼唱检索。但是一些多声部,或者复杂一些的曲子就没办法了。随着时间推移,有时连旋律都忘了,只记得“有那么一段优美的旋律,而我不知道它叫什么”,如鲠在喉。 前阵子同事跟我提到Google App的音乐搜索功能,虽然之前也知道这个功能,但其实都是偶然触发,并没有想搜音乐。后来去麦当劳时,觉得BGM挺好听,就用Google App搜了一下,虽然由于周围环境噪音的原因总是不能捕捉到声音,不过最后我像傻子一样把手机高举过头顶,还是一次就找到了结果:  Lianne La Havas - Lost & Found 话说到这,就刚刚我又想起另一个麦当劳放的曲子,由于有歌词,没花多久就找到了: Alex Winston - Sister Wife 前几天别人发我一个Youtube视频,我对BGM很感兴趣,也是很容易就搜到了:Dr Dre - The Next Episode。跟她提起这个音乐时,我猛然想起自己的一个“有那么一段优美的旋律,而我不知道它叫什么”的回忆。然而我已经完全不记得曲子的旋律,以及在哪里听到这个曲子了。当然一旦听到曲子我肯定能发应过来。我总觉得人的记忆是单向hash,比如四句的唐诗,给出第二句背第三句就很容易,反过来就难很多。 决定试一下再次挑战,因为我觉得如果能再次找到这个音乐,Google App八成能搜出来名字。 一开始发散思维,回想是哪里听到的。这是最难的一步。冷静了一会儿想到那是一个找不同的游戏。于是第一反应是去Kongregate上找,搜到的找不同游戏只有三个(别的都不太像),为了找到BGM也只能全都通关一遍。好在游戏都不太长,并且游戏也不错。顺便也搜了一下游戏的BGM,很有趣。不过不幸的是那段音乐不在这几个游戏中。 说到这种枚举的事情我也不是第一次做了。小时候玩的FC游戏Moon Crystal...

NetHack 网页移植

最近在试图把NetHack移植到网页上,名曰 BrowserHack 。目前功能上基本完成了,还剩下界面调整和修复bug。 NetHack我很早就有耳闻,简单尝试一下不太喜欢它的字符界面。其实我小时候很喜欢玩SuperZZT,现在也还行,不过比较来看SuperZZT还是象形,而NetHack的字符界面就是会意了,还是蛮需要想像力的。 NetHack自然也有各种图形界面移植。以前也是没有深入尝试过。这次移植正好也研究了一番,没想到很快就入迷了,令我之前玩过的RPG游戏顿时黯然失色。 这游戏有两个特点,其一是系统和操作非常复杂,各种奇怪的命令,让我不禁想起了文字冒险类游戏。不过配合地图和帮助,这不是问题。里面物体和各种交互也非常复杂,武器放水里会生锈,地面上各种暗门陷阱,怪物的AI,无不体现出设计者的用心。另一个特点是,按Wiki的说法是这个游戏最难在于初期,这在现代游戏里也是不多见,这可能让我一开始有点望而却步,但是熟悉了几本操作以后,每次重玩都能很快上手进入状态,开始刺激的冒险。专门有一片文章讲“为什么我死了又死还是死?”,按现代游戏的玩法,一上来就横冲直撞,很快就死了。如果考虑现实生活中的探险,每一步前进必定是小心翼翼。 反观现代游戏,显示技术不断提高,似乎大多数游戏都把精力放到显示效果去了。虽然显示技术能极大提高游戏吸引力,NetHack换了几个主题我也是非常兴奋,但是玩家不是傻子,游戏本质如果弱智还是没法玩。此外,现在游戏的难度与老游戏也是没有可比性。大多数游戏难度都是循序渐进的,各种教学关卡。当然这是改进了,可是很多游戏设置了各种弱智的成就,欺骗大脑的奖励系统,感觉是把玩家训练成傀儡。 NetHack也有各种不错的移植,比如Steam上的Vulture for NetHack。有如此强大的游戏核心,再辅以美观的画面和易用的操作,真是绝了!

Studying Metal Slug's Engine

There's a Debug Menu in many titles from the Metal Slug series. Today I played around with that debug menu in Metal Slug X, especially I turned on 'body rect' and 'attack rect', which revealed how the game works. Now not only did I have tons of hours of fun, I also studied a lot from this amazing game! Of course the following are only my observations, or my best guess on how they have been implemented the game. Although I think my interpretation should work, but it's definitely not the only way, and it's quite possible that the developers have achieved the same effect with another (maybe better) method. First Impression At the first glance, the debug drawing is far cleaner than I had expected, it seems that it's not tiled based physics at all. But note the thin shadowed area below the line, which may imply that it's still using tiled based calculation somehow. Edges The ground is described as line segments, from the way the ...

路径环境变量中的陷阱 | Traps in path related environment variables

最近需要在没有root的机器上配一个自己的编译环境,于是需要改一些环境变量,比如 CFLAGS="-I#/include" LDFLAGS="-L#/lib" PATH="#/bin" LD_LIBRARY_PATH="#/lib" LIBRARY_PATH="#/lib" MANPATH="#/man" C_INCLUDE_PATH="#/include" CPLUS_INCLUDE_PATH="#/include" PKG_CONFIG_PATH="#/lib/pkgconfig" 当然可能还需要其他的。 如果就按这么写明显有问题,比如PATH原先可能不是空的,所以应该写成PATH="#/bin:$PATH",其他变量也类似。但是这样会有个更严重的问题,困扰了我一天。 问题出在C_INCLUDE_PATH,一般这个变量都是空的,所以按上面的方法添加自定义路径后变成了"#/include:",而这个末尾的":"会被理解为末尾有个当前目录,即'.',开头的':'以及中间的'::'会有同样情况。 另一方面,在使用automake编译的程序中,经常会出现-I.的编译参数,而且通常出现在最开始以保证当前目录是第一个被搜寻的路径。但是如果'.'出现了C_INCLUDE_PATH中,gcc会认为它是系统标准路径,于是命令行中的-I.会被忽略掉。这样搜索路径的顺序就改变了,就会出问题。 我是在编译binutils时发现的问题,很多目录里都有config.h,于是搜索路径的顺序很重要。 解决方法当然也很简单,就是麻烦一些,即判断一下原来的路径是否为空,避免添加多余的分隔符':'。 Recently I need to set up a development environment without root privilege, therefore I need to tweak several environment variables, for example:...

杂记 | Misc Notes

1. Firefox 全屏时显示地址栏和标签栏,设置browser.fullscreen.autohide=false 2. 禁用一个upstart的服务: echo "manual" >> xxx.conf,natty的upstart版本支持了override文件,于是可以 echo "manual" >> xxx.override 3. bootchart小工具可以分析开机时各程序启动,资源占用等情况,另有pybootchartgui可以将结果转换成图片查看 4. colortest 用于测试终端对颜色支持情况 5. synapse 一个 gnome-do 替代品,不依赖mono,重启compiz也不会崩溃 6. vimperator 最近又用了一下,比以往好了很多,装上以后多了各种快捷键,同时也不影响原来的界面。对gmail和google reader有冲突,之需要按一下ctrl+z 7. solarized 一个很不错的颜色主题,可以用于vim mutt terminal等等,很不错。也有对gnome-teriminal的移植,但是我这里显示效果不是很好 8. Terminus 一个很不错的终端字体,适用于小字号 1. To show the location bar and tab bar when Firefox is in fullscreen mode, set browser.fullscreen.autohide=false 2. To disable an upstart service: echo "manual" >> xxx.conf. Staring from Natty, upstart has supported the override files, so we may use: echo "manual" >> xxx.override 3. bootchart is a small tool to visualize the performance (of programs, resources) in the boot process, and pybootchartgui is availabl...

X11 鼠标主题中的诡异名字 | Weird names in X11 cursor themes.

经常换鼠标主题,经常好奇的看看里面内容,然后经常发现里面诡异的名字,比如这个:'00008160000006810000408080010102' 一直找不到这种名字的命名规范,最近要做一个主题转换脚本,于是仔细搜了一下。在 http://fedoraproject.org/wiki/Artwork/EchoCursors/NamingSpec 找到了结果。里面之说说这些是hash,也没说是个怎样的历史缘由。 I used to change mouse cursor theme, and often I would like to peek at the contents in the packages. Well I always see weird names such as '00008160000006810000408080010102'. I've got no idea about this kind of names. Recently as I'm making a cursor theme converter, I googled for a while, then found something useful at: http://fedoraproject.org/wiki/Artwork/EchoCursors/NamingSpec It says these names are hashes, but the reasons are not mentioned.

[转] That mysterious J

// 原文链接: http://blogs.msdn.com/b/oldnewthing/archive/2006/05/23/604741.aspx // 解决困扰我好久的问题 :) In e-mail from Microsoft employees, you may find a stray J like this one at the end of a message from Rico Mariani . Some of you might see it; others might not. What's the deal with the J? The J started out its life as a smiley-face. The WingDings font puts a smiley face where the letter J goes. Here, let me try: J results in J . As the message travels from machine to machine, the font formatting may get lost or mangled, resulting in the letter J appearing when a smiley face was intended. (Note that this is not the same as the smiling face incorporated into Unicode as U+263A, which looks like this: ☺. Some of you might see it; others might not.) I recall a story (possibly apocryphal) of somebody who regularly exchanged a lot of e-mail with Microsoft employees and who as a result started signing their own messages with a J, figuring this was some sort of Microsoft slang. The Microso...