Linux运维(折腾)小技巧一览

众所周知,Linux存在大量奇奇怪怪的小问题,为此将一些遇到过的小问题快速解决方案贴出来,以供快速查阅参考。

虚拟化篇

QEMU/KVM便捷地创建桥接网络

有时候,我们希望把虚拟机暴露到局域网LAN中,方便局域网内其他机器访问。然而,在Debian系统上使用QEMU/KVM虚拟化技术,配合libvirt,其默认创建的default网络是NAT模式的,不能满足以上要求。

目前网络上关于创建QEMU桥接网络的方法有很多,但通常很复杂,而且常常要求机器上有两个网卡。

问题在于,普通家用电脑上,通常很难找到两个同时连接到网络的网卡。

因此,这里推荐一种相对方便的,使用macvtap的桥接网络创建方法。

宿主机创建macvtap网络接口

在宿主机上使用以下命令创建一个macvtap网络接口:

1
nmcli connection add type macvlan dev eth0 mode bridge tap yes ifname macvtap0

其中,eth0是连接到网络,也就是虚拟机希望桥接到的网络的物理网卡接口。ifname后的macvtap0是可以任意指定的接口名称。

再执行以下命令:

1
2
nmcli connection modify macvlan-macvtap0 ipv6.method disabled
nmcli connection modify macvlan-macvtap0 ipv4.method disabled

根据前面接口名称的不同,modify后面的连接名称可能也有差异。

重新启动以上网络连接。

1
2
nmcli connection down macvlan-macvtap0
nmcli connection up macvlan-macvtap0

虚拟机连接到macvtap网络接口

打开virt-manager界面,修改虚拟机网卡NIC设置,网络类型选择Macvtap device。网络设备名称填写上面创建的接口名,例如macvtap0

保存后启动虚拟机,此时虚拟机就桥接连接到网卡所在网络中了。

宿主机和虚拟机的访问

macvtap的一大局限是,默认配置下,宿主机不能和虚拟机通过此网卡通信。即便分配到了局域网地址,宿主机访问虚拟机的局域网地址也是不通的。

为了允许宿主机也可以和虚拟机通信,一种解决方法是,额外在虚拟机上创建一个NIC,并连接到默认的NAT连接上。


基础运维篇

Systemd限制用户计算资源

在多人使用的Linux服务器上,会遇到这样的情况:某些淘气的小伙伴把服务器资源都占满了,其他人完全无法使用,能不能做点限制呢?

限制用户CPU使用

假设服务器上一共有32个逻辑CPU(线程),如果有一个用户运行的程序将32个逻辑核全部吃满,会导致其他所有用户程序,即使是一些简单的小工作,都很难正常运行。

在这种时候,若希望保障其他用户进行小工作处理的能力,可以用Systemd对占满大量资源的用户进行限制。

在Systemd中,用户进程和服务都会受到user-<UID>.slice配置文件的管理。其中,就提供了计算资源限制相关的属性。

首先来看最简单的限制方法:限制用户使用的最大CPU时间。假设服务器上有32个逻辑核,可以只允许某一用户最多使用等价24个核的CPU计算时间。这样一来,CPU就有余力处理其他用户的请求。

1
2
3
USER_UID=$(id -u <限制目标用户名>)

sudo systemctl set-property "user-${USER_UID}.slice" CPUQuota=2400%

如果有需要,甚至可以把该用户的进程全部赶到前24个逻辑核上,这样其他用户就稳定地还有8个核可用,非常划得来。

1
sudo systemctl set-property "user-${USER_UID}.slice" CPUQuota=2400% AllowedCPUs=0-23

但这种方法会导致,即使没有其他用户使用服务器,被限制的用户也最多只能使用2400%的CPU时间,没法充分利用CPU算力资源。

而理想状态下,我们其实只是希望,要长时间高负载占用CPU的用户,能在其他用户使用时,稍微让出一条路,让其他用户的小工作能正常进行。

所以有第二种方法:限制用户的进程优先级

通过设置进程调度,可以将某个用户的进程优先级拉低,这样,其他用户进程会被分配更多时间片以保证交互流畅,而长时任务在没其他人时,依然可以满负载运行。

1
sudo systemctl set-property "user-${USER_UID}.slice" CPUQuota= CPUWeight=25 IOWeight=25

Linux默认的CPUWeight是100,权重越大,得到的CPU时间就越多。在这里,IOWeight也是同理,且IO优先级对一些程序的交互体验影响更加明显。

限制内存使用

假设系统总内存128G,若希望限制所有用户内存总使用量在限定范围内,杜绝OOM,可以试着这样操作:

1
sudo systemctl set-property user.slice MemoryHigh=96G MemoryMax=112G

实战中只拿来阻止过某个程序的 OOM Bug.

限制用户GPU访问

有时,资源管理也颇为无奈,曾遇到一个情况,已经脱离团队的人,却仍然在使用组内的GPU。

这时,其他成员急着用卡,碍于身份难以开口让其停止使用。而且,更不可能直接强制删除用户数据,再怎么说都要给人家下载数据的时间,怎么办呢?

能不能悄悄地把这名用户的GPU访问权限下掉,但同时保留正常的用户登录、文件访问权限呢?

这也可以通过Systemd设备管理实现。对于需要限制的用户,创建一个文件夹/etc/systemd/system/user-<UID>.slice.d/

1
mkdir /etc/systemd/system/user-${USER_UID}.slice.d

然后创建一个文件override.conf,填入以下内容:

1
2
3
4
5
6
7
8
# /etc/systemd/system/user-1001.slice.d/override.conf

[Slice]
DevicePolicy=closed

# Interactive terminals
DeviceAllow=/dev/tty rw
DeviceAllow=char-pts rw

实际上,这种限制等级比较高,对于该用户来说,不仅GPU无法使用,系统上位于/dev下的设备,包括未挂载的硬盘、USB等都无法访问。当然,在科学计算服务器上,普通用户往往也无需访问这些设备。

施加这一设置后,对被限制的用户来说,其运行nvidia-smi只会提示找不到GPU设备。同时,还不影响其访问/home路径下的数据,可以让其自行将数据导出带走。

密码强度设置

在Debian/Ubuntu下,怎么设置系统用户密码的最低强度标准?

首先需要安装libpam-pwquality包:

1
sudo apt install libpam-pwquality

然后编辑/etc/security/pwquality.conf文件,可参考文件注释进行调整:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# Number of characters in the new password that must not be present in the
# old password.
difok = 3

# Minimum acceptable size for the new password (plus one if
# credits are not disabled which is the default). (See pam_cracklib manual.)
# Cannot be set to lower value than 6.
minlen = 12

# The maximum credit for having digits in the new password. If less than 0
# it is the minimum number of digits in the new password.
dcredit = -1

# The maximum credit for having uppercase characters in the new password.
# If less than 0 it is the minimum number of uppercase characters in the new
# password.
ucredit = -1

# The maximum credit for having lowercase characters in the new password.
# If less than 0 it is the minimum number of lowercase characters in the new
# password.
lcredit = -1

# The maximum credit for having other characters in the new password.
# If less than 0 it is the minimum number of other characters in the new
# password.
ocredit = -1

上面的配置对应于以下密码强度约束:

  • 修改密码与原密码必须有3个字符以上不同
  • 密码最小长度为12字符
  • 密码必须包含大小写字母、数字、其他字符(标点)

Debian系统列出可升级软件包所含Bug

前不久,Debian Testing更新内核版本号至6.10,导致默认软件源中的NVIDIA驱动535版本DKMS模块无法正常编译。看来,即使是风评比Ubuntu更稳定的Debian Testing,作为桌面系统也会产生严重Bug啊!

大家都知道,Debian软件包上发现的Bug,都会在Debian bug tracking system里被跟踪,但在近乎滚动更新的Debian Testing上,一次更新可能超过200个软件包,不可能一个个手动分开查询。

我们可以使用apt-listbugs工具完成这一操作。如果系统上没有,使用APT即可快速安装。

接着只需要执行以下命令,待更新的软件包中有哪些严重Bug就都知道了。

1
apt-listbugs -s critical,grave,serious list $(apt list --upgradable 2>/dev/null | awk -F/ '{print $1}' | grep -v "Listing" | tr '\n' ' ')

其中,-s参数指定了查询的Bug严重程度,默认就是上例中的critical,grave,serious,如果希望无论轻重列出所有Bug,只需要把这一串参数改成all即可。$()中的一大串是,将APT命令列出的可升级软件包列表格式化成apt-listbugs可接受的空格列表。


用户应用篇

修复SKN键盘在FN键工作异常

手上有一块SKN青龙3.0机械键盘,平时用起来倒也比较舒适,但在Linux下总是无法正常地使用F系列按键。

更具体来说,最顶上的一排F1-F12按键,总是只能触发对应的Fn功能,无论是否按下Fn,都不能正常触发F数字按钮的功能。

查看lsusb输出,发现键盘竟然被Linux系统识别成了苹果的外接键盘:

1
Bus 005 Device 004: ID 05ac:024f Apple, Inc. Aluminium Keyboard (ANSI)

然而,我没能在5分钟之内,在网络上搜索到如何让Linux纠正键盘型号的方法,只得另寻他法。

尽管暂时没有简便的切换键盘型号方法,但是,只要能让顶部的F数字按钮正常工作,取消掉默认的Fn键锁定,那是否将键盘误认为苹果键盘也无所谓。

解决这一问题的参考链接🔗:InstallingDebianOn / Apple / PageFragmentKeyboardAppleKeyboard.

先试试水

首先简单测试本方法是否有效,请在终端中输入:

1
$ echo 2 | sudo tee /sys/module/hid_apple/parameters/fnmode

这里的数字2代表Fn键的功能模式,该模式的取值可以是:

  • 0 = disabled: Disable the ‘fn’ key. Pressing ‘fn’ has no effect
  • 1 = fkeyslast: Enable the ‘fn’ key. Pressing ‘F1-F12’ keys will act as special keys. Pressing ‘fn’+‘F1-F12’ will behave like ‘F1-F12’.
  • 2 = fkeysfirst: Enable the ‘fn’ key. Pressing ‘F1-F12’ keys will behave like the real ‘F1-F12’. Pressing ‘fn’+‘F8’ will act as the special key (play/pause in this case).

这里我们希望使用2模式,也就是,默认不按Fn时按下F1-F12键即为对应的F数字功能;按下Fn后再按F数字键,则执行对应的特殊Fn键功能(如音乐播放、屏幕亮度调整等)。

执行上述命令后,试一试,F5键是否已经能正常刷新网页?

如果到此为止没有任何效果,那么说明遇到的问题和本案例不同。需要另外寻找解决方案。如果已达到目标效果,那么已经成功一半了!

持久化设置

上述方法通过直接修改内核参数调整键盘的Fn行为,但每次重启后,该修改就会丢失。怎么将这一修改持久化呢?

两种方法。第一种是设置模块的参数:

1
2
3
$ echo options hid_apple fnmode=2 | sudo tee -a /etc/modprobe.d/hid_apple.conf 
$ sudo modprobe --dry-run hid_apple
$ sudo update-initramfs -u # If the above line does not throw error.

或者直接编辑GRUB启动内核的参数,编辑/etc/default/grub,找到GRUB_CMDLINE_LINUX_DEFAULT变量定义,并在双引号里追加内容(双引号多项内容通过空格分隔):

1
hid_apple.fnmode=2

然后重新生成GRUB:

1
sudo update-grub

重启系统,应该就一切都好啦。

SSH Host Key遗忘

我,毋畏遗忘

虽然SSH Host Key在不可信网络上确实是验证SSH连接可信性的重要手段,但是,在会频繁刷新Host Key的如容器、虚拟机场景下,又显得不太方便。

然而,SSH并没有直接提供诸如“不记录本机Host Key”等功能,有一个选项StrictHostKeyChecking no,但其仍然会在Host Key不匹配时弹出大大的警告窗口。

这样的目标可以简单变通实现,只需要在 SSH Config 配置中设置 UserKnownHostsFile,将其指向黑洞即可。

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Host myserver
    Hostname 192.168.1.2
    Port 22
    User root
    IdentityFile ~/.ssh/id_rsa
    StrictHostKeyChecking no

    # Linux
    # UserKnownHostsFile /dev/null

    # Windows
    UserKnownHostsFile \\.\NUL

更方便的环境变量组织

众所周知,在Linux中给普通应用设置环境变量,一般只需要在~/.bashrc等Shell配置文件中直接写export语句即可。

不过,有时候存在下面需求:

  1. 希望给不同的命令指定同名环境变量的不同值,例如MYENV=abc cmd1MYENV=def cmd2
  2. 不希望环境变量对所有命令全局生效,只对特定命令生效
  3. .bashrc中用更加简洁的语法管理环境变量

那么,相较于原始的大量独立export语句写法,可以试试下面的写法。

假设原先的.bashrc如下:

1
2
3
export MYAPP_ENV_1=abcd
export MYAPP_ENV_2=efg
export MYAPP_ENV_3=hijk

再假设需要设置上述环境变量的命令为myapp,那么可以将上面的export语句换成下面这种写法:

1
2
3
4
5
6
7
8
9
MYAPP_ENVS=(
    MYAPP_ENV_1=abcd
    MYAPP_ENV_2=efg
    MYAPP_ENV_3=hijk
)

myapp() {
    env "${MYAPP_ENVS[@]}" myapp "$@"
}

这样设置的好处包括:

  1. 在Shell中调用myapp命令与常规调用等价,不影响参数传递,也不影响argv等参数内容
  2. MYAPP_ENVS中定义的变量只影响myapp一个命令,对其他命令全无影响
  3. 增删环境变量只需直接按行修改,可按行注释掉不想要的环境变量,维护方便

若定义了多个环境变量数组,只需要在env命令后,程序命令之前添加即可:

1
2
3
4
5
6
7
8
ANOTHER_MYAPP_ENVS=(
    MYAPP_ENV_4=hijk
    MYAPP_ENV_5=xyz
)

myapp() {
    env "${MYAPP_ENVS[@]}" "${ANOTHER_MYAPP_ENVS[@]}" myapp "$@"
}

Claude Code 快速安装使用

达里奥,你模什么时候送啊?

注意:npm安装方式未来可能有变动,请先行查阅官方文档

首先执行 npm install -g @anthropic-ai/claude-code

安装完成就要开始配置。如果使用A社官方模型API,记得设置好网络。

当然,我用的是Deepseek,其他第三方模型也可以参考下面的配置方法。

新建一个~/.claude.json文件,按需填写:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
{
  "env": {
    "ANTHROPIC_BASE_URL": "https://api.deepseek.com/anthropic",
    "ANTHROPIC_AUTH_TOKEN": "sk-12345678",
    "ANTHROPIC_MODEL": "deepseek-v4-pro[1m]",
    "ANTHROPIC_DEFAULT_OPUS_MODEL": "deepseek-v4-pro[1m]",
    "ANTHROPIC_DEFAULT_SONNET_MODEL": "deepseek-v4-pro[1m]",
    "ANTHROPIC_DEFAULT_HAIKU_MODEL": "deepseek-v4-flash",
    "CLAUDE_CODE_SUBAGENT_MODEL": "deepseek-v4-pro[1m]",
    "CLAUDE_CODE_EFFORT_LEVEL": "max",
    "DISABLE_AUTOUPDATER": "1",
    "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
    "ENABLE_TOOL_SEARCH": "1",
    "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1",
    "IS_SANDBOX": "1"
  },
  // 这一行很重要,否则会在启动时连接A社API并提示地区不支持
  "hasCompletedOnboarding": true
}

桌面应用篇

Gnome应用列表按字母表排序

至今,我依然没有弄明白,GNOME的应用列表里,图标究竟遵循了怎样的排序规律。

或许翻阅源代码可以弄明白,但或许也不需要了,因为我更习惯按应用名称字母表排序。想要设置按字母表排序,只需要在命令行中执行以下命令即可:

1
gsettings set org.gnome.shell app-picker-layout "[]"

修复桌面系统中文显示异常

如果安装了英文的系统,又在之后切换为中文,有时候会发现中文渲染不太正常,比方说突然有个字体只有一半宽度,或者笔画字形怪怪的。

这是因为,系统中安装的CJK字体 Noto Sans CJK,在无特殊配置时,日文变体JP优先级高于中文的SC(字母表排序),导致部分汉字按日文字形渲染。这就是我们所看到的异常由来。

解决办法自然就围绕,怎么告诉系统优先加载SC字体进行。这里的方法参考了 ArchLinux Wiki

/etc/fonts/conf.d/(系统全局生效)或~/.fonts.conf(仅用户生效)下创建一个新文件64-language-selector-prefer.conf,并填入:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
    <alias>
        <family>sans-serif</family>
        <prefer>
            <family>Noto Sans CJK SC</family>
            <family>Noto Sans CJK TC</family>
            <family>Noto Sans CJK JP</family>
        </prefer>
    </alias>
    <alias>
        <family>serif</family>
        <prefer>
            <family>Noto Serif CJK SC</family>
            <family>Noto Serif CJK TC</family>
            <family>Noto Serif CJK JP</family>
        </prefer>
    </alias>
    <alias>
        <family>monospace</family>
        <prefer>
            <family>Noto Sans Mono CJK SC</family>
            <family>Noto Sans Mono CJK TC</family>
            <family>Noto Sans Mono CJK JP</family>
        </prefer>
    </alias>
</fontconfig>

接着执行:

1
fc-cache -fv

并验证:

1
fc-match -s | grep 'Noto Sans CJK'

重启电脑,解决问题。

中文输入法之选:雾凇拼音

Linux中文输入法中,libpinyin 虽然开箱即用,但在我的GNOME下存在卡顿、响应不灵敏、不跟手、词库简陋等缺点,充其量就是一个能用的状态。

过去Linux还有搜狗输入法可用,就流畅度和输入体验来说是T1水平,可惜依赖的古老Fcitx已经很难在最新Wayland和GNOME下使用。

Rime输入法虽然提供了极其丰富的扩展空间,但是配置非常复杂,并不是每次都有一下午时间查资料调配置。

幸好,有人帮我们踩过了坑,我们不需要自己手动调整,只需要使用:iDvel/rime-ice

系统安装Rime

以GNOME为例,默认使用的是IBus输入框架,在比较新版本的Debian或者Ubuntu上,使用apt安装ibus-rime包即可。

如果系统源中提供的librime版本号小于1.85,那么需要想办法自行升级librime,具体参见:Linux 用户须知:如需使用本库配置,推荐使用以下 Rime 安装方式 #840

安装rime-ice

项目主页提供了非常多种安装方法,但我们这里回归本真,不用什么复杂的方法,只需要直接在Github下载rime-ice仓库的源码包,然后解压到:

  • IBus 需解压到 $HOME/.config/ibus/rime/
  • Fcitx5 需解压到 $HOME/.local/share/fcitx5/rime/

如果先前有其他配置文件,建议先备份后清空上述文件夹,再安装新的配置文件。

稍作修改

进入上面的安装目录中,打开default.yaml,根据里面的注释稍作修改。

可以删除掉其他不需要的输入方案,可以修改候选词个数,还可以修改Shift键的行为等。

花里胡哨1:拆字输入

拆字输入就是将一个不知道怎么读的汉字,通过将其拆分成几个简单易读的偏旁进行依次输入。

例如,如果不知道这个字怎么读,可以将其拆解为三个进行输入。

在本方案中,触发拆字的引导前缀是uU,也就是输入uUshuishuishui即可。当然,引导前缀可以自定义。

花里胡哨2:以词定字

设想以下场景:

  • “您贵姓?”
  • “我姓 Ji。”
  • “哪个 Ji 呀?”
  • " 暨南大学。"

百度百科:暨姓是中国罕见姓氏,属汉族古老姓氏,起源于商代彭祖后代受封于暨地

许多专有名词、名字中,部分汉字不常出现在候选字的第一屏。此时,与其不断翻页寻找目标字,不如直接打出该字组词,更容易快速定位,上屏后删掉多余的字即可。

而以词定字就提供了快速根据词语进行定位的能力,只需要打出对应的二字词,按下[或者],即可确定是输入词组的前一个字还是后一个字,省去上屏后删除的烦恼。

例如,上面的案例中,可以输入jinan,然后按下[即可把"暨"字快速上屏。(前提是没有匹配到 济南

花里胡哨3:候选项水平/垂直分布

在IBus下,修改候选项水平或垂直分布,需要修改$HOME/.config/ibus/rime/build/ibus_rime.yaml

1
2
style:
  horizontal: true

花里胡哨4:双拼兼容性问题

笔者习惯使用小鹤双拼输入文字,默认方案是针对全拼的,在双拼上还需要一定定制。参阅:常见问题 #133

拆字输入

对双拼用户来说,在输入例如这样的字时,可能会更希望以uUuvuvuv输入。此时需要修改一下配置文件。可以直接修改radical_pinyin.schema.yaml,也可以创建一个patch文件radical_pinyin.custom.yaml,修改以下值:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
patch:
  # 修改为双拼的拼写派生规则,因为不在同一个文件了,前面要加上文件名
  speller/algebra:
    # __include: radical_pinyin.schema.yaml:/algebra_pinyin         # 全拼
    # __include: radical_pinyin.schema.yaml:/algebra_double_pinyin  # 自然码双拼
    __include: radical_pinyin.schema.yaml:/algebra_flypy            # 小鹤双拼
    # __include: radical_pinyin.schema.yaml:/algebra_mspy           # 微软双拼
    # __include: radical_pinyin.schema.yaml:/algebra_sogou          # 搜狗双拼
    # __include: radical_pinyin.schema.yaml:/algebra_abc            # 智能ABC双拼
    # __include: radical_pinyin.schema.yaml:/algebra_ziguang        # 紫光双拼
自定义短语库

双拼短语库文件不同于全拼的短语库文件custom_phrase.txt,其名称为custom_phrase_double.txt,需要自行创建并填入内容。

当然,也可以懒得弄。

融合拼音输入

虽然我也没弄懂融合拼音是啥,起什么作用。但总之是要修改melt_eng.schema.yaml 文件,或创建一个melt_eng.custom.yaml文件,修改或填入:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
patch:
  # 修改为双拼的拼写派生规则,因为不在同一个文件了,前面要加上文件名
  speller/algebra:
    # __include: melt_eng.schema.yaml:/algebra_rime_ice       # 全拼
    # __include: melt_eng.schema.yaml:/algebra_double_pinyin  # 自然码双拼
    __include: melt_eng.schema.yaml:/algebra_flypy            # 小鹤双拼
    # __include: melt_eng.schema.yaml:/algebra_mspy           # 微软双拼
    # __include: melt_eng.schema.yaml:/algebra_sogou          # 搜狗双拼
    # __include: melt_eng.schema.yaml:/algebra_abc            # 智能ABC双拼
    # __include: melt_eng.schema.yaml:/algebra_ziguang        # 紫光双拼
输入显示双拼原始输入或全拼拼音

这个选项控制的是,在例如输入uhhd双拼编码时,屏幕上显示的是原始输入uhhd,还是显示转译后的shanghai。这一选项同步影响Shift + Enter后上屏的输入结果。

默认情况下,显示的是转译后的全拼编码shanghai。如果希望显示原始输入,需要创建一个 double_pinyin_flypy.custom.yaml文件:

1
2
3
patch:
  # (按需选择)清空 preedit_format 中的内容,输入时显示双拼编码
  translator/preedit_format: []

常见问题

参阅:常见问题 #133

Licensed under CC BY-NC-SA 4.0
最后更新于 2026年7月6日星期一