如何要求WSL检查是否存在发行版,使用Bash和' wsdl .exe ' ?



我试图要求WSL检查分布是否存在,例如,wsl.exe -l -v输出:

NAME                   STATE           VERSION
Arch-Linux             Running         2
* Ubuntu                 Running         2
docker-desktop         Running         2
docker-desktop-data    Running         2

我需要让WSL检查desktop-desktop-dataArch是否存在。

这是我的小Bash代码。我用几种不同的方法进行了测试,都没有效果。

# Distribution name: Ubuntu
wsl_distro_name="docker-desktop"
# WSL command to find the distribution name
wsl_command=`wsl.exe -l -v | grep -iq '^$wsl_distro_name' | awk '{print $2}'`
if [[ "$wsl_command" ]]; then
echo "Distro found"
exit 0
else
echo "Not found"
exit 1
fi

更新答案:

这个问题背后的核心问题已经修复,或者至少在最新的WSL预览版本(0.64.0)中得到了改进,但请注意,这目前仅适用于Windows 11用户。

为了避免破坏依赖(或绕过)该问题的旧代码,修复是可选的。将WSL_UTF8环境变量设置为1(在我的测试中,只有该值)将导致wsl.exe的正确/预期输出。

请注意,如果在 WSL中使用这个环境变量,您还需要将它添加到WSLENV中,以便它被传递回"

对于您的使用,例如,现在可以使用以下命令:

export WSL_UTF8=1
WSLENV="$WSLENV":WSL_UTF8
wsl_distro_name="docker-desktop-data"
wsl.exe -l -v | grep -q "s${wsl_distro_name}s" && echo "Found" || echo "Not found"f

对于旧的WSL安装

短答:

wsl_distro_name="docker-desktop-data"
wsl.exe -l -v | iconv -f UTF-16 | grep -q "s${wsl_distro_name}s" && echo "Found" || echo "Not found"

解释:

在你的例子中有一些事情要做:

  • 首先,最可能阻碍您的事情是wsdl错误(在本问题中更详细地讨论),该错误导致输出使用混乱的UTF-16编码。在某种程度上,您可以通过wsl.exe | hexdump -C看到这一点,它将在每个常规字符之后显示空字节字符。

    该部分的解决方案是通过iconv -f utf16运行它。例如:

    wsl.exe -l -v | iconv -f UTF-16
    

我猜您可能在尝试解决前面的错误时,在代码中引入了以下一些错误:

  • 您的grep中有单引号中的$wsl_distro_name,它在Bash中禁用字符串插值。这里需要双引号

  • ^不会在正则表达式的开始工作,因为在wsl.exe -l -v输出的前几个字符中有空白(和/或星号)。最好使用"s$wsl_distro_names来查找被空格包围的发行版名称。

    这也将防止表达式找到"partial"分布的名字。没有它,"docker-desktop";将匹配"docker-desktop";"docker-desktop-data"。

  • grep -q禁用输出,当找到0或未找到1时只返回状态码。由于您试图将grep输出捕获到$wsl_command中,因此结果将始终为空。您可以删除-q以捕获输出,或者继续使用-q并测试状态代码。

  • 给定您的if语句,似乎您可能期望输出是状态结果,但测试"$wsl_command"不会为此工作,也不会通过反引号捕获输出。它看起来更像:

    wsl_distro_name="docker-desktop-data"
    wsl.exe -l -v | iconv -f UTF-16 | grep -q "s${wsl_distro_name}s"
    if [[ $? -eq 0 ]]; then
    echo Found
    fi
    

    $?变量保存了最后一个命令的退出码。

    另外:

    wsl_distro_name="docker-desktop-data"
    wsl_distro_result=$(wsl.exe -l -v | iconv -f UTF-16 | grep -o "s${wsl_distro_name}s.*" | awk '{print $2}')
    if [[ -n "$wsl_distro_result" ]]; then
    echo "Found ${wsl_distro_name} and it is ${wsl_distro_result}."
    else
    echo "${wsl_distro_name} not found."
    fi
    

    注意,我在该代码片段中向grep添加了-o选项。默认分布将在第一个字段中有一个星号,这意味着我们需要"规范化"。使awk的第二个字段始终是Status.

  • 最后,建议使用$()而不是反引号。请参阅这个问题,但请注意POSIX规范说,"不建议使用反引号括起的各种命令替换。">

  • 旁注:如果出于某种原因,您需要在Alpine中运行此操作,那么请确保安装gnu-libiconv包,以便iconv也能正确处理此操作。

最新更新