Chris Stryczynski
Chris Stryczynski

Reputation: 33931

NixOS service systemd unit's $PATH does not contain expected dependency

I have the following definition:

  hello123 = 
    (pkgs.writeScriptBin "finderapp" ''
      #!${pkgs.stdenv.shell}
      # Call hello with a traditional greeting 
      ls ${pkgs.ffmpeg-full}/bin/ffmpeg

      ffmpeg --help

      echo hello
    ''
    );

And the service:

  systemd.services = {
    abcxyz = {
      enable = true;
      description = "abcxyz";
      serviceConfig = {
        WorkingDirectory = "%h/temp/";
        Type      = "simple";
        ExecStart = "${hello123}/bin/finderapp";
        Restart   = "always";
        RestartSec   = 60;
      };
      wantedBy = [ "default.target" ];
    };
  };

However, this seems to fail being able to execute ffmpeg:

Jul 10 19:47:54 XenonKiloCranberry systemd[1]: Started abcxyz.
Jul 10 19:47:54 XenonKiloCranberry finderapp[10042]: /nix/store/9yx9s5yjc6ywafadplblzdfaxqimz95w-ffmpeg-full-4.2.3/bin/ffmpeg
Jul 10 19:47:54 XenonKiloCranberry finderapp[10042]: /nix/store/bxfwljbpvl21wsba00z5dm9dmshsk3bx-finderapp/bin/finderapp: line 5: ffmpeg: command not found
Jul 10 19:47:54 XenonKiloCranberry finderapp[10042]: hello

Why is this failing? I assume it's correctly getting ffmpeg as a runtime dependency (verified with nix-store -q --references ...) as stated in another question here: https://stackoverflow.com/a/68330101/1663462


If I add a echo $PATH to the script, it outputs the following:

Jul 10 19:53:44 XenonKiloCranberry finderapp[12011]: /nix/store/x0jla3hpxrwz76hy9yckg1iyc9hns81k-coreutils-8.31/bin:/nix/store/97vambzyvpvrd9wgrrw7i7svi0s8vny5-findutils-4.7.0/bin:/nix/store/srmjkp5pq8c055j0lak2hn0ls0fis8yl-gnugrep-3.4/bin:/nix/store/p34p7ysy84579lndk7rbrz6zsfr03y71-gnused-4.8/bin:/nix/store/vfzp1mavwiz5w3v10hs69962k0gwl26c-systemd-243.7/bin:/nix/store/x0jla3hpxrwz76hy9yckg1iyc9hns81k-coreutils-8.31/sbin:/nix/store/97vambzyvpvrd9wgrrw7i7svi0s8vny5-findutils-4.7.0/sbin:/nix/store/srmjkp5pq8c055j0lak2hn0ls0fis8yl-gnugrep-3.4/sbin:/nix/store/p34p7ysy84579lndk7rbrz6zsfr03y71-gnused-4.8/sbin:/nix/store/vfzp1mavwiz5w3v10hs69962k0gwl26c-systemd-243.7/sbin

Or these paths basically:

/nix/store/x0jla3hpxrwz76hy9yckg1iyc9hns81k-coreutils-8.31/bin
/nix/store/97vambzyvpvrd9wgrrw7i7svi0s8vny5-findutils-4.7.0/bin
/nix/store/srmjkp5pq8c055j0lak2hn0ls0fis8yl-gnugrep-3.4/bin
/nix/store/p34p7ysy84579lndk7rbrz6zsfr03y71-gnused-4.8/bin
/nix/store/vfzp1mavwiz5w3v10hs69962k0gwl26c-systemd-243.7/bin
/nix/store/x0jla3hpxrwz76hy9yckg1iyc9hns81k-coreutils-8.31/sbin
/nix/store/97vambzyvpvrd9wgrrw7i7svi0s8vny5-findutils-4.7.0/sbin
/nix/store/srmjkp5pq8c055j0lak2hn0ls0fis8yl-gnugrep-3.4/sbin
/nix/store/p34p7ysy84579lndk7rbrz6zsfr03y71-gnused-4.8/sbin
/nix/store/vfzp1mavwiz5w3v10hs69962k0gwl26c-systemd-243.7/sbin

Which shows that ffmpeg is not in there.

Upvotes: 2

Views: 3113

Answers (2)

Robert Hensing
Robert Hensing

Reputation: 7369

In addition to the previous answers

  • not using PATH
  • adding to PATH via systemd config

you can add it to the PATH inside the wrapper script, making the script more self-sufficient and making the extended PATH available to subprocesses, if ffmpeg or any other command needs it (probably not in this case).

The ls command has no effect on subsequent commands, like it shouldn't.

What you want is to add it to PATH:

  hello123 = 
    (pkgs.writeScriptBin "finderapp" ''
      #!${pkgs.stdenv.shell}
      # Call hello with a traditional greeting 
      PATH="${pkgs.ffmpeg-full}/bin${PATH:+:${PATH}}"

      ffmpeg --help

      echo hello
    ''
    );

The part ${PATH:+:${PATH}} takes care of the : and pre-existing PATH, if there is one. The simplistic :${PATH} could effectively add . to PATH when it was empty, although that would be rare.

Upvotes: 4

Chris Stryczynski
Chris Stryczynski

Reputation: 33931

I don't think this is the most elegant solution as the dependencies have to be known in the service definition instead of the package/derivation, but it's a solution none the less.

We can add additional paths with path = [ pkgs.ffmpeg-full ];:

abcxyz = {
  enable = true;
  description = "abcxyz";
  path = [ pkgs.ffmpeg-full ];
  serviceConfig = {
    WorkingDirectory = "%h/temp/";
    Type      = "simple";
    ExecStart = "${hello123}/bin/finderapp";
    Restart   = "always";
    RestartSec   = 60;
  };
  wantedBy = [ "default.target" ];
};

Upvotes: 5

Related Questions