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

7bsow1i6  于 2023-03-23  发布在  Shell
关注(0)|答案(3)|浏览(306)

在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标志似乎可以打印字符串中的第一个单词(但不是整个字符串)。不包含'"'字符的命令有时似乎可以工作。但我还没有找到一致的方法。
A similar looking question似乎不能直接与wsl一起工作,并且似乎不能运行驻留在Windows文件系统上的脚本文件。

oaxa6hgo

oaxa6hgo1#

从Windows执行基于shebang行的shell脚本的健壮而有效的方法是通过wsl.exe -e**

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

注:

  • 如果./不显式指示可执行文件位于当前目录中,则命令将 * 悄悄地 * 失败(只能 * 按名称 * 调用位于PATH环境变量中列出的目录中的可执行文件)。
  • -e * 绕过 * Linux端的shell,而是让Linux系统函数解释基于shebang行的纯文本文件,这会自动执行指定的解释器。
  • 也许令人惊讶的是,WSL认为位于 Windows 文件系统中的 * 所有 * 文件(包括纯文本文件)都设置了 executable bit,您可以使用wsl -e ls -l ./simple_script.sh轻松验证这一点

至于你所尝试的

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

主要的问题是Get-Content默认返回一个 array 行,并且试图将该数组用作 * 外部程序 *(如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无法识别。

cczfrluj

cczfrluj2#

我在执行上述步骤时遇到了麻烦。原来是WSL中默认的Linux发行版的问题。这些步骤解决了它。
步骤1:检查当前发行版

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

docker-desktop-data默认值似乎是问题所在。
步骤2:更改默认值
> wsl --setdefault Ubuntu
从那以后,一切都开始工作了。

另见

How to set default distro using WSL2 on Windows 10

icomxhvb

icomxhvb3#

要在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的别名Map,因此您也可以使用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"

相关问题