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

How to run a bash script on wsl with powershell?

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

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

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

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

以下命令有效(我认为)

wsl bash -c "echo hi from simple script"

然而,当尝试将脚本内容加载到变量中并 运行ning 时,它没有按预期工作:

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

失败:

bash: -c: option requires an argument

我尝试了几种变体。将 Get-Content-Raw 标志一起使用似乎使要打印的字符串中的第一个单词(但不是整个字符串)。不包含“”字符的命令有时似乎有效。但我还没有找到一致的方法。

似乎不直接与 wsl 一起工作,并且似乎 运行 不是驻留在 Windows 文件系统上的脚本文件。

要 运行 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 有一个别名映射 echoWrite-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"

从 Windows 执行您的 shebang-line-based shell 脚本的稳健有效的方法是 通过 wsl.exe -e

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

注:

  • 没有 ./ 明确指示可执行文件位于当前目录中,命令将失败 安静地(仅位于目录中的可执行文件PATH 环境变量中列出的只能按名称调用)。

  • -e 绕过 shell 在 Linux 方面的参与,而是让 Linux 系统函数解释 shebang-line-based plain-text 文件,它自动接受指定的解释器。

    • 也许令人惊讶的是,WSL 考虑了位于 Windows file-system 中的 所有 个文件,包括 plain-text 个,设置 可执行位 ,您可以使用 wsl -e ls -l ./simple_script.sh
    • 轻松验证

至于你试过的

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

主要问题是 Get-Content 默认情况下 return 是一个 数组 行,并试图将该数组用作 return 的参数=52=]外部程序 例如wsl 导致数组的元素作为单独的参数传递

立即修复是使用 -Raw 开关 ,这使得 Get-Content return 文件内容成为 单个,multi-line字符串.

但是,由于非常不幸的 long-standing 错误,PowerShell - 至少 v7.2.3 - 需要手动 \-转义 嵌入 " 个字符 在传递给外部程序的参数中

  • 请参阅 v7.3 预览 版本中的 for details, including about a potential future fix that is already available as an experimental feature

因此:

# 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 at least PowerShell 7.2.3
wsl bash -c ($simple_script -replace '"', '\"')

请注意,虽然通过管道 (stdin) 提供脚本文本 试图绕过转义的需要,但这从 PowerShell 7.2.3 开始, 是否按预期工作:

# !! Tempting, but does NOT work.
Get-Content -Raw ./simple_script.sh | wsl -e bash

这不起作用的原因是 PowerShell 总是将 Windows-format 换行符 (CRLF) 附加到发送到外部程序的内容通过管道 ,Bash 无法识别。

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