Makefile调用PowerShell脚本提示执行被禁用问题排查
问题背景
编写的Makefile代码如下:
SHELL := powershell.exe .SHELLFLAGS := -NoProfile -Command # Save the virtual environment path for later use VENV_PATH = $(shell poetry env info --path) # Activate the virtual environment activate: & $(VENV_PATH)\Scripts\activate.ps1
在PowerShell中执行make activate时,报错:
& : File .venv\Scripts\activate.ps1 cannot be loaded because running
scripts is disabled on this system. For more information, see about_Execution_Policies at
https:/go.microsoft.com/fwlink/?LinkID=135170.
但执行Get-ExecutionPolicy返回结果为Unrestricted。
核心原因
PowerShell的执行策略分多个作用域(Process、CurrentUser、LocalMachine等),直接在终端执行Get-ExecutionPolicy查看的是CurrentUser或LocalMachine作用域的策略,但Make调用的PowerShell是作为子进程启动的,它的Process作用域默认是Restricted,这个作用域优先级最高,会覆盖全局策略导致脚本无法执行。
另外也可能存在这种情况:你当前用的是64位PowerShell,但Make调用的是32位PowerShell,两者的执行策略设置是分开的。
解决办法
1. 强制Make调用的PowerShell使用宽松执行策略
修改Makefile中的.SHELLFLAGS,添加-ExecutionPolicy Bypass参数,让每次启动的PowerShell子进程都允许执行脚本:
.SHELLFLAGS := -NoProfile -ExecutionPolicy Bypass -Command
2. 验证PowerShell作用域的执行策略
可以在Makefile中添加一个目标,查看所有作用域的执行策略,确认问题所在:
check-policy: Get-ExecutionPolicy -List
执行make check-policy,就能看到各个作用域的执行策略值,重点看Process列的结果。
3. 注意:Make激活虚拟环境的局限性
Make的每个命令都是在独立的子进程中运行的,执行activate目标后,这个子进程就会结束,当前的PowerShell会话并不会被激活。如果想在当前会话激活虚拟环境,直接在终端执行以下命令更有效:
& $(poetry env info --path)\Scripts\activate.ps1 # 或者更简单的: poetry shell
内容的提问来源于stack exchange,提问作者Woody1193

