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 commands 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.
#!nix-shell -i bash
, I can write the command for nix-shell? Since I ran the script you posted, and I didn't enter either nix shell or the virtual env. In your suggestion, shall I generate a script with onlysource .venv/bin/activate
in it ? Additionally, I was trying to have--run python start.py
, but it was showingline 5: --run: command not found.
Did I do something wrong here? – Ellmyer