标签归档:linux

m1 MacBook 安装 asahi linux 磁盘调整失败解决

尝试在 MacBook Air m1 安装 asahi linux ,在磁盘分区过程遭遇报错,具体过程没有留下来,是类似这样的报错:

error: doc-id tree: record exists for doc-id 64, file-id 9665861 but no inode references this doc-id

大致解决是要进恢复模式,之后使用急救程序尝试修复。

尝试后发现还是报错,后来在 asahi linux 的 github 找到一个类似问题,使用下列方法解决:

I had a similar issue, where /dev/disk3s5 had warnings that wouldn’t go away, and I solved it as follows:

Boot into recovery and open a terminal
`diskutil unmountdisk /dev/disk3`
`fsck_apfs /dev/disk3` (and hit y in response to the various prompts)

I believe unmounting was the important part.

之后磁盘分区就不报错了。

参考文献: https://github.com/AsahiLinux/asahi-installer/issues/88#issuecomment-1095019173

Linux 禁用 SWAP

在服务器和容器平台建议关闭 SWAP,避免内存交换影响服务器性能,甚至引发数据丢失。

一、不重启电脑,禁用启用swap,立刻生效

# 禁用命令

sudo swapoff -a

# 启用命令

sudo swapon -a

# 查看交换分区的状态
sudo free -m

二、重新启动电脑,永久禁用Swap

把根目录文件系统设为可读写

sudo mount -n -o remount,rw /

用vi修改/etc/fstab文件,在swap分区这行前加 # 禁用掉,保存退出

vi /etc/fstab

i      #进入insert 插入模式

:wq   #保存退出
mount -a
# 使 fstab 文件生效

重新启动电脑,使用free -m查看分区状态

reboot

sudo free -m

参考文献

pkg-config 自动补全 C 编译库依赖

pkg-config 是一个在源代码编译时查询已安装的库的使用接口的计算机工具软件。

工作原理

其工作原理如下: 当安装一个库时(例如从RPMdeb或其他二进制包管理系统),会包括一个后缀名为 pc 的文件,它会放入某个文件夹下(依赖于你的系统设置)。 例如,在 Linux 为该软件的库文件所在文件夹 lib 之下的子文件夹 pkgconfig 。 并把该子文件夹加入 pkg-config 的环境变量 PKG_CONFIG_PATH 作为搜索路径,例如在 bash 配置文件中加入一行:

$ export PKG_CONFIG_PATH=/usr/local/`库的名字`/lib/pkgconfig:$PKG_CONFIG_PATH

在这个.pc文件里包含有数个条目。这些条目通常包含用于其他使用这个库的程序编译时需要的库设置,以及头文件的位置,版本信息和一个简介。

这是一个用于libpng的.pc文件的样例:

prefix=/usr/local  
 exec_prefix=${prefix}  
 libdir=${exec_prefix}/lib  
 includedir=${exec_prefix}/include  
    
 Name: libpng12  
 Description: Loads and saves PNG files  
 Version: 1.2.8  
 Libs: -L${libdir} -lpng12 -lz  
 Cflags: -I${includedir}/libpng12

这个文件告诉我们这些库可以在/usr/local/lib找到,头文件可以在/usr/local/include里找到,库的名字是libpng12并且版本号是1.2.8。它也提供了用于编译依赖于libpng的源代码时需要的链接器参数。

这儿是一个编译时使用pkg-config的样例:

gcc -o test test.c $(pkg-config --libs --cflags libpng)

pkg-config 同其他命令一样,有很多选项,不过我们一般只会用到 --libs--cflags 选项,分别用于搜索指定头文件和库文件。

在 Makefile 中则是这样来用:

...
DEPENDENCIES=libcpg libcmap libquorum libqb glib-2.0 fuse sqlite3 librrd

CFLAGS += -I.
CFLAGS += $(shell pkg-config --cflags ${DEPENDENCIES})

LDFLAGS += $(shell pkg-config --libs ${DEPENDENCIES})

.c.o:
        $(CC) $(CFLAGS) -c -o $@ $< -MMD -MT $@ -MF $@.d
...

参考文献

在 linux 中解析 lib 文件

解析 lib 文件可以获取一些二进制库的版本历史信息,例如解析 /usr/lib64/libc.so.6 即可解析到 glibc 的版本历史。

在Linux中,有许多工具可以用来解析库文件( .lib 文件)。 可以使用工具如 nmobjdumpreadelf 来查看库文件的符号表,包含在库文件中的对象文件的信息,以及库文件的其他信息。

下面是一些常用的命令:

`nm`: 这个命令可以显示符号表信息。你可以运行 `nm <library-name>.lib` 来查看库文件的符号表信息。

`objdump`: 这个命令可以显示包含在库文件中的对象文件的信息。你可以运行 `objdump -p <library-name>.lib` 来查看库文件的信息。

`readelf`: 这个命令可以显示库文件的其他信息,包括符号表信息和对象文件信息。你可以运行 `readelf -a <library-name>.lib` 来查看库文件的信息。

这些命令可以帮助你解析库文件并查看其中包含的信息。

内容参考自 ChatGPT

Linux (Debian 系) 安装官方微信 (Electron,非 wine 版)

使用 Linux 作为唯一主力系统的阻力之一,就来自于微信。

微信大概是目前大多数人都无法离开的软件,而在 Linux 下安装微信在此前是比较复杂的,这对于使用 Linux 工作生活存在一些障碍。

最近才发现微信有推出基于 Electron.js 的一款桌面程序,不需要依赖 Wine 那复杂和冗余的依赖,只需要装一个稍微“大”一点的 deb 包就可以。

而且因为是基于 deb,理论来说 debian 系操作系统,如 Ubuntu、Kali 等都是可以直接安装的。

软件可以从优麒麟官网的软件下载页面找到:

https://www.ubuntukylin.com/applications/106-cn.html

在这个页面直接下载就可以,不要在其他陌生的地方下载。

下载下来之后看一下,一个平平无奇的 deb 软件包, debian 系操作系统直接 dpkg -i xx.deb 安装即可,基本不会出现依赖问题。

实测在 kali 下正常使用。安装完成,就可以在软件清单找到微信了,直接打开即可,扫码登录即可使用。

不要抱有太高期待,现阶段只是能用。不过这对于大部分会考虑使用 linux 做主系统的人们来说,应该是够用了。

实际上在优麒麟官网还可以找到其他一些常用软件,可以看到 QQ 和微信还有提供一种 crosscover 版,也就是基于 wine 的,在 linux 运行 windows 的方式运行,这种方式也许功能会多一些,但依赖实在太多,配置复杂,用起来很繁琐,不推荐使用。

总结一下,当前国产操作系统发展越来越好,虽然与 windows、macos 的差距还很大,而且对于底层技术的掌控也比较有限,但这是一个很好的趋势,提升自己在 linux 下的工作能力,对于技术人员或是工作离不开计算机的人们来说,长期来看很有益处。

另外,在 linux 下几乎可实现所有想要的功能,相对 windows 或 macos 的直接使用,可以在这一过程中获得更多成就感。

参考文献

Juice FS 初探 | 一种为 VPS 提供无限磁盘空间的解决方案

JuiceFS 是一款面向云原生设计的高性能分布式文件系统,在 Apache 2.0 开源协议下发布。提供完备的 POSIX 兼容性,可将几乎所有对象存储接入本地作为海量本地磁盘使用,亦可同时在跨平台、跨地区的不同主机上挂载读写。

使用 JunicsFS 将云厂商的 S3 对象存储挂载到本地,就得到一个几乎无限容量的 VPS 空间了。目前 Juice 支持大部份主流厂商提供的 s3 服务,具体请查阅官方文档。

本文以 腾讯云 COS + 腾讯云轻量服务器,演示一下基本使用。

挂载 COS 到本地

使用以下命令即可创建一个基于 COS 的文件系统,下面演示基于 sqlite 和 redis 的创建、挂载、卸载命令。

# Jfs With Redis
juicefs format \
    --storage cos \
    --bucket jfs-redis-******** \
    --access-key ******** \
    --secret-key ******** \
    "redis://127.0.0.1:6379/1" \
    jfs-redis
# 挂载
juicefs mount -d "redis://127.0.0.1:6379/1" /mnt/jfs-redis/
# 卸载
juicefs umount /mnt/jfs-redis/

# Jfs With sqlite
juicefs format \
    --storage cos \
    --bucket jfs-******** \
    --access-key ******** \
    --secret-key ******** \
    "sqlite3:///opt/jfs/jfs.db" \
    jfs
# 挂载
juicefs mount -d "sqlite3:///opt/jfs/jfs.db" /mnt/jfs/
# 卸载
juicefs umount /mnt/jfs/

自动挂载

具体使用时,可以配置一下自动挂载,方法如下。

首先创建一个从 /sbin/mount.juicefsjuicefs 可执行文件的软链接,操作系统解析 fstab 时会调用 /sbin/mount.juicefs 命令。

$ which juicefs
/usr/local/bin/juicefs
$ ln -s /usr/local/bin/juicefs /sbin/mount.juicefs

新增以下内容到 /etc/fstab 使得开机自动挂载,这里以上文 sqlite 为例:

sqlite3:///opt/jfs/jfs.db    /mnt/jfs       juicefs     _netdev,max-uploads=50,writeback,cache-size=204800     0  0

使用 mount -a 使配置生效

限制容量和文件数

没有限制的行为可想而知,JuicsFS 的默认限制较高,可以手动限制一下文件系统的容量和文件数量。

# 限制文件系统容量 (GiB)
$ juicefs config "sqlite3:///opt/jfs/jfs.db" --capacity 102400
# 限制文件数量 (inode 数)
$ juicefs config "sqlite3:///opt/jfs/jfs.db" --inodes 100000

限制容量举例,可以看到设定前后可以看到挂载点容量的变化:

# 示例
$ df -h | grep jfs
Filesystem      Size  Used Avail Use% Mounted on
JuiceFS:jfs     1.0P  8.0K  1.0P   1% /mnt/jfs

# 设定容量上限为 128 GiB
$ juicefs config "sqlite3:///opt/jfs/jfs.db" --capacity 128
2022/11/20 21:07:08.832094 juicefs[2253158] 
<INFO>: Meta address: sqlite3:///opt/jfs/jfs.db [interface.go:402]
  capacity: 0 GiB -> 128 GiB

# 再次查看发现大小为 128GiB
$ df -h | grep jfs
JuiceFS:jfs     128G  8.0K  128G   1% /mnt/jfs

限制文件 inodes 数量举例,可以看到设定前后可以看到挂载点容量的变化:

# 示例
$ df -i
Filesystem       Inodes  IUsed    IFree IUse% Mounted on
/dev/vda2       3901440 367127  3534313   10% /
JuiceFS:jfs    10485762      2 10485760    1% /mnt/jfs

$ juicefs config "sqlite3:///opt/jfs/jfs.db" --inodes 3901440
2022/11/20 21:13:30.977616 juicefs[2255902] 
<INFO>: Meta address: sqlite3:///opt/jfs/jfs.db [interface.go:402]
    inodes: 0 -> 3901440
$ df -i
Filesystem       Inodes  IUsed    IFree IUse% Mounted on
/dev/vda2       3901440 367128  3534312   10% /
JuiceFS:jfs     3901440      2  3901438    1% /mnt/jfs

性能测试

文件系统怎么能没有性能测试呢,下面分别使用 dd 和自带 bench 演示性能。

dd 简单读写测试

# 本地文件系统 io 性能
$ sync; dd if=/dev/zero of=/tmp/tempfile-12138 bs=1M count=1024; sync
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 5.563 s, 193 MB/s

# JuicfFS sqlite 元数据驱动性能
$ sync; dd if=/dev/zero of=/mnt/jfs/tmpfile bs=1M count=1024; sync
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 6.97672 s, 154 MB/s

# JuicfFS redis 元数据驱动性能
$ sync; dd if=/dev/zero of=/mnt/jfs-redis/tmpfile-12138 bs=1M count=1024; sync
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 5.59675 s, 192 MB/s

juicefs bench 测试

本地文件系统成绩

# juicefs bench -p 4 /tmp/
  Write big blocks count: 4096 / 4096 [==============================================================]  done
   Read big blocks count: 4096 / 4096 [==============================================================]  done
Write small blocks count: 400 / 400 [==============================================================]  done
 Read small blocks count: 400 / 400 [==============================================================]  done
  Stat small files count: 400 / 400 [==============================================================]  done
Benchmark finished!
BlockSize: 1 MiB, BigFileSize: 1024 MiB, SmallFileSize: 128 KiB, SmallFileCount: 100, NumThreads: 4
+------------------+------------------+--------------+
|       ITEM       |       VALUE      |     COST     |
+------------------+------------------+--------------+
|   Write big file |     153.98 MiB/s | 26.60 s/file |
|    Read big file |     148.60 MiB/s | 27.56 s/file |
| Write small file |   2064.9 files/s | 1.94 ms/file |
|  Read small file |   3150.8 files/s | 1.27 ms/file |
|        Stat file | 111847.4 files/s | 0.04 ms/file |
+------------------+------------------+--------------+

juicefs + sqlite 成绩

$ juicefs bench -p 4 /mnt/jfs
  Write big blocks count: 4096 / 4096 [==============================================================]  done
   Read big blocks count: 4096 / 4096 [==============================================================]  done
Write small blocks count: 400 / 400 [==============================================================]  done
 Read small blocks count: 400 / 400 [==============================================================]  done
  Stat small files count: 400 / 400 [==============================================================]  done
Benchmark finished!
BlockSize: 1 MiB, BigFileSize: 1024 MiB, SmallFileSize: 128 KiB, SmallFileCount: 100, NumThreads: 4
Time used: 72.0 s, CPU: 35.5%, Memory: 704.1 MiB
+------------------+------------------+---------------+
|       ITEM       |       VALUE      |      COST     |
+------------------+------------------+---------------+
|   Write big file |     148.25 MiB/s |  27.63 s/file |
|    Read big file |     144.29 MiB/s |  28.39 s/file |
| Write small file |     40.5 files/s | 98.83 ms/file |
|  Read small file |    715.9 files/s |  5.59 ms/file |
|        Stat file |   3759.0 files/s |  1.06 ms/file |
|   FUSE operation | 71735 operations |    2.99 ms/op |
|      Update meta |  4773 operations |   27.18 ms/op |
|       Put object |  1424 operations |  443.33 ms/op |
|       Get object |     0 operations |    0.00 ms/op |
|    Delete object |     0 operations |    0.00 ms/op |
| Write into cache |  1424 operations |  281.82 ms/op |
|  Read from cache |  1428 operations |  556.68 ms/op |
+------------------+------------------+---------------+

juicefs + redis 成绩

试着跑了一次,结果跑崩了,想玩的自己跑一跑吧。

由于 redis 是内存数据库,跑这种没有上限的测试一定要谨慎。在实际使用中,也要根据自己的需要选择,否则机器很容易 gg。

垃圾清理

juicefs 默认有回收站机制,删除文件默认在回收站保留一天。

可以去挂载目录下执行这条命令彻底删除:

$ find .trash -name '*.tmp' | xargs rm -f

总结

本文介绍了 JuiceFS 的基本用法,为“大盘鸡”需求提供一种新的思路,展示了使用对象存储挂载到机器作为文件系统的基本效果。

目前看来是解决系统盘过小问题的好方案,但具体是不是采纳这种方案,等我明天看看账单再做决定。

第二天看了下账单,跑了大概 10 轮测试,账单 0.02¥ ,初步看还能接受:

至于元数据引擎的选择,在单节点服务器的需求上我还是偏向 sqlite 或 mysql 集群的方案,redis 虽然性能强劲,但实在有点吃不消。

最后,这一定是一个很棒的项目,在对接 docker、k8s 之类的容器设施非常方便,提供了插件,可以像操作默认存储卷一样使用,还可以直接使用挂载在本地的路径,总之,在一些方面 JuiceFS 做的已经很好了,下面就是等待时间的检验了。

参考文献

macOS 使用 arping 扫描 ip 冲突

最近工作网络不稳定,多个常用 IP 出现冲突,就连 DHCP 获取到的 IP 也会立刻冲突,原因等待相关人员去解决,今天简单记录 macOS 下 IP 冲突检测的原因。

一般检查 IP 是否被占用的方法是使用 ping

$ ping 119.29.29.29
PING 119.29.29.29 (119.29.29.29): 56 data bytes
64 bytes from 119.29.29.29: icmp_seq=0 ttl=50 time=14.477 ms
64 bytes from 119.29.29.29: icmp_seq=1 ttl=50 time=15.033 ms
64 bytes from 119.29.29.29: icmp_seq=2 ttl=50 time=15.330 ms
^C
--- 119.29.29.29 ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 14.477/14.947/15.330/0.354 ms

但是这种方法看不到ip冲突,如果出现多个机器占用同个 IP,可以利用arp协议查一下 MAC 地址:

# macOS 下这样安装
$ brew install arping
# 使用 alias 定义快速使用别名
$ alias arping='sudo /opt/homebrew/opt/arping/sbin/arping'

另外发现 m1 下的 brew 安装 arping 默认不会进入 PATH ,因此在这里手动设定一个别名,方便使用。

之后扫描,如果出现 IP 冲突,可以看到有多个 MAC 地址回应:

$ sudo /opt/homebrew/opt/arping/sbin/arping 192.168.5.79
Password:
ARPING 192.168.5.79
60 bytes from 6a:f2:77:bd:bf:16 (192.168.5.79): index=0 time=463.000 usec
60 bytes from 6a:29:af:20:80:7f (192.168.5.79): index=1 time=1.002 msec
60 bytes from 6a:f2:77:bd:bf:16 (192.168.5.79): index=2 time=582.000 usec
60 bytes from 6a:29:af:20:80:7f (192.168.5.79): index=3 time=1.182 msec
60 bytes from 6a:f2:77:bd:bf:16 (192.168.5.79): index=4 time=658.000 usec
60 bytes from 6a:29:af:20:80:7f (192.168.5.79): index=5 time=1.117 msec
60 bytes from 6a:f2:77:bd:bf:16 (192.168.5.79): index=6 time=772.000 usec
60 bytes from 6a:29:af:20:80:7f (192.168.5.79): index=7 time=1.096 msec
^C
--- 192.168.5.79 statistics ---
4 packets transmitted, 8 packets received,   0% unanswered (4 extra)
rtt min/avg/max/std-dev = 0.463/0.859/1.182/0.257 ms

还可以通过 arping 来查看是否 IP 被占用,有些机器会禁止 PING 检测,使用 arp 这类二层协议检测占用情况会更准确些。

参考文献

Linux 使用 diff 分栏对比文本差异

首先看一下帮助文档:

$ diff --help  
用法:diff [选项]... 文件列表  
逐行比较<各文件>。  

长选项的必需参数也是相应短选项的必需参数。  
     --normal                  以正常的 diff 方式输出 (默认)  
 -q, --brief                   只有在文件不同时报告  
 -s, --report-identical-files  当两个一样时仍然显示结果  
 -c, -C NUM, --context[=NUM]   同时输出 NUM 行(默认为 3 行)的复制上下文内容  
 -u, -U 数量, --unified[=数量] 输出 <数量>(默认为 3)行一致化上下文  
 -e, --ed                      以 ed script 方式输出  
 -n, --rcs                     以 RCS diff 格式输出  
 -y, --side-by-side            以两栏的格式输出  
 -W, --width=数量              每行显示最多 <数量>(默认 130)个字符  
     --left-column             当有两行相同时只显示左边栏的一行  
     --suppress-common-lines   当有两行相同时不显示  

 -p, --show-c-function         显示每个变更位于哪个 C 函数中  
 -F, --show-function-line=正则 显示匹配给定<正则>表达式的最近一行  
     --label 标签              使用给定<标签>替代文件名和时间戳  
                                 (可以重复)  

 -t, --expand-tabs             将输出中的 tab 转换成空格  
 -T, --initial-tab             每行先加上 tab 字符,使 tab 字符可以对齐  
     --tabsize=数字           TAB 格的宽度,默认为 8 个打印列宽  
     --suppress-blank-empty    在空的输出行之前去除空白或制表符  
 -l, --paginate                将输出送至 “pr” 指令来分页  

 -r, --recursive                 连同所有子目录一起比较  
     --no-dereference            不要跟随符号链接  
 -N, --new-file                  不存在的文件以空文件方式处理  
     --unidirectional-new-file   若第一文件不存在,以空文件处理  
     --ignore-file-name-case     忽略文件名大小写的区别  
     --no-ignore-file-name-case  不忽略文件名大小写的区别  
 -x, --exclude=模式              排除匹配 <模式> 的文件  
 -X, --exclude-from=文件         排除所有匹配在<文件>中列出的模式的文件  
 -S, --starting-file=文件        当比较目录時,由<文件>开始比较  
     --from-file=文件1           将<文件1>和操作数中的所有文件/目录作比较;  
                                   <文件1>可以是目录  
     --to-file=文件2             将操作数中的所有文件/目录和<文件2>作比较;  
                                   <文件2>可以是目录  

 -i, --ignore-case               忽略文件内容大小写的区别  
 -E, --ignore-tab-expansion      忽略由制表符宽度造成的差异  
 -Z, --ignore-trailing-space     忽略每行末端的空格  
 -b, --ignore-space-change       忽略由空格数不同造成的差异  
 -w, --ignore-all-space          忽略所有空格  
 -B, --ignore-blank-lines        忽略任何因空行而造成的差异  
 -I, --ignore-matching-lines=正则 若某行完全匹配 <正则>,则忽略由该行造成的差异  

 -a, --text                      所有文件都以文本方式处理  
     --strip-trailing-cr         去除输入内容每行末端的回车(CR)字符  

 -D, --ifdef=名称                输出的内容以 ‘#ifdef <名称>’ 方式标明差异  
     --GTYPE-group-format=GFMT   以 GFMT 格式处理 GTYPE 输入行组  
     --line-format=LFMT          以 LFMT 格式处理每一行资料  
     --LTYPE-line-format=LFMT    以 LFMT 格式处理 LTYPE 输入的行  
   这些格式化选项提供对 diff 输出的精细控制,从而泛化 -D/--ifdef。  
   LTYPE 可以是 “old”、“new” 或 “unchanged”。GTYPE 可以是 LTYPE 的选择  
   或是 “changed”。  
   (仅)GFMT 可包括:  
     %<  该组中每行属于<文件1>的差异  
     %>  该组中每行属于<文件2>的差异  
     %=  该组中同时在<文件1>和<文件2>出现的每一行  
     %[-][宽度][.[精确度]]{doxX}字符  以 printf 格式表示该<字符>代表的内容  
       大写<字符>表示属于新的文件,小写表示属于旧的文件。<字符>的意义如下:  
         F  行组中第一行的行号  
         L  行组中最后一行的行号  
         N  行数 ( =L-F+1 )  
         E  F-1  
         M  L+1  
     %(A=B?T:E)  如果 A 等于 B 那么 T 否则 E  
   (仅)LFMT 可包括:  
     %L  该行的内容  
     %l  该行的内容,但不包括结束的换行符  
     %[-][宽度][.[精确度]]{doxX}n  以 printf 格式表示的输入行号  
   GFMT 或 LFMT 都可包括:  
     %%        %  
     %c'C'     单个字符 C  
     %c'\OOO'  八进制码 OOO 所代表的字符  
     C         字符 C(处上述转义外的其他字符代表它们自身)  

 -d, --minimal            尽可能找出最小的差异集  
     --horizon-lines=数量 保持指定行数的一致前后缀  
     --speed-large-files  假设文件十分大而且文件中含有许多微小的差异  
     --color[=何时]       给输出上色;“何时”可以是“never”(从不)、  
                            “always”(总是)或“auto”(自动,默认);  
                            仅指定 --color 与 --color='auto' 效果相同  
     --palette=调色板     在 --color 选项启用时使用的颜色;<调色板>参数应当是  
                            一个冒号分隔的列表以提供 terminfo capabilities 信息  

     --help               显示此帮助信息并退出  
 -v, --version            输出版本信息并退出  

 <文件列表> 的格式可以是“文件1 文件2”、“目录1 目录2”、“目录 文件”或  
     “文件 目录”。  
如果使用 --from-file 或 --to-file 选项,<文件名> 的格式则不受限制。  
如果 FILE 是 “-”,则由标准输入读取内容。  
如果输入相同,则退出状态为 0;1 表示输入不同;2 表示有错误产生。  

报告程序错误到: bug-diffutils@gnu.org  
报告翻译错误到: https://translationproject.org/teams/zh_CN.html  
GNU diffutils 主页: <https://www.gnu.org/software/diffutils/>  
使用 GNU 软件的通用帮助:<https://www.gnu.org/gethelp/>

用的时候可以横排查看不同的地方:

$ diff pmxcfs.kylin.e pmxcfs.debian10.e -y -W 180

使用 -y 表示两列查看,使用 -W 设定宽度,这样就可以在终端里分栏查看文件差异:

参考文献

linux grep 过滤多个单词

有时会需要使用 grep 做多关键词匹配,这里给出集中方法,简单记录:

grep 'word1\|word2\|word3' /path/to/file
### Search all text files ###
$ grep 'word*' *.txt
### Search all python files for 'wordA' or 'wordB' ###
$ grep 'wordA*'\''wordB' *.py
$ grep -E 'word1|word2' *.doc
$ grep -e string1 -e string2 *.pl
$ grep -E "word1|word2" *.c
### Show all the lines that do not match given pattern/words/strings ###
$ grep -v 'bar\|foo' /dir1/dir2/file1
$ grep -E -v 'pattern1|pattern2' /path/to/file

参考文献

Linux USB 设备基础理论

通过扫描以下目录获取物理节点所有 USB 设备:

/sys/bus/usb/devices/usb*
/sys/bus/usb/devices/usb*/$busnum-*

从该文件系统收集某一个设备的主要信息如下:

{
    "busnum": 1,
    "class": 0,
    "devnum": 2,
    "level": 1,
    "manufacturer": "QEMU",
    "port": 0,
    "prodid": "0001",
    "product": "QEMU USB Tablet",
    "speed": "12",
    "usbpath": "1",
    "vendid": "0627"
}

文件含义

目录下部分文件含义如下:

  • busnum: 总线号
  • devnum: 设备号(该总线的第几台设备)
  • speed: 速率
  • bDeviceClass: 设备类型
  • idVendor: 设备的生产商ID,由USB设备生产商向USB-IF官方来统一管理和申请
  • idProduct: 该生产商生产的产品编号,同一厂商下的不同idProduct代表着该公司不同的产品系列
  • product: 制造商
  • manufacturer: 产品
  • serial: USB 硬件设备序列号 ,例如 0000:00:01.2

定位方法

定位某一个 USB 设备的方法有两种:

  • busnum + devnum
  • idVendor + idProduct

设备类型bDeviceClass

类代码 用法 描述
00h 设备描述符 Use class information in the interface Descriptors
01h 接口描述符 音频
02h 设备描述符、接口描述符 通讯设备,如电话,moden等等
03h 接口描述符 HID设备
05h 接口描述符 Physical
06h 接口描述符 Image
07h 接口描述符 打印机
08h 接口描述符 大容量存储
09h 设备描述符 Hub USB集线器
0Ah 接口描述符 CDC-Data
0Bh 接口描述符 Smart Card
0Dh 接口描述符 Content Security
0Eh 接口描述符 UVC视频/CAMERA
0Fh 接口描述符 Personal Healthcare
10h 接口描述符 音视频设备
11h 设备描述符 Billboard Device Class
12h 接口描述符 USB Type-C Bridge Class
DCh 设备描述符、接口描述符 Diagnostic Device
E0h 接口描述符 无线控制器
EFh 设备描述符、接口描述符 Miscellaneous
FEh 接口描述符 Application Specific
FFh 设备描述符、接口描述符 厂商用自定义

参考文献