# 在 FreeBSD 上以 lsblk(8) 风格列出块设备

* [List Block Devices on FreeBSD lsblk(8) Style](https://vermaden.wordpress.com/2019/09/27/list-block-devices-on-freebsd-lsblk8-style/)
* 作者：𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗
* 2019/09/27

当我需要在 Linux 系统上工作时，我通常会怀念很多 FreeBSD 上很棒的工具，比如仅举几例：

* **sockstat**
* **gstat**
* **top -b -o res**
* **top -m io -o total**
* **usbconfig**
* **rcorder**
* **beadm**/**bectl**
* **idprio**/**rtprio**

……但有时候——虽然很少——Linux 上也有一些非常有用的工具，而 FreeBSD 上则没有。例子就是 **lsblk(8)**，它专注于一件事，而且做得相当好——列出块设备及其内容。它也有一些问题，比如在完全应用 ZFS 池使用的磁盘上，它会显示两个分区，而不是直接显示 ZFS 的信息——但我们都知道，在某些圈子里，CDDL 许可的 ZFS 在那个 GPL 世界里是多么地“不受待见”。

来自 Linux 系统的 **lsblk(8)** 示例输出：

```sh
$ lsblk
NAME                         MAJ:MIN RM   SIZE RO TYPE   MOUNTPOINT
sr0                           11:0    1  1024M  0 rom
sda                            8:0    0 931.5G  0 disk
|-sda1                         8:1    0   500M  0 part   /boot
`-sda2                         8:2    0   931G  0 part
  |-vg_local-lv_root (dm-0)  253:0    0    50G  0 lvm    /
  |-vg_local-lv_swap (dm-1)  253:1    0  17.7G  0 lvm    [SWAP]
  `-vg_local-lv_home (dm-2)  253:2    0   1.8T  0 lvm    /home
sdc                            8:32   0 232.9G  0 disk
`-sdc1                         8:33   0 232.9G  0 part
  `-md1                        9:1    0 232.9G  0 raid10 /data
sdd                            8:48   0 232.9G  0 disk
`-sdd1                         8:49   0 232.9G  0 part
  `-md1                        9:1    0 232.9G  0 raid10 /data
```

而 FreeBSD 在这方面提供了什么？可以使用命令 **camcontrol(8)** 和 **geom(8)**。你也可以使用 **gpart(8)** 命令来列出分区。下面是我在单磁盘笔记本上运行这些命令的输出。

```sh
# camcontrol devlist
<Samsung SSD 860 EVO mSATA 1TB RVT41B6Q>  at scbus1 target 0 lun 0 (ada0,pass0)

% geom disk list
Geom name: ada0
Providers:
1. Name: ada0
   Mediasize: 1000204886016 (932G)
   Sectorsize: 512
   Mode: r1w1e2
   descr: Samsung SSD 860 EVO mSATA 1TB
   lunid: 5002538e402b4ddd
   ident: S41PNB0K303632D
   rotationrate: 0
   fwsectors: 63
   fwheads: 1

# gpart show
=>        40  1953525088  ada0  GPT  (932G)
          40      409600     1  efi  (200M)
      409640        1024     2  freebsd-boot  (512K)
      410664         984        - free -  (492K)
      411648  1953112064     3  freebsd-zfs  (931G)
  1953523712        1416        - free -  (708K)
```

它们以可接受的方式提供了所需信息，但仅适用于磁盘数量较少的系统。如果你想显示所有系统驱动器内容的汇总呢？这时 **lsblk.sh** 就派上用场了。虽然 **lsblk(8)** 拥有许多有趣的功能，如 **--perms**/**--scsi**/**--inverse** 模式，我这里重点提供的只是最基本的功能——列出系统块设备及其内容。由于我在编写 shell 脚本方面有长期且愉快的经验，例如 [**sysutils/beadm**](https://vermaden.wordpress.com/2018/11/15/zfs-boot-environments-reloaded-at-nluug-autumn-conference-2018/) 或 [**sysutils/automount**](https://vermaden.wordpress.com/2018/10/11/freebsd-desktop-part-17-automount-removable-media/)，我认为编写 **lsblk.sh** 是一个不错的主意。我实际上在 2016 年就在这个主题 [**lsblk(8)** Command for FreeBSD](https://forums.freebsd.org/threads/lsblk-8-command-for-freebsd.56008/) 的 *FreeBSD Forums* 上‘开源’或说分享了这个项目/想法，但由于时间有限，这个“副项目”的开发进度非常缓慢。我最终重新回到它，完成了它。

**lsblk.sh** 是一个总体上小巧且简单的 shell 脚本，代码行数不到四百行。

![image](https://github.com/user-attachments/assets/150fb2c9-10da-4c2f-be77-a96e5a3e2281)

下面是我在单硬盘笔记本上运行 **lsblk.sh** 命令的示例输出。

```sh
% lsblk.sh
DEVICE         MAJ:MIN  SIZE TYPE                      LABEL MOUNT
ada0             0:5b  932G GPT                           - -
  ada0p1         0:64  200M efi                    efiboot0 <UNMOUNTED>
  ada0p2         0:65  512K freebsd-boot           gptboot0 -
  <FREE>         -:-   492K -                             - -
  ada0p3         0:66  931G freebsd-zfs                zfs0 <ZFS>
  <FREE>         -:-   708K -                             - -
```

同样的输出在图形窗口中显示。

![](https://vermaden.wordpress.com/wp-content/uploads/2019/09/lolcat.png?w=960)

下面是来自一台拥有两块系统固态硬盘（**da0**/**da1**）和两块机械数据盘（**da2**/**da3**）的服务器的 **lsblk.sh** 输出示例。

```sh
# lsblk.sh
DEVICE         MAJ:MIN SIZE TYPE                      LABEL MOUNT
da0              0:be  224G GPT                           - -
  da0p1          0:15a 200M efi                    efiboot0 <UNMOUNTED>
  da0p2          0:15b 512K freebsd-boot           gptboot0 -
  <FREE>         -:-   492K -                             - -
  da0p3          0:15c 2.0G freebsd-swap              swap0 <UNMOUNTED>
  da0p4          0:15d 221G freebsd-zfs                zfs0 <ZFS>
  <FREE>         -:-   580K -                             - -
da1              0:bf  224G GPT                           - -
  da1p1          0:16a 200M efi                    efiboot1 <UNMOUNTED>
  da1p2          0:16b 512K freebsd-boot           gptboot1 -
  <FREE>         -:-   492K -                             - -
  da1p3          0:16c 2.0G freebsd-swap              swap1 <UNMOUNTED>
  da1p4          0:16d 221G freebsd-zfs                zfs1 <ZFS>
  <FREE>         -:-   580K -                             - -
da2              0:c0   11T GPT                           - -
  da2p1          0:16e  11T freebsd-zfs                   - <ZFS>
  <FREE>         -:-   1.0G -                             - -
da3              0:c1   11T GPT                           - -
  da3p1          0:16f  11T freebsd-zfs                   - <ZFS>
  <FREE>         -:-   1.0G -                             - -
```

下面是我在其他系统上测试 **lsblk.sh** 时的其他示例。

![image](https://github.com/user-attachments/assets/4535bb72-87e2-445f-92a0-201199e25f0f)

虽然 **lsblk.sh** 并不是地球上最快的脚本（因为需要进行大量解析），但它能够很好地完成工作。如果你想在系统中安装它，只需输入以下命令：

```sh
# fetch -o /usr/local/bin/lsblk https://raw.githubusercontent.com/vermaden/scripts/master/lsblk.sh
# chmod +x /usr/local/bin/lsblk
# hash -r || rehash
# lsblk
```

如果有时间，我可以考虑在 **lsblk.sh** 脚本中添加哪些其他原创的 Linux **lsblk(8)** 子命令/选项/参数呢？:🙂:

此致敬礼。

## 更新 1 – 添加 USAGE/HELP 信息

刚刚添加了一些用法信息，可以通过以下任意参数显示：

* **h**
* **-h**
* **--h**
* **help**
* **-help**
* **--help**

依我看，为这么一个简单的工具写 man 页面是没有必要的。我想等 **lsblk.sh** 工具在功能和选项上扩展到可与 Linux **lsblk(8)** 相媲美时，再创建专门的 man 页面。下面是它的显示效果。

```sh
# lsblk.sh --help
usage:

  BASIC USAGE INFORMATION
  =======================
  # lsblk.sh [DISK]

example(s):

  LIST ALL BLOCK DEVICES IN SYSTEM
  --------------------------------
  # lsblk.sh
  DEVICE         MAJ:MIN SIZE TYPE                      LABEL MOUNT
  ada0             0:5b  932G GPT                           - -
    ada0p1         0:64  200M efi                    efiboot0 <UNMOUNTED>
    ada0p2         0:65  512K freebsd-boot           gptboot0 -
    <FREE>         -:-   492K -                             - -
    ada0p3         0:66  931G freebsd-zfs                zfs0 <ZFS>

  LIST ONLY da1 BLOCK DEVICE
  --------------------------
  # lsblk.sh da1
  DEVICE         MAJ:MIN SIZE TYPE                      LABEL MOUNT
  da1              0:80  2.0G MBR                           - -
    da1s1          0:80  2.0G freebsd                       - -
      da1s1a       0:81  1.0G freebsd-ufs                root /
      da1s1b       0:82  1.0G freebsd-swap               swap SWAP

hint(s):

  DISPLAY ALL DISKS IN SYSTEM
  ---------------------------
  # sysctl kern.disks
  kern.disks: ada0 da0 da1
```

此致敬礼。

## 更新 2 – 代码重组与重写 75%

……至少这是 **git(1)** 在 **commit** 信息中告诉我的内容。

```sh
% git commit (...)
[master 12fd4aa] Rework entire flow. Split code into functions. Add many useful comments. In other words its 2.0 version.
 1 file changed, 494 insertions(+), 505 deletions(-)
 rewrite lsblk.sh (75%)
```

经过几个高效小时的工作，**lsblk.sh** 的新版本现已发布。

它的源代码行数类似，但现在缩小了四分之一……同时功能更多、准确性更高。这是 *“少即是多”* 的绝佳例子。

```sh
% wc scripts/lsblk.sh.OLD
     491    2201   19721 scripts/lsblk.sh.OLD

% wc scripts/lsblk.sh
     494    1871   15472 scripts/lsblk.sh
```

一些没有简单解决方案的问题如下所述。

其中之一是 FAT 文件系统的“双重”标签。我们既有 **/dev/gpt/efiboot0** 标签，也有 FAT 标签 **EFISYS**。必须在两者中做出选择。由于并非所有 FAT 文件系统都有标签，我选择了 GPT 标签。

```sh
% glabel status | grep ada0p1
  gpt/efiboot0     N/A  ada0p1
msdosfs/EFISYS     N/A  ada0p1
```

我也无法覆盖 FUSE 挂载。当你挂载——例如——/dev/da0 设备为 NTFS（使用 **ntfs-3g**）或 exFAT（使用 **mount.exfat**）时，**mount(8)** 输出没有明显区别。

```sh
% mount -t fusefs
/dev/fuse on /mnt/ntfs (fusefs)
/dev/fuse on /mnt/exfat (fusefs)
```

当我通过守护进程（如 **sysutils/automount**）挂载此类文件系统时，我会在 **/var/run/automount.state** 文件中记录设备挂载到的目录。然后，当我收到 **/dev/da0** 设备的 **detach** 事件时，我就知道该卸载哪个挂载点……但当只有 **/dev/fuse** 设备时，这是不可能的。

……或者，也许你知道有什么方法可以从 **/dev/fuse**（或 FUSE 一般）中提取设备挂载位置的信息吗？

下面展示更新后的效果。

这里是各种非 ZFS 文件系统的挂载情况：

```sh
% mount -t nozfs
devfs on /dev (devfs, local, multilabel)
linprocfs on /compat/linux/proc (linprocfs, local)
tmpfs on /compat/linux/dev/shm (tmpfs, local)
/dev/label/ASD on /mnt/tmp (msdosfs, local)
/dev/fuse on /mnt/ntfs (fusefs)
/dev/md0s1f on /mnt/ufs.other (ufs, local)
/dev/gpt/OTHER on /mnt/fat.other (msdosfs, local)
/dev/md0s1a on /mnt/ufs (ufs, local)
```

……现在 **lsblk.sh** 显示它们的方式如下。

```sh
% lsblk.sh
DEVICE         MAJ:MIN SIZE TYPE                      LABEL MOUNT
ada0             0:56  932G GPT                           - -
  ada0p1         0:64  200M efi                gpt/efiboot0 -
  ada0p2         0:65  512K freebsd-boot       gpt/gptboot0 -
  <FREE>         -:-   492K -                             - -
  ada0p3         0:66  931G freebsd-zfs                   - <ZFS>
  <FREE>         -:-   708K -                             - -
md0              0:28f 1.0G MBR                           - -
  md0s1          0:294 512M freebsd                       - -
    md0s1a       0:29a 100M freebsd-ufs                root /mnt/ufs
    md0s1b       0:29b  32M freebsd-swap         label/swap SWAP
    md0s1e       0:29c  64M freebsd-ufs                   - -
    md0s1f       0:29d 316M freebsd-ufs                   - /mnt/ufs.other
  md0s2          0:296 256M ntfs                          - -
  md0s3          0:297 256M fat32               msdosfs/ONE -
md1              0:2a4 1.0G msdosfs                   LARGE 
md2              0:298 2.0G GPT                           - -
  md2p1          0:29f 2.0G ms-basic-data         gpt/OTHER /mnt/fat.other
```

我为此使用了一些基于文件的内存设备。现在，默认情况下 **lsblk.sh** 也会显示内存磁盘的内容。

```sh
% mdconfig.sh -l
md0     vnode    1024M  /home/vermaden/FILE     
md2     vnode    2048M  /home/vermaden/FILE.GPT 
md1     vnode    1024M  /home/vermaden/FILER
```

下面是在 **xterm(1)** 终端中的显示效果。

![](https://vermaden.wordpress.com/wp-content/uploads/2019/09/lsblk.2.0.png?w=960)

此致敬礼。

## 更新 3 – 添加 **geli(8)** 支持

我认为添加 **geli(8)** 支持可能会很有用。最新的 **lsblk.sh** 版本现在避免了 **MOUNT** 和 **LABEL** 检测的代码重复（已移入单一统一函数）。同时添加了更多注释以提高代码可读性，并进行了一些小修复……而且脚本再次变得更小 :🙂:

```sh
% wc lsblk.sh.1.0
     491    2201   19721 lsblk.sh.1.0

% wc lsblk.sh.2.0
     493    1861   15415 lsblk.sh.2.0

% wc lsblk.sh
     488    1820   15332 lsblk.sh
```

此次更新大约修改了 40%（根据 **git commit** 显示：*191 行新增，196 行删除*）。

```sh
# git commit (...)
[master ec9985a] Add geli(8) support. Avoid code duplication and move MOUNT/LABEL detection into function. More comments. Minor fixes.
 1 file changed, 191 insertions(+), 196 deletions(-)
```

还忘了提到，现在得益于智能优化（比如避免重复操作，并将 **grep(1) | awk(1)** 管道聚合为单个 **awk(1)** 查询），**lsblk.sh** 的运行速度比最初版本快了三倍 :🙂:

下面是添加 **geli(8)** 支持后的新输出。

![](https://vermaden.wordpress.com/wp-content/uploads/2019/09/lsblk.2.1.geli_.png?w=960)

此致敬礼。

## 更新 4 – 添加 **fuse(8)** 支持

如我在 **更新 2** 中所述，跟踪 **fuse(8)** 下的挂载设备及其挂载位置非常困难，因为挂载完成后，所有挂载的设备都会神奇地变成 **/dev/fuse**。

经过一些研究，我发现这个信息（在 FreeBSD 下通过 **fuse(8)** 接口实际挂载的设备位置）可以在挂载 **procfs** 文件系统于 **/proc** 后获取。你只需要查看所有 **ntfs-3g** 进程的 **cmdline** 条目。虽然不完美，但至少可以获取到这些信息。

```sh
# mount -t procfs proc /proc

# ps ax | grep ntfs-3g
45995  -  Is      0:00.00 ntfs-3g /dev/md1s2 /mnt/ntfs
59607  -  Is      0:00.00 ntfs-3g /dev/md3 /mnt/ntfs.another
83323  -  Is      0:00.00 ntfs-3g /dev/md3 /mnt/ntfs.another

# pgrep ntfs-3g
59607
83323
45995

% pgrep ntfs-3g | while read I; do cat /proc/$I/cmdline; echo; done
ntfs-3g/dev/md3/mnt/ntfs.another
ntfs-3g/dev/md3/mnt/ntfs.another
ntfs-3g/dev/md1s2/mnt/ntfs
```

这是用于检测 **fuse(8)** 挂载点的代码原型。

```sh
    if [ -e /proc/0/status ]
    then
      FUSE_MOUNTS=$(
        while read PID
        do
          cat /proc/${PID}/cmdline
          echo
        done << ________EOF
          $( pgrep ntfs-3g )
________EOF
)
      FUSE_MOUNTS=$( echo "${FUSE_MOUNTS}" | sort -u )
      FUSE_MOUNTS=$( echo "${FUSE_MOUNTS}" | sed 's|ntfs-3g||g' )
      FUSE_CHECKS=$( echo "${FUSE_MOUNTS}" | grep /dev/${TARGET}/ )
      if [ "${FUSE_CHECKS}" != "" ]
      then
        MOUNT=$( echo "${FUSE_CHECKS}" | sed "s|/dev/${TARGET}||g" )
      fi
    fi
  fi
```

……我刚刚意识到，我找到了获取该信息的新方法（更好），无需挂载 **/proc** 文件系统——你只需要显示 **ntfs-3g** 进程及其命令行参数，例如如下方式：

```sh
% ps -p $( pgrep ntfs-3g | tr '\n' ',' | sed '$s/.$//' ) -o command | sed 1d
ntfs-3g /dev/md1s2 /mnt/ntfs
ntfs-3g /dev/md3 /mnt/ntfs.another
ntfs-3g /dev/md3 /mnt/ntfs.another
```

因此，在我考虑到这最初仅针对 NTFS（**ntfs-3g(8)** 进程）后，我也添加了 exFAT 支持，通过搜索 **mount.exfat** 的 PID。现在 **fuse(8)** 挂载点检测可以同时支持 NTFS 和 exFAT 文件系统……而且支持该功能的代码甚至更简洁。

```sh
  # 尝试从进程中获取 fuse(8) 挂载点
  if [ "${MOUNT_FOUND}" != "1" ]
  then
    FUSE_PIDS=$( pgrep mount.exfat ntfs-3g | tr '\n' ',' | sed '$s/.$//' )
    FUSE_MOUNTS=$( ps -p "${FUSE_PIDS}" -o command | sed 1d | sort -u )
    MOUNT=$( echo "${FUSE_MOUNTS}" |  grep "/dev/${TARGET} " | awk '{print $3}' )
  fi
```

我还修改了 MAJOR 和 MINOR 号的显示方式——从 HEX 改为 DEC，就像 Linux 一样。FreeBSD *Base System* 的 **ls(1)** 会以 HEX 显示，例如你会得到 **0x2af** 值：

```
% ls -l /dev/md4
crw-rw----  1 root  operator  0x2af 2019.09.29 05:18 /dev/md4
```

但使用 FreeBSD Ports 中的 GNU 等价工具 **gls(1)**（来自 **sysutils/coreutils** 包），则以 DEC 值显示 MAJOR 和 MINOR。**gls(1)** 只是 Linux 世界的 **ls(1)**，由于 FreeBSD 的 Base System 已有 **ls(1)**，开发者在名称前加了 ‘g’（代表 GNU）来区分。

```
% gls -l /dev/md4
crw-rw---- 1 root 2, 175 2019-09-29 05:18 /dev/md4
```

使用 **stat(1)** 工具也可以更方便/快速获取：

```
MAJ=$( stat -f "%Hr" /dev/${DEV} )
MIN=$( stat -f "%Lr" /dev/${DEV} )
```

最新的 **lsblk.sh** 如下所示：

![](https://vermaden.wordpress.com/wp-content/uploads/2019/09/lsblk.2.3.fuse_.ntfs_.exfat_.png?w=960)

这也是我还没有将 **lsblk.sh** 添加到 FreeBSD Ports 的原因——几天内就发布了几版带有重要新功能的版本 :🙂:

此致敬礼。

## 更新 5 – 再次重写 69%

在进一步研究 **gpart(8)** 后，我发现使用参数 **-p** 是个重大改变。使用 **-p** 参数后，它会直接显示带有分区名的输出，不再需要自己寻找 **PREFIX** 并“创建”分区名。

默认 **gpart(8)** 输出：

```sh
# gpart show md0
=>     63  2097089  md0  MBR  (1.0G)
       63  1048576    1  freebsd  (512M)
  1048639   524288    2  ntfs  (256M)
  1572927   524225    3  fat32  (256M)
```

使用参数 **-p** 的输出：

```sh
# gpart show -p md0
=>     63  2097089    md0  MBR  (1.0G)
       63  1048576  md0s1  freebsd  (512M)
  1048639   524288  md0s2  ntfs  (256M)
  1572927   524225  md0s3  fat32  (256M)
```

这一发现导致 **lsblk.sh** 进行了相当大幅重写。**git commit** 估计此次重写达 69%：

```sh
# git commit (...)
(...)
 1 file changed, 487 insertions(+), 501 deletions(-)
 rewrite lsblk.sh (69%)
```

最新 **lsblk.sh** 的特性如下：

* 修复了之前的 BUG。
* 可以检测 exFAT 标签。
* 运行速度提升 20%。
* SLOC 减少 10%。
* 代码量减少 15%。
* 正确处理整个设备上的 **bsdlabel(8)**。
* 正确处理整个设备上的 exFAT。

代码差异如下：

```sh
# wc lsblk.sh
     487    1791   13705 lsblk.sh

# wc lsblk.sh.OLD
     544    1931   16170 lsblk.sh.OLD
```

最新 **lsblk.sh** 看起来仍然如以前，但我现在用 ‘**-**’ 替代了以前的 ‘’ 标记：

![](https://vermaden.wordpress.com/wp-content/uploads/2019/09/lsblk.2.5.gpart_.exfat_.png?w=960)

## 更新 6 – 新的更新与修复版本

**lsblk.sh** 已更新至 3.4 版本——并已在 FreeBSD Ports 树中更新，在 **sysutils/lsblk** Port 中可用。

该版本的 *变更日志* 如下：

* 在磁盘列表中添加 **sysctl -n kern.disks**。
* 在 **\_\_gpart\_present** 函数中重置 **LABEL**。
* 修复 **gpart(8)** 的 **\[bootme]** 和 **\[bootonce]** 标志行为。
* 禁用 **GPTID** 显示标签。
* 添加 **-d|–disks** 选项，仅列出整个磁盘。

请注意，**lsblk.sh** 使用 **diskinfo(8)**，为了正常工作，你需要属于 **operator** 组。你可以这样将自己添加到该组：

```
# pw groupmod operator -m yourself
```

……或者通过编辑 **/etc/group** 文件。

示例输出如下：

![](https://vermaden.wordpress.com/wp-content/uploads/2019/09/lsblk.update6.png?w=960)

## 更新 7 – 更多修复

**lsblk.sh** 已更新至 3.5 版本——并已在 FreeBSD Ports 树中更新，在 **sysutils/lsblk** Port 中可用。

该版本的 *变更日志* 如下：

* 列出磁盘时移除输出中的控制序列和颜色。
* **diskinfo(8)** 仅用于 **md(4)** 磁盘，因为 **geom(4)** 不支持它们。
* 添加新注释并重新整理部分旧注释。
* 为 SIZE 收集和显示增加额外检查。
* 当整个设备没有分区时，正确显示 exFAT 文件系统标签。
* 修复 NTFS-3G 挂载点显示。
* 检查 **automount(8)** 的 **/var/run/automount.state** 以处理 **fusefs(5)** 文件系统。

仅 **md(4)** 磁盘的大小需要属于 **operator** 组。所有其他磁盘大小现在通过 **geom(8)** 命令收集。

## 更新 8 – 优化标签

现在 3.9 版本的 **lsblk(8)** 比以往更好。

![](https://vermaden.wordpress.com/wp-content/uploads/2019/09/lsblk.update8.png)

该版本的 *变更日志* 如下：

* 改进 **glabel(8)** 标签搜索。
* 改进 **gpart(8)** 输出标签处理。
* 将冗长的 Microsoft 分区名称替换为合理名称。
* 改进 exFAT 处理。
* 改进 **md(4)** 磁盘大小处理。
* 移除标签中的冗余空格。
* 为 **-d** 选项添加 **TOTAL SYSTEM STORAGE**。
* 移除主设备检查循环中的子 shell。

已提交 PR [283268](https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=283268) ，因此在 Ports 中更新前请稍作等待。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://translated-articles.bsdcn.org/2025-nian/list-block-devices-on-freebsd-lsblk8-style.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
