NixOS 服务 systemd 单元的 $PATH 不包含预期的依赖项

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

我的定义如下:

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

      ffmpeg --help

      echo hello
    ''
    );

和服务:

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

但是,这个好像无法执行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

为什么会失败?我假设它正确地将 ffmpeg 作为运行时依赖项(使用 nix-store -q --references ... 验证),如此处另一个问题所述:


如果我在脚本中添加 echo $PATH,它会输出以下内容:

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

或者基本上是这些路径:

/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

这表明 ffmpeg 不在其中。

我不认为这是最优雅的解决方案,因为依赖项必须在服务定义中而不是 package/derivation 中已知,但它是一个解决方案 none 更少。

我们可以添加额外的路径 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" ];
};

除了之前的回答

  • 不使用PATH
  • 通过 systemd 配置添加到 PATH

您可以将它添加到包装脚本内的 PATH,使脚本更加自给自足,并使扩展的 PATH 可用于子进程,如果 ffmpeg 或任何其他命令需要它(在这种情况下可能不是。

ls 命令对后续命令没有影响,就像它不应该那样。

你要的是加到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
    ''
    );

${PATH:+:${PATH}} 部分负责 : 和先前存在的 PATH,如果有的话。简单化的 :${PATH} 可以在 PATH 为空时有效地将 . 添加到 PATH,尽管这种情况很少见。