0%

WSL 开机启动并挂载 EXT4 硬盘

如何挂载 EXT4 硬盘

在 WSL 2 中装载 Linux 磁盘

确定磁盘,在powershell中运行以下命令:

1
Get-Disk | Format-Table Number, FriendlyName, Size, HealthStatus

输出为

1
2
3
4
5
6
Number FriendlyName                         Size HealthStatus
------ ------------ ---- ------------
0 Fanxiang S100Pro 1TB 1024209543168 Healthy
1 HGST HUS728T8TALE6L4 8001563222016 Healthy
3 SanDisk Ultra 3D NVMe 500GB 500107862016 Healthy
2 ZHITAI TiPlus7100 2TB 2048408248320 Healthy

选择HGST HUS728T8TALE6L4确定分区

1
Get-Partition -DiskNumber 1 | Format-Table PartitionNumber, Size, Type

输出

1
2
3
4
PartitionNumber          Size Type
--------------- ---- ----
1 6597069766656 Unknown
2 1404492054528 Basic

选择分区1

准备进行挂载操作
首先确定Disk

1
Get-CimInstance -Query "SELECT * from Win32_DiskDrive"

输出

1
2
3
4
5
6
DeviceID           Caption                     Partitions Size          Model
-------- ------- ---------- ---- -----
\\.\PHYSICALDRIVE3 SanDisk Ultra 3D NVMe 500GB 2 500105249280 SanDisk Ultra 3D NVMe 500GB
\\.\PHYSICALDRIVE0 Fanxiang S100Pro 1TB 1 1024203640320 Fanxiang S100Pro 1TB
\\.\PHYSICALDRIVE1 HGST HUS728T8TALE6L4 2 8001560609280 HGST HUS728T8TALE6L4
\\.\PHYSICALDRIVE2 ZHITAI TiPlus7100 2TB 3 2048407280640 ZHITAI TiPlus7100 2TB

\\.\PHYSICALDRIVE1

挂载命令,注意挂载命令需要以管理员权限运行

1
2
wsl.exe --mount <Disk> --partition <Index> --type <Type>
wsl.exe --mount \\.\PHYSICALDRIVE1 --partition 1 --type ext4

打开 WSL ,不需要管理员权限,在 WSL 中查看是否挂载

1
ls /mnt/wsl/

输出

1
PHYSICALDRIVE1  PHYSICALDRIVE1p1  resolv.conf

在 WSL 2 中运行以下命令来列出分区:

1
lsblk

输出

1
2
3
4
5
6
7
8
9
10
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 388.4M 1 disk
sdb 8:16 0 186M 1 disk
sdc 8:32 0 6G 0 disk [SWAP]
sdd 8:48 0 7.3T 0 disk
├─sdd1 8:49 0 6T 0 part /mnt/wsl/PHYSICALDRIVE1p1
└─sdd2 8:50 0 1.3T 0 part
sde 8:64 0 1T 0 disk /var/lib/docker
/mnt/wslg/distro
/

可以看到分区已经成功挂载到/mnt/wsl/PHYSICALDRIVE1p1

题外话

已经可以结束了,但是为了方便,创建软连接管理一下

1
sudo mkdir -p /mnt/data && sudo ln -s /mnt/wsl/PHYSICALDRIVE1p1 /mnt/data/myLibrary

验证

1
ls /mnt/data/myLibrary

搬输出出来,把ntfs分区的数据拿出来,以后吧

1
sudo mount -t ntfs-3g -o uid=1000,gid=1000,umask=022 /dev/sdX1 /mnt/ntfs_data

如何开机启动 WSL

实现 WSL 2 开机免登录自动启动

做个备份吧,万一那个 blog 没了呢。

步骤

  1. 一定要确保 WSL 当前处于最新版本(即 WSL September 2023 update 之后的版本),系统自带版本不支持这种开机启动。
  2. 打开任务计划程序。
  3. 点击右边的创建任务。
  4. 任务的名称和描述可以随便写,安全选项需要选择“不管用户是否登录都要运行”。
  5. 点击上方的“触发器”选项卡,点新建按钮,然后会卡几秒(微软的老 BUG )。开始任务中选择“启动时”,然后点击确定。
  6. “操作”选项卡中,点新建按钮,然后“程序或脚本”下的文本框里输入”C:\Program Files\WSL\wsl.exe”,引号也要带上(非常重要,除了这个目录下的wsl.exe,其他位置的都不行)。添加参数可以根据需要填写,比如-d Debian指定发行版。
  7. “条件”选项卡中,所有选项全部取消勾选。
  8. ”设置“选项卡中,除了“允许按需执行任务”,其他全部取消勾选。
  9. 点击确定关闭窗口。可以先右键运行试试效果。这种方法运行的 WSL 即使当前用户注销也是会继续运行的。

powershell命令中运行命令查看是否成功

1
wsl --list --running

输出

1
2
适用于 Linux 的 Windows 子系统分发:
Ubuntu (默认值)

启动 WSL 后自动挂载 EXT4 硬盘

思路来源于:https://github.com/microsoft/WSL/issues/6073#issuecomment-1266405095

不过他的对我来说有点问题,执行老是不成功,我自己结合我的情况写了一个,但思路是差不多的。编辑 WSL 中的/etc/wsl.conf文件,自动运行命令挂载硬盘。

AI 生成了一个ps1脚本自动挂载硬盘,脚本使用powershell7运行,所有先决条件是安装powershell7。脚本内容

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# ===========================================
# WSL 自动挂载脚本 (简化版)
# 用途:开机自动挂载多个物理磁盘分区
# ===========================================

# 配置区域 - 可根据需要修改
$isStdout = $true
$LogPath = "C:\Users\Kumi\wsl-mount.log"
$InitialDelay = 1 # 启动后延迟执行时间(秒)

#region 函数定义
function Write-Log {
param (
[string]$Message,
[bool]$isHeader=$false
)
$timestamp = if ($isHeader) { Get-Date -Format "yyyy-MM-dd HH:mm:ss" } else { Get-Date -Format "HH:mm:ss" }
if ($isStdout) {
Write-Host "[$timestamp] $Message"
}
"[$timestamp] $Message" | Out-File -FilePath $LogPath -Append
}

# 添加固定延迟(替代WSL响应检查)
"[$(Get-Date -Format 'HH:mm:ss')] 等待 $InitialDelay 秒让系统初始化..." | Out-File -FilePath $LogPath -Append
Start-Sleep -Seconds $InitialDelay

function Check-IsElevated {
$id = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$p = New-Object System.Security.Principal.WindowsPrincipal($id)
if ($p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)) {
return $true
}
else {
return $false
}
}

function Mount-DiskPartition {
param(
[int]$DiskNumber,
[int]$PartitionNumber,
[string]$FileSystemType = "ext4"
)

$mountPoint = "PHYSICALDRIVE${DiskNumber}p${PartitionNumber}"

# 检查是否已挂载
$isMounted = wsl.exe ls /mnt/wsl/ 2>$null | findstr /i $mountPoint
if ($isMounted) {
"[$(Get-Date -Format 'HH:mm:ss')] 警告:分区 $mountPoint 已挂载,跳过操作" | Out-File -FilePath $LogPath -Append
return $true
}

# 确保磁盘离线
try {
Set-Disk -Number $DiskNumber -IsOffline $true -ErrorAction Stop
"[$(Get-Date -Format 'HH:mm:ss')] 已将磁盘 $DiskNumber 设置为离线状态" | Out-File -FilePath $LogPath -Append
}
catch {
"[$(Get-Date -Format 'HH:mm:ss')] 注意:磁盘 $DiskNumber 可能已离线或不存在 - $($_.Exception.Message)" | Out-File -FilePath $LogPath -Append
}

# 执行挂载
$isAdmin = Check-IsElevated

if (-not $isAdmin) {
throw "挂载操作需要管理员权限"
}

"[$(Get-Date -Format 'HH:mm:ss')] 开始挂载:磁盘 $DiskNumber 分区 $PartitionNumber" | Out-File -FilePath $LogPath -Append
wsl.exe --mount "\\.\PHYSICALDRIVE${DiskNumber}" --partition $PartitionNumber --type $FileSystemType

# 验证挂载结果
$mountSuccess = wsl.exe ls /mnt/wsl/ | findstr /i $mountPoint
if ($mountSuccess) {
"[$(Get-Date -Format 'HH:mm:ss')] 成功挂载:\\.\PHYSICALDRIVE${DiskNumber} 分区 ${PartitionNumber} -> /mnt/wsl/${mountPoint}" | Out-File -FilePath $LogPath -Append
return $true
}
else {
throw "挂载失败:无法访问 /mnt/wsl/${mountPoint}"
}
}
#endregion


Write-Log -Message "===== WSL 挂载脚本开始执行 =====" -isHeader $true

try {
# 定义要挂载的磁盘配置
$disksToMount = @(
@{ DiskNumber = 1; PartitionNumber = 1; FileSystemType = "ext4" },
@{ DiskNumber = 3; PartitionNumber = 1; FileSystemType = "ext4" }
)

# 逐个挂载磁盘分区
foreach ($disk in $disksToMount) {
try {
Write-Log -Message "===== 开始处理磁盘 $($disk.DiskNumber) 分区 $($disk.PartitionNumber) ====="

# 执行挂载操作
$mountResult = Mount-DiskPartition `
-DiskNumber $disk.DiskNumber `
-PartitionNumber $disk.PartitionNumber `
-FileSystemType $disk.FileSystemType

Write-Log -Message "===== 磁盘 $($disk.DiskNumber) 分区 $($disk.PartitionNumber) 处理完成 =====`n"
}
catch {
Write-Log -Message "❌ 处理磁盘 $($disk.DiskNumber) 时出错:$($_.Exception.Message)"
}
}

Write-Log -Message "所有挂载操作已完成"
}
catch {
$errorMsg = $_.Exception.Message
Write-Log -Message "❌ 脚本级错误:$errorMsg"
exit 1
}
finally {
Write-Log -Message "===== WSL 挂载脚本执行结束 =====`n"
}

脚本在本机中的路径C:\Users\Kumi\wsl-mount.ps1

在 WSL 中,创建文件/path/to/wsl-auto-mount.sh,内容为:

1
2
#!/bin/bash
/mnt/c/Program\ Files/PowerShell/7/pwsh.exe -NoProfile -ExecutionPolicy Bypass -File C:\\Users\\Kumi\\wsl-mount.ps1 > /tmp/wsl-auto-mount.log 2>&1

修改 WSL 中的/etc/wsl.conf文件,添加:

1
2
[boot]
command="bash /path/to/wsl-auto-mount.sh"

可以关闭 WSL 看看效果。

1
wsl --shutdown

然后在运行 WSL 看看情况,这里可以运行之前设定好的开机任务测试一下,日志在/tmp/wsl-auto-mount.log中。

注意日志编码问题,可以使用以下命令查看:

1
cat /tmp/wsl-auto-mount.log | iconv -f GBK -t UTF-8