在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
环境变量中列出的目录中的可执行文件才能通过名称调用)。
也许令人惊讶的是,WSL认为位于Windows文件系统中的所有文件,包括纯文本文件,都具有可执行位设置,您可以轻松地使用-e
绕过Linux端shell对的参与,而是让Linux系统函数解释基于shebang行的纯文本文件,该文件自动执行指定的解释器。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
将其保存在一个变量中,并在wsl
或powershell
中作为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"