feat: udpate for 'nix run' & 'nix shell'

This commit is contained in:
Ryan Yin 2023-07-16 13:00:39 +08:00
parent a94d3f0700
commit dcc7f4b48f
7 changed files with 230 additions and 133 deletions

View File

@ -242,49 +242,52 @@ Hello, world!
This usage is mainly used to debug the build process of a Nix package, or to execute some commands in the build environment of a Nix package. This usage is mainly used to debug the build process of a Nix package, or to execute some commands in the build environment of a Nix package.
## `nix shell` & `nix run` ## `nix build`
Compare to `nix develop`, these two commands are much simpler and easier to understand. The `nix build` command is used to build a software package and creates a symbolic link named `result` in the current directory, which points to the build result.
`nix shell` is used to enter an environment containing the specified Nix package and open an interactive shell for it: Here's an example:
```shell ```bash
# hello not exists # Build the package 'ponysay' from the 'nixpkgs' flake
hello nix build "nixpkgs#ponysay"
hello: command not found # Use the built 'ponysay' command
./result/bin/ponysay 'hey buddy!'
# enter an environment containing hello ____________
nix shell nixpkgs#hello < hey buddy! >
------------
# now hello exists \
hello \
Hello, world! \
▄▄ ▄▄ ▄ ▄
▀▄▄▄█▄▄▄▄▄█▄▄▄
▀▄███▄▄██▄██▄▄██
▄██▄███▄▄██▄▄▄█▄██
█▄█▄██▄█████████▄██
▄▄█▄█▄▄▄▄▄████████
▀▀▀▄█▄█▄█▄▄▄▄▄█████ ▄ ▄
▀▄████▄▄▄█▄█▄▄██ ▄▄▄▄▄█▄▄▄
█▄██▄▄▄▄███▄▄▄██ ▄▄▄▄▄▄▄▄▄█▄▄
▀▄▄██████▄▄▄████ █████████████
▀▀▀▀▀█████▄▄ ▄▄▄▄▄▄▄▄▄▄██▄█▄▄▀
██▄███▄▄▄▄█▄▄▀ ███▄█▄▄▄█▀
█▄██▄▄▄▄▄████ ███████▄██
█▄███▄▄█████ ▀███▄█████▄
██████▀▄▄▄█▄█ █▄██▄▄█▄█▄
███████ ███████ ▀████▄████
▀▀█▄▄▄▀ ▀▀█▄▄▄▀ ▀██▄▄██▀█
▀ ▀▀█
``` ```
`nix run` is used to create an environment containing the specified installable and run the installable in it(without install it to the system): ## Other Commands
```shell There are other commands like `nix flake init`, which you can explore in [New Nix Commands][New Nix Commands]. For more detailed information, please refer to the documentation.
# hello not exists
hello
hello: command not found
# enter an environment containing hello and run it
nix run nixpkgs#hello
Hello, world!
```
Because `nix run` will directly run the Nix package as an installable, the Nix package used as its parameter must be able to generate an executable program.
According to the description of `nix run --help`, `nix run` will execute `<out>/bin/<name>`, where `<out>` is the root directory of a Derivation, and `<name>` is selected in the following order:
- The `meta.mainProgram` attribute of the derivation.
- The `pname` attribute of the derivation.
- The `name` part of the value of the name attribute of the derivation.
For instance, if name is set to `hello-1.10`, nix run will run $out/bin/hello.
## References ## References
- [pkgs.mkShell - nixpkgs manual](https://nixos.org/manual/nixpkgs/stable/#sec-pkgs-mkShell) - [pkgs.mkShell - nixpkgs manual](https://nixos.org/manual/nixpkgs/stable/#sec-pkgs-mkShell)
- [A minimal nix-shell](https://fzakaria.com/2021/08/02/a-minimal-nix-shell.html) - [A minimal nix-shell](https://fzakaria.com/2021/08/02/a-minimal-nix-shell.html)
- [One too many shell, Clearing up with nix' shells nix shell and nix-shell - Yannik Sander](https://blog.ysndr.de/posts/guides/2021-12-01-nix-shells/) - [One too many shell, Clearing up with nix' shells nix shell and nix-shell - Yannik Sander](https://blog.ysndr.de/posts/guides/2021-12-01-nix-shells/)
[New Nix Commands]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix.html

View File

@ -1,43 +1,49 @@
# Flake inputs {#flake-inputs} # Flake Inputs
The `inputs` in `flake.nix` is an attribute set, used to specify the dependencies of the current flake, there are many types of `inputs`, for example: The `inputs` section in `flake.nix` is an attribute set used to specify the dependencies of the current flake. There are various types of inputs, as shown in the examples below:
```nix ```nix
{ {
inputs = { inputs = {
# use master branch of the GitHub repository as input, this is the most common input format # GitHub repository as the data source, specifying the master branch. This is the most common input format.
nixpkgs.url = "github:Mic92/nixpkgs/master"; nixpkgs.url = "github:Mic92/nixpkgs/master";
# Git URL, can be used for any Git repository based on https/ssh protocol # Git URL, applicable to any Git repository using the https/ssh protocol.
git-example.url = "git+https://git.somehost.tld/user/path?ref=branch&rev=fdc8ef970de2b4634e1b3dca296e1ed918459a9e"; git-example.url = "git+https://git.somehost.tld/user/path?ref=branch";
# The above example will also copy .git, use this for (shallow) local Git repos # Similar to fetching a Git repository, but using the ssh protocol with key authentication. Also uses the shallow=1 parameter to avoid copying the .git directory.
ssh-git-example.url = "git+ssh://git@github.com/ryan4yin/nix-secrets.git?shallow=1";
# It's also possible to directly depend on a local Git repository.
git-directory-example.url = "git+file:/path/to/repo?shallow=1"; git-directory-example.url = "git+file:/path/to/repo?shallow=1";
# Local directories (for absolute paths you can omit 'path:') # Using the `dir` parameter to specify a subdirectory.
nixpkgs.url = "github:foo/bar?dir=shu";
# Local folder (if using an absolute path, the 'path:' prefix can be omitted).
directory-example.url = "path:/path/to/repo"; directory-example.url = "path:/path/to/repo";
# If the data source is not a flake, set flake=false.
# `flake=false` is usually used to include additional source code, configuration files, etc.
# In Nix code, you can directly reference files within it using "${inputs.bar}/xxx/xxx" notation.
# For example, import "${inputs.bar}/xxx/xxx.nix" to import a specific nix file,
# or use "${inputs.bar}/xx/xx" as a path parameter for certain options.
bar = { bar = {
url = "github:foo/bar/branch"; url = "github:foo/bar/branch";
# if the input is not a flake, you need to set flake=false
flake = false; flake = false;
}; };
sops-nix = { sops-nix = {
url = "github:Mic92/sops-nix"; url = "github:Mic92/sops-nix";
# The `follows` keyword in inputs is used for inheritance. # `follows` is the inheritance syntax within inputs.
# Here, `inputs.nixpkgs` of sops-nix is kept consistent with the `inputs.nixpkgs` in # Here, it ensures that sops-nix's `inputs.nixpkgs` aligns with the current flake's inputs.nixpkgs,
# the current flake, to avoid problems caused by different versions of nixpkgs. # avoiding inconsistencies in the dependency's nixpkgs version.
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
# Pin flakes to a specific revision # Lock the flake to a specific commit.
nix-doom-emacs = { nix-doom-emacs = {
url = "github:vlaci/nix-doom-emacs?rev=238b18d7b2c8239f676358634bfb32693d3706f3"; url = "github:vlaci/nix-doom-emacs?rev=238b18d7b2c8239f676358634bfb32693d3706f3";
flake = false; flake = false;
}; };
# To use a subdirectory of a repo, pass `dir=xxx`
nixpkgs.url = "github:foo/bar?dir=shu";
}; };
outputs = { self, ... }@inputs: { ... }; outputs = { self, ... }@inputs: { ... };
} }
``` ```

View File

@ -1,37 +1,77 @@
# Usage of the New CLI # Usage of the New CLI
Once you have enabled `nix-command` and `flake`, you can use the `nix help` command to obtain information about the [New Nix Commands][New Nix Commands]. Here are some useful examples: Once you have enabled the `nix-command` and `flakes` features, you can start using the new generation Nix command-line tools provided by [New Nix Commands][New Nix Commands]. In this section, we will focus on two commands: `nix shell` and `nix run`. Other important commands like `nix build` will be discussed in detail in the chapter "Development Work on NixOS".
```bash ## `nix shell`
# The following command installs and runs the `ponysay` package from the `nixpkgs` flake.
# The `nixpkgs` flake refers to the `nixpkgs` repository on GitHub, which contains a `flake.nix` file.
# `nixpkgs` is a flake registry ID for `github:NixOS/nixpkgs/nixos-unstable`.
# You can find all the flake registry IDs at <https://github.com/NixOS/flake-registry/blob/master/flake-registry.json>.
echo "Hello Nix" | nix run "nixpkgs#ponysay"
# this command is the same as above, but use a full flake URI instead of falkeregistry id. The `nix shell` command allows you to enter an environment with the specified Nix package and opens an interactive shell within that environment:
echo "Hello Nix" | nix run "github:NixOS/nixpkgs/nixos-unstable#ponysay"
# instead of treat flake package as an application, ```shell
# this command use `devShells.example` in flake `zero-to-nix`'s outputs, to setup the development environment, # hello is not available
# and then open a bash shell in that environment. hello
nix develop "github:DeterminateSystems/zero-to-nix#example" hello: command not found
# instead of using a remote flake, you can open a bash shell using the flake located in the current directory. # Enter an environment with the 'hello' package
mkdir my-flake && cd my-flake nix shell nixpkgs#hello
# init a flake with template
nix flake init --template "github:DeterminateSystems/zero-to-nix#javascript-dev"
# open a bash shell using the flake in current directory
nix develop
# or if your flake has multiple devShell outputs, you can specify which one to use.
nix develop .#example
# build package `bat` from flake `nixpkgs`, and put a symlink `result` in the current directory. # hello is now available
mkdir build-nix-package && cd build-nix-package hello
nix build "nixpkgs#bat" Hello, world!
# build a local flake is the same as nix develop, skip it
``` ```
We will introduce more details about `nix develop`, `nix shell` and `nix run` in the next chapter. ## `nix run`
On the other hand, `nix run` creates an environment with the specified Nix package and directly runs that package within the environment (without installing it into the system environment):
```shell
# hello is not available
hello
hello: command not found
# Create an environment with the 'hello' package and run it
nix run nixpkgs#hello
Hello, world!
```
Since `nix run` directly executes the Nix package, the package specified as the argument must generate an executable program.
According to the `nix run --help` documentation, `nix run` executes the command `<out>/bin/<name>`, where `<out>` is the root directory of the derivation and `<name>` is selected in the following order:
- The `meta.mainProgram` attribute of the derivation
- The `pname` attribute of the derivation
- The content of the `name` attribute of the derivation with the version number removed
For example, in the case of the 'hello' package we tested earlier, `nix run` actually executes the program `$out/bin/hello`.
Here are two more examples with detailed explanations of the relevant parameters:
```bash
# Explanation of the command:
# `nixpkgs#ponysay` means the 'ponysay' package in the 'nixpkgs' flake.
# `nixpkgs` is a flake registry id, and Nix will find the corresponding GitHub repository address
# from <https://github.com/NixOS/flake-registry/blob/master/flake-registry.json>.
# Therefore, this command creates a new environment, installs, and runs the 'ponysay' package provided by the 'nixpkgs' flake.
# Note: It has been mentioned earlier that a Nix package is one of the outputs of a flake.
echo "Hello Nix" | nix run "nixpkgs#ponysay"
# This command has the same effect as the previous one, but it uses the complete flake URI instead of the flake registry id.
echo "Hello Nix" | nix run "github:NixOS/nixpkgs/nixos-unstable#ponysay"
```
## Common Use Cases for `nix run` and `nix shell`
These commands are commonly used for running temporary commands. For example, if I want to clone my configuration repository using Git on a new NixOS host without Git installed, I can use the following command:
```bash
nix run nixpkgs#git clone git@github.com:ryan4yin/nix-config.git
```
Alternatively, you can use the following command:
```bash
nix shell nixpkgs#git
git clone git@github.com:ryan4yin/nix-config.git
```
[New Nix Commands]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix.html [New Nix Commands]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix.html

View File

@ -246,49 +246,53 @@ Hello, world!
这种用法的主要应用场景是调试某个 Nix 包的构建过程,或者在某个 Nix 包的构建环境中执行一些命令。 这种用法的主要应用场景是调试某个 Nix 包的构建过程,或者在某个 Nix 包的构建环境中执行一些命令。
## `nix shell` 与 `nix run` ## `nix build`
`nix develop` 相比,这两个命令就简单且好理解很多了 `nix build` 用于构建一个软件包,并在当前目录下创建一个名为 `result` 的符号链接,链接到该构建结果
`nix shell` 用于进入到一个含有指定 Nix 包的环境并为它打开一个交互式 shell 一个示例
```shell ```bash
# hello 不存在 # 构建 `nixpkgs` flake 中的 `ponysay` 这个包
hello nix build "nixpkgs#ponysay"
hello: command not found # 使用构建出来的 ponysay 命令
./result/bin/ponysay 'hey buddy!'
# 进入到一个含有 hello 的 shell 环境 ____________
nix shell nixpkgs#hello < hey buddy! >
------------
# hello 可以用了 \
hello \
Hello, world! \
▄▄ ▄▄ ▄ ▄
▀▄▄▄█▄▄▄▄▄█▄▄▄
▀▄███▄▄██▄██▄▄██
▄██▄███▄▄██▄▄▄█▄██
█▄█▄██▄█████████▄██
▄▄█▄█▄▄▄▄▄████████
▀▀▀▄█▄█▄█▄▄▄▄▄█████ ▄ ▄
▀▄████▄▄▄█▄█▄▄██ ▄▄▄▄▄█▄▄▄
█▄██▄▄▄▄███▄▄▄██ ▄▄▄▄▄▄▄▄▄█▄▄
▀▄▄██████▄▄▄████ █████████████
▀▀▀▀▀█████▄▄ ▄▄▄▄▄▄▄▄▄▄██▄█▄▄▀
██▄███▄▄▄▄█▄▄▀ ███▄█▄▄▄█▀
█▄██▄▄▄▄▄████ ███████▄██
█▄███▄▄█████ ▀███▄█████▄
██████▀▄▄▄█▄█ █▄██▄▄█▄█▄
███████ ███████ ▀████▄████
▀▀█▄▄▄▀ ▀▀█▄▄▄▀ ▀██▄▄██▀█
▀ ▀▀█
``` ```
`nix run` 则是创建一个含有指定 Nix 包的环境,并在该环境中直接运行该 Nix 包(临时运行该程序,不将它安装到系统环境中): ## 其他命令
```shell 其他还有些 `nix flake init` 之类的命令,请自行查阅 [New Nix Commands][New Nix Commands] 学习研究,这里就不详细介绍了。
# hello 不存在
hello
hello: command not found
# 创建一个含有 hello 的环境并运行它
nix run nixpkgs#hello
Hello, world!
```
因为 `nix run` 会直接将 Nix 包运行起来,所以作为其参数的 Nix 包必须能生成一个可执行程序。
根据 `nix run --help` 的说明,`nix run` 会执行 `<out>/bin/<name>` 这个命令,其中 `<out>` 是一个 Derivation 的根目录,`<name>` 则按如下顺序进行选择尝试:
- Derivation 的 `meta.mainProgram` 属性
- Derivation 的 `pname` 属性
- Derivation 的 `name` 属性中去掉版本号后的内容
比如说我们上面测试的包 hello`nix run` 实际会执行 `$out/bin/hello` 这个程序。
## References ## References
- [pkgs.mkShell - nixpkgs manual](https://nixos.org/manual/nixpkgs/stable/#sec-pkgs-mkShell) - [pkgs.mkShell - nixpkgs manual](https://nixos.org/manual/nixpkgs/stable/#sec-pkgs-mkShell)
- [A minimal nix-shell](https://fzakaria.com/2021/08/02/a-minimal-nix-shell.html) - [A minimal nix-shell](https://fzakaria.com/2021/08/02/a-minimal-nix-shell.html)
- [One too many shell, Clearing up with nix' shells nix shell and nix-shell - Yannik Sander](https://blog.ysndr.de/posts/guides/2021-12-01-nix-shells/) - [One too many shell, Clearing up with nix' shells nix shell and nix-shell - Yannik Sander](https://blog.ysndr.de/posts/guides/2021-12-01-nix-shells/)
[New Nix Commands]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix.html

View File

@ -8,12 +8,21 @@
# 以 GitHub 仓库为数据源,指定使用 master 分支,这是最常见的 input 格式 # 以 GitHub 仓库为数据源,指定使用 master 分支,这是最常见的 input 格式
nixpkgs.url = "github:Mic92/nixpkgs/master"; nixpkgs.url = "github:Mic92/nixpkgs/master";
# Git URL可用于任何基于 https/ssh 协议的 Git 仓库 # Git URL可用于任何基于 https/ssh 协议的 Git 仓库
git-example.url = "git+https://git.somehost.tld/user/path?ref=branch&rev=fdc8ef970de2b4634e1b3dca296e1ed918459a9e"; git-example.url = "git+https://git.somehost.tld/user/path?ref=branch";
# 上面的例子会复制 .git 到本地, 如果数据量较大,建议使用 shallow=1 参数避免复制 .git # 同样是拉取 Git 仓库,但使用 ssh 协议 + 密钥认证,同时使用了 shallow=1 参数避免复制 .git
ssh-git-example.url = "git+ssh://git@github.com/ryan4yin/nix-secrets.git?shallow=1";
# 当然也可以直接依赖本地的 git 仓库
git-directory-example.url = "git+file:/path/to/repo?shallow=1"; git-directory-example.url = "git+file:/path/to/repo?shallow=1";
# 使用 `dir` 参数指定某个子目录
nixpkgs.url = "github:foo/bar?dir=shu";
# 本地文件夹 (如果使用绝对路径,可省略掉前缀 'path:') # 本地文件夹 (如果使用绝对路径,可省略掉前缀 'path:')
directory-example.url = "path:/path/to/repo"; directory-example.url = "path:/path/to/repo";
# 如果数据源不是一个 flake则需要设置 flake=false # 如果数据源不是一个 flake则需要设置 flake=false
# `flake=false` 通常被用于引入一些额外的源代码、配置文件等
# 在 nix 代码中可以直接通过 "${inputs.bar}/xxx/xxx" 的方式来引用其中的文件
# 比如说通过 `import "${inputs.bar}/xxx/xxx.nix"` 来导入其中的 nix 文件
# 或者直接将 "${inputs.bar}/xx/xx" 当作某些 option 的路径参数使用
bar = { bar = {
url = "github:foo/bar/branch"; url = "github:foo/bar/branch";
flake = false; flake = false;
@ -32,9 +41,6 @@
url = "github:vlaci/nix-doom-emacs?rev=238b18d7b2c8239f676358634bfb32693d3706f3"; url = "github:vlaci/nix-doom-emacs?rev=238b18d7b2c8239f676358634bfb32693d3706f3";
flake = false; flake = false;
}; };
# 使用 `dir` 参数指定某个子目录
nixpkgs.url = "github:foo/bar?dir=shu";
}; };
outputs = { self, ... }@inputs: { ... }; outputs = { self, ... }@inputs: { ... };

View File

@ -2,6 +2,3 @@
到这里我们已经写了不少 Nix Flakes 配置来管理 NixOS 系统了,这里再简单介绍下 Nix Flakes 更细节的内容,以及常用的 nix flake 命令。 到这里我们已经写了不少 Nix Flakes 配置来管理 NixOS 系统了,这里再简单介绍下 Nix Flakes 更细节的内容,以及常用的 nix flake 命令。
此外 [Zero to Nix - Determinate Systems][Zero to Nix - Determinate Systems] 是一份全新的 Nix & Flake 新手入门文档,写得比较浅显易懂,也可以一读。
[Zero to Nix - Determinate Systems]: https://github.com/DeterminateSystems/zero-to-nix

View File

@ -1,6 +1,50 @@
# 新一代 Nix 命令行工具的使用 {#flake-commands-usage} # 新一代 Nix 命令行工具的使用 {#flake-commands-usage}
在启用了 `nix-command` & `flakes` 功能后,我们就可以使用 Nix 提供的新一代 Nix 命令行工具 [New Nix Commands][New Nix Commands] 了,下面列举下其中常用命令的用法: 在启用了 `nix-command` & `flakes` 功能后,我们就可以使用 Nix 提供的新一代 Nix 命令行工具 [New Nix Commands][New Nix Commands] 了,
这里主要介绍 `nix shell``nix run` 两个命令,其他重要的命令(如 `nix shell` `nix build`)将在「在 NixOS 上进行开发工作」一章中再详细介绍。
## `nix shell`
`nix shell` 用于进入到一个含有指定 Nix 包的环境并为它打开一个交互式 shell
```shell
# hello 不存在
hello
hello: command not found
# 进入到一个含有 hello 的 shell 环境
nix shell nixpkgs#hello
# hello 可以用了
hello
Hello, world!
```
## `nix run`
`nix run` 则是创建一个含有指定 Nix 包的环境,并在该环境中直接运行该 Nix 包(临时运行该程序,不将它安装到系统环境中):
```shell
# hello 不存在
hello
hello: command not found
# 创建一个含有 hello 的环境并运行它
nix run nixpkgs#hello
Hello, world!
```
因为 `nix run` 会直接将 Nix 包运行起来,所以作为其参数的 Nix 包必须能生成一个可执行程序。
根据 `nix run --help` 的说明,`nix run` 会执行 `<out>/bin/<name>` 这个命令,其中 `<out>` 是一个 Derivation 的根目录,`<name>` 则按如下顺序进行选择尝试:
- Derivation 的 `meta.mainProgram` 属性
- Derivation 的 `pname` 属性
- Derivation 的 `name` 属性中去掉版本号后的内容
比如说我们上面测试的包 hello`nix run` 实际会执行 `$out/bin/hello` 这个程序。
再给两个示例,并详细说明下相关参数:
```bash ```bash
# 解释下这条指令涉及的参数: # 解释下这条指令涉及的参数:
@ -14,25 +58,22 @@ echo "Hello Nix" | nix run "nixpkgs#ponysay"
# 这条命令和上面的命令作用是一样的,只是使用了完整的 flake URI而不是 flakeregistry id。 # 这条命令和上面的命令作用是一样的,只是使用了完整的 flake URI而不是 flakeregistry id。
echo "Hello Nix" | nix run "github:NixOS/nixpkgs/nixos-unstable#ponysay" echo "Hello Nix" | nix run "github:NixOS/nixpkgs/nixos-unstable#ponysay"
```
# 这条命令的作用是使用 zero-to-nix 这个 flake 中名 `devShells.example` 的 outptus 来创建一个开发环境,
# 然后在这个环境中打开一个 bash shell。
nix develop "github:DeterminateSystems/zero-to-nix#example"
# 除了使用远程 flake uri 之外,你也可以使用当前目录下的 flake 来创建一个开发环境。 ## `nix run``nix shell` 的常见用途
mkdir my-flake && cd my-flake
# 通过模板初始化一个 flake
nix flake init --template "github:DeterminateSystems/zero-to-nix#javascript-dev"
# 使用当前目录下的 flake 创建一个开发环境,并打开一个 bash shell
nix develop
# 或者如果你的 flake 有多个 devShell 输出,你可以指定使用名为 example 的那个
nix develop .#example
# 构建 `nixpkgs` flake 中的 `bat` 这个包 那显然就是用来跑些临时命令,比如说我在新 NixOS 主机上恢复环境,但是还没有装 Git我可以直接用如下命令临时使用 Git 克隆我的配置仓库:
# 并在当前目录下创建一个名为 `result` 的符号链接,链接到该构建结果文件夹。
mkdir build-nix-package && cd build-nix-package ```bash
nix build "nixpkgs#bat" nix run nixpkgs#git clone git@github.com:ryan4yin/nix-config.git
# 构建一个本地 flake 和 nix develop 是一样的,不再赘述 ```
或者也可以这样:
```bash
nix shell nixpkgs#git
git clone git@github.com:ryan4yin/nix-config.git
``` ```
[New Nix Commands]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix.html [New Nix Commands]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix.html