如何使用powershell在wsl上运行bash脚本?



在Windows的当前目录中,我有以下脚本文件simple_script.sh:

#!/bin/bash
echo "hi from simple script"

我希望通过powershell命令行在wsl上运行这个脚本。

使用wsl命令,我找不到告诉wsl调用脚本代码的方法。

下面的命令可以工作(我认为)

wsl bash -c "echo hi from simple script"

但是,当尝试将脚本内容加载到变量中并运行它时,它不会像预期的那样工作:

$simple_script = Get-Content ./simple_script.sh
wsl bash -c $simple_script

失败:

bash: -c: option requires an argument

我尝试了一些变体。使用Get-Content-Raw标志似乎使字符串中的第一个单词打印(但不是整个字符串)。不包含""字符的命令有时似乎可以工作。但我还没有找到一个一致的方法。

一个类似的问题似乎不能直接与wsl一起工作,并且似乎没有运行驻留在Windows文件系统中的脚本文件。

从Windows执行基于shebang行的shell脚本的健壮而有效的方法isviawsl.exe -e

wsl -e ./simple_script.sh # !! ./ is required

注意:

  • 如果没有./显式地指示可执行文件位于当前目录中,该命令将以安静地失败(只有位于PATH环境变量中列出的目录中的可执行文件才能通过名称调用)。

  • -e绕过Linux端shell对的参与,而是让Linux系统函数解释基于shebang行的纯文本文件,该文件自动执行指定的解释器。

    也许令人惊讶的是,WSL认为位于Windows文件系统中的所有文件,包括纯文本文件,都具有可执行位设置,您可以轻松地使用wsl -e ls -l ./simple_script.sh
  • 进行验证。

至于你试过的:

$simple_script = Get-Content ./simple_script.sh
wsl bash -c $simple_script

主要问题是Get-Content默认返回一个数组行,并且试图将该数组用作外部程序(如wsl)的参数,导致数组的元素作为单独的参数传递给

的直接修复是使用-Raw开关,这使得Get-Content将文件内容返回为单个多行字符串

然而,由于一个非常不幸的,长期存在的错误,PowerShell -直到v7.2。x -要求手动-转义嵌入"字符传递给外部程序的参数.

  • 详情见此回答
  • 因此:

# Using -Raw, read the file in full, as a single, multi-line string.
$simple_script = Get-Content -Raw ./simple_script.sh
# !! The -escaping is needed up to PowerShell 7.2.x
wsl bash -c ($simple_script -replace '"', '"')
请注意,虽然试图通过管道 (stdin)提供脚本文本来绕过转义的需要,但是很诱人。在PowerShell 7.3.3中,不能像预期的那样工作。:
# !! Tempting, but does NOT work.
Get-Content -Raw ./simple_script.sh | wsl -e bash

这不起作用的原因是PowerShell总是在通过管道发送给外部程序的内容后面附加一个windows格式的换行符(CRLF)。, Bash无法识别。

  • 这个有问题的行为正在GitHub问题#13579中讨论。

我很难让上面的步骤为我工作。事实证明,这是WSL中默认Linux发行版的一个问题。这些步骤解决了问题。

步骤1:检查当前发行版

❯ wsl --list
Windows Subsystem for Linux Distributions:
docker-desktop-data (Default)
Ubuntu
docker-desktop

docker-desktop-data的默认值似乎是问题所在。

步骤2:更改默认

> wsl --setdefault Ubuntu

之后一切都开始工作了。

参见
如何在Windows 10上使用WSL2设置默认发行版

要在wsl上运行脚本,只需调用bash

> bash simple_script.sh
hi from simple script

将其保存在一个变量中,并在wslpowershell中作为bash脚本运行,不需要Get-Content

> $simple_script = bash /mnt/c/Users/user-name/path/to/simple_script.sh
> Write-Output $simple_script
hi from simple script

注意:Powershell有一个别名将echo映射到Write-Output,所以你也可以使用echo

> $simple_script = bash /mnt/c/Users/user-name/path/to/simple_script.sh
> echo $simple_script
hi from simple script

如果这是你最初的目标,你也可以抓取内容。

> Get-Content simple_script.sh
#!/bin/bash
echo "hi from simple script"

> $content = Get-Content .simple_script.sh
> Write-Output $content
#!/bin/bash
echo "hi from simple script"

相关内容

  • 没有找到相关文章

最新更新