I want to schedule a job from wsl. The job will need to be run in the nix-shell and then in the python virtual environment under Nix-shell. I try to do this by writing a shell script, run ./enter.sh
.
#!/bin/bash nix-shell -p python38Full python38Packages.virtualenv; source .venv/bin/activate
However, it doesn’t enter the
(virt) [nix-shell:xxx]
after I run ./enter.sh
. I need to first run the first line, then run the second line separately.
It would be super helpful if someone knows a way to write a shell script that can do these two steps by running one script.
Advertisement
Answer
Shell scripts are a bit different from interactive sessions in the terminal.
When you run nix-shell
in your terminal, the original shell process creates a nix-shell
process and lets it read your input until nix-shell
exits, returning control to the original shell.
In a shell script on the other hand, the shell will read all lines by itself and will not delegate the processing of the shell script to other executables like nix-shell
. *
If you want to run all comamnds in the nix-shell
, you can use a special shebang at the top of the file. For example:
#!/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
is just a helper to look up nix-shell
without an absolute path.
nix-shell
is run as a script interpreter that will parse #!nix-shell
lines for its own options.
The -i bash
option tells it to invoke bash
as the actual interpreter for this script.
bash
ignores the shebang and #!nix-shell
lines, because they’re comments. nix-shell
has set the right environment variables in advance. It continues to source the activate file.
You might want to generate the activate script before running source
, but I suppose that depends on your workflow.
Alternatively, you could use the --run COMMAND
option of nix-shell
to run single commands in the context provided by Nix.
*: commands in parentheses do run in a separate process, but this is mostly an implementation detail. It won’t let other programs take over the execution of the script.