编写一个Shell脚本,首先进入nix shell,然后进入python虚拟环境

问题描述

我想从wsl安排工作。该工作将需要在nix-shell中运行,然后在Nix-shell下的python虚拟环境中运行。我试图通过编写一个shell脚本来执行此操作,运行./enter.sh

#!/bin/bash
nix-shell -p python38Full python38Packages.virtualenv;
source .venv/bin/activate

但是,它没有输入

(virt)
[nix-shell:xxx] 

我运行./enter.sh之后。我需要先运行第一行,然后分别运行第二行。 如果有人知道一种编写可以通过运行一个脚本来完成这两个步骤的Shell脚本的方法,那将非常有帮助。

解决方法

Shell脚本与终端中的交互式会话有些不同。

当您在终端中运行nix-shell时,原始shell进程将创建一个nix-shell进程,并使其读取您的输入,直到nix-shell退出,将控制权返回到原始shell。

另一方面,在Shell脚本中,Shell会自行读取所有行,并且不会将Shell脚本的处理委托给其他可执行文件,例如nix-shell。 *

如果要运行nix-shell中的所有命令,则可以在文件顶部使用特殊的shebang。例如:

#!/usr/bin/env nix-shell
#!nix-shell -p python38Full -p python38Packages.virtualenv
#!nix-shell -i bash
source .venv/bin/activate

# insert commands to be run here

/usr/bin/env只是一个查找nix-shell的助手,没有绝对路径。 nix-shell作为脚本解释器运行,它将解析#!nix-shell行以获得其自身的选项。 -i bash选项告诉它调用bash作为此脚本的实际解释器。 bash忽略了shebang和#!nix-shell行,因为它们是注释。 nix-shell已预先设置了正确的环境变量。它将继续获取激活文件。

您可能想在运行source之前生成激活脚本,但是我想这取决于您的工作流程。

或者,您可以使用--run COMMAND的{​​{1}}选项在Nix提供的上下文中运行单个命令。


*:括号中的命令确实在单独的进程中运行,但这主要是实现细节。它不会让其他程序接管脚本的执行。