问题描述
我想从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提供的上下文中运行单个命令。
*:括号中的命令确实在单独的进程中运行,但这主要是实现细节。它不会让其他程序接管脚本的执行。