我在 WSL 中使用 Ubuntu,并使用 zsh/bash shell。我的主机操作系统是 Windows 10。我已经弄清楚了如何安装 Windows 外部驱动器:
sudo mkdir /mnt/d
sudo mount -t drvfs D: /mnt/d
我很少插入此驱动器,因此我希望在插入时自动安装它。如果在插入驱动器后发生这种情况,则没问题,然后启动一个新的 WSL 终端。
我不想把这个命令放在某种.bashrc
文件中,因为每次打开终端时都要输入密码,这太麻烦了,尤其是如果 99% 的情况下命令都会失败。把它放在 bash 脚本中也没什么用,因为我很少运行它,等到我需要使用它的时候,我就会忘记我一开始创建了它。
那么,当外部驱动器在 WSL 中可用时,有没有办法安装它?
我不知道这是否是一个好的解决方案,但这会告诉你如何关闭 sudo 的密码请求。这是我采取的路线:https://superuser.com/a/1492456/89165
答案1
在我看来,这需要两种不同的方法:
- 首先,我们需要处理驱动器已连接时 WSL 启动的情况。
- 而且我们还需要处理当 WSL 已在运行时连接驱动器的情况。
WSL 启动时驱动器已连接
第一部分应该相当简单。
我不想把这个命令放在 .bashrc 类型的文件中,因为每次打开终端时都要输入密码
这很容易解决。将以下内容添加到您的~/.bashrc
:
wsl.exe -u root -e mount -t drvfs D: /mnt/d > /dev/null 2>&1
如果驱动器可用,则将安装该驱动器。如果不可用,则将默默失败。
WSL 运行时驱动器已连接
这并不容易,并且可能需要更多的错误处理才能“健壮”,但我能够通过创建 PowerShell 脚本来使其工作:
- 当 USB 驱动器连接时注册操作
wsl -u root -e mount -t drvfs /mnt/<driveletter> <Drive>
事件触发时运行。
$query = "select * from __InstanceCreationEvent within 5 where TargetInstance ISA 'Win32_LogicalDisk' and TargetInstance.DriveType = 2"
$action = {
$drivePath = $event.SourceEventArgs.NewEvent.TargetInstance.Name
$driveLetter = $drivePath.ToLower()[0]
wsl -u root -e mount -t drvfs $drivePath /mnt/$driveLetter
}
Register-WmiEvent -Query $Query -Action $Action -SourceIdentifier USBFlashDriveWSLMount
请注意,由于它使用了,因此需要在 Windows PowerShell(而不是 PowerShell Core)中运行WMIEvent
。我确信有一个使用 CIM 的 PowerShell Core 等效程序,但我还没有尝试过这种方式。
如果遇到问题,请检查输出。从 PowerShell:
Get-Job
# Get the Id of the job then
Receive-Job <job_id>
理论上,您可以通过任务计划程序将此脚本设置为在 Windows 登录时运行,但我还没有尝试过。我有 80% 的信心它会起作用。您需要通过命令调用它powershell
(pwsh
因为它使用 WMIEvent,所以不需要)。
请注意,显然还有一种方法可以通过 CIM 永久注册事件侦听器。上周我花了一些时间研究这个问题,但当我按照一些文档操作时,却发现在我的系统上创建了一个我无法摆脱的 CIM 类,于是就陷入了困境。我可能最终会回到这个问题上,但希望这对您来说可以作为计划任务。我只是不想等到我“恰到好处”时才发布,因为我可能永远也做不完。
答案2
这 1 行代码将删除 sudo 的密码请求。
sudo sed -i 's|^%sudo.*$|%sudo ALL=(ALL:ALL) NOPASSWD: ALL|' -i /etc/sudoers
这 1 行代码将列出未安装的驱动器。
echo -e "$(cmd.exe /C "wmic logicaldisk get name" 2>/dev/null | sed '1d;$d')\n$(mount | grep drvfs | sed 's|\(^.:\).*|\1|')" | tr '\r' ' ' |sed 's| ||g' | sort | uniq -u
因此,我们可以定义一个函数~/.bashrc
或创建一个 bash 脚本来挂载它们。您可以自行决定是手动调用该函数还是将其添加到~/.bashrc
mountext(){ # Find unmounted windows drives and mount them.
ds=$(echo -e "$(cmd.exe /C "wmic logicaldisk get name" 2>/dev/null | sed '1d;$d')\n$(mount | grep drvfs | sed 's|\(^.:\).*|\1|')" | tr '\r' ' ' |sed 's| ||g' | sort | uniq -u | cut -c1)
if [ ! $ds = $'\n' ] || [ ! -z "${ds}" ]; then
for d in $ds; do
sudo bash -c "mkdir -p /mnt/${d,} && mount -t drvfs ${d}: /mnt/${d,}"
echo "Mounted drive ${d}: at /mnt/${d,}."
done
else echo "No drives to mount."
fi
}
答案3
此命令:
cmd.exe /C "wmic logicaldisk get name"
将显示网络安装以及实际上未加载媒体的驱动器号。例如,我有一个多格式存储卡读卡器,它保留了五个驱动器号(每个插槽一个,例如 SD、micro-SD 等),即使没有安装卡,此查询也会返回所有这些驱动器号。因此,我使用以下命令获取其中有媒体的本地驱动器号:
powershell.exe -Command "gdr -PSProvider 'FileSystem'"|grep '[0-9]\+'|grep -o '[A-Z]:'
假设您的路径中有 powershell.exe 并以 sudo 身份运行。
第一个 grep 语句选择文件系统列表中显示可用空间的行(即已安装媒体的代理);第二个 grep 只是在末尾提取驱动器号。您应该能够将此输出输入到上面提供的相同脚本中,以便在 WSL 中安装为 drvfs。
总而言之,您可以以 root 身份将其作为 cronjob 运行:
#!/bin/bash
ds=$(echo -e "$(powershell -Command "gdr -PSProvider 'FileSystem'"|grep '[0-9]\+'|grep -o '[A-Z]:' 2>/dev/null | sed '1d;$d')\n$(mount | grep drvfs | sed 's|\(^.:\).*|\1|')" | tr '\r' ' ' |sed 's| ||g' | sort | uniq -u | cut -c1)
if [ ! $ds = $'\n' ] || [ ! -z "${ds}" ]; then
for d in $ds; do
bash -c "mkdir -p /mnt/${d,} && mount -t drvfs ${d}: /mnt/${d,}"
echo "Mounted drive ${d}: at /mnt/${d,}."
done
else echo "No drives to mount."
fi