Search code examples
nixnixos

Why does `runScript =` in `buildFHSUserEnv` stop after first line when using two single quotes?


Running the below shell.nix using nix-shell ./shell.nix gives the expected output:

{ pkgs ? import <nixpkgs> {} }:

(pkgs.buildFHSUserEnv {
  name = "test";
  runScript = "
    echo one
    echo two
  ";
}).env
one
two

as expected.

But changing the double quotes to two single quotes only seems to execute the first line of runScript:

{ pkgs ? import <nixpkgs> {} }:

(pkgs.buildFHSUserEnv {
  name = "test";
  runScript = ''
    echo one
    echo two
  '';
}).env
one

This is strange, since both quoting styles do evaluate to multi-line strings with all the lines I entered:

$ nix-instantiate --eval -                                                                                                                                                                                          
"
  first line
  second line
"
"\n  first line\n  second line\n"
$ nix-instantiate --eval -                                                                                                                                                                                               
''
  first line
  second line
''
"first line\nsecond line\n"

Solution

  • runScript isn't treated as a proper bash script, but is rather pasted directly after the beginning of an exec statement.

    The generated code becomes either

    exec
    echo one
    echo two
    

    or

    exec echo one
    echo two
    

    because '' removes the starting newline.

    exec with no arguments is a no-op in bash, so the first example happens to behave as expected; but exec echo one replaces the shell interpreter by an echo one process, which is not what you intended.

    Seems like the runScript parameter should be deprecated and replaced by two optional ones which are self-explanatory, unless this behavior is caused by a recent change, which would make it a regression (bug).