nix-shell --command doesn't work for FHS environments

Created on 18 Sep 2017  路  4Comments  路  Source: NixOS/nix

I'm scripting a tedious process I have to do to get a build for a project.The project lives in a FHS built by buildFHSUserEnv. It would be very convenient if I could pass commands to be executed in the chroot like it works with regular nix-shell environments, e.g.

nix-shell default.nix --command "make -j4 && cp some_file other_place"

Unfortunately this doesn't seem to be possible.

Most helpful comment

The way I solve this problem is to make runScript an argument, then you can supply your command to that argument. e.g.

# fhs.nix
{
  pkgs ? import <nixpkgs> {},
  # This allows us to provide a command to run via `--argstr run COMMAND`.
  run ? "bash"
}:
with pkgs; (buildFHSUserEnv {
  name = "fhs";
  targetPkgs = pkgs: with pkgs; [
    curl
    git
    gnumake
  ];
  runScript = "${run}";
  profile = ''
    export SSL_CERT_FILE=${cacert}/etc/ssl/certs/ca-bundle.crt
    export GIT_SSL_CAINFO="$SSL_CERT_FILE"
    export LANG=C.UTF-8
  '';
}).env

You can execute your command with:

$ nix-shell --pure --argstr run "sh -c 'make -j4 && cp some_file other_place'" fhs.nix

I tend to wrap it up in a little script, fhs:

#!/usr/bin/env bash

set -euo pipefail

fhs="./fhs.nix"

function run {
  nix-shell --pure --argstr run "$*" "${fhs}"
}

if [[ $# -eq 0 ]]; then
  run bash
else
  run "$@"
fi

Usage is then:

$ ./fhs # for a bash shell in the FHS
$ ./fhs echo hi # do execute command in FHS

All 4 comments

A nix-shell with a buildFHSUserEnv does not behave like a regular nix-shell at all, unfortunately.
Things like --command and --run are simply broken, even simple things like using an interactive bash are not possible.
Putting bashInteractive into the targetPkgs doesn't change anything.

Hi folks, just wondering if there's any workaround/solution to this yet?

If you set runScript = "bash", you can run nix-shell and you get a shell in the environment.
Still doesn't work with --run but it'll give you a shell.
If you only ever want to run one command, you can put that as your runScript.

The way I solve this problem is to make runScript an argument, then you can supply your command to that argument. e.g.

# fhs.nix
{
  pkgs ? import <nixpkgs> {},
  # This allows us to provide a command to run via `--argstr run COMMAND`.
  run ? "bash"
}:
with pkgs; (buildFHSUserEnv {
  name = "fhs";
  targetPkgs = pkgs: with pkgs; [
    curl
    git
    gnumake
  ];
  runScript = "${run}";
  profile = ''
    export SSL_CERT_FILE=${cacert}/etc/ssl/certs/ca-bundle.crt
    export GIT_SSL_CAINFO="$SSL_CERT_FILE"
    export LANG=C.UTF-8
  '';
}).env

You can execute your command with:

$ nix-shell --pure --argstr run "sh -c 'make -j4 && cp some_file other_place'" fhs.nix

I tend to wrap it up in a little script, fhs:

#!/usr/bin/env bash

set -euo pipefail

fhs="./fhs.nix"

function run {
  nix-shell --pure --argstr run "$*" "${fhs}"
}

if [[ $# -eq 0 ]]; then
  run bash
else
  run "$@"
fi

Usage is then:

$ ./fhs # for a bash shell in the FHS
$ ./fhs echo hi # do execute command in FHS
Was this page helpful?
0 / 5 - 0 ratings