You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在NixOS中创建systemd服务模板?%u占位符未展开如何解决

问题原因

你遇到的%u不展开的问题核心是:NixOS提供的systemd.services.<name>.script是语法糖配置,它会自动将你写的脚本内容打包成一个存放在Nix Store中的独立shell脚本,再自动把ExecStart指向这个生成的脚本。而systemd的模板占位符(如%u、%i等)只会解析ExecStart行本身的内容,不会解析被调用的脚本内部的字符串,所以你写在script里的%u会作为静态文本保留,不会被展开。

规范解决方案

方案1:直接定义ExecStart(适合简单逻辑)

不需要使用script字段,直接在serviceConfig中定义ExecStart,让占位符直接出现在ExecStart行中,systemd就可以正常解析:

systemd.services."myuser@" = {
  serviceConfig = {
    Type = "oneshot";
    # 直接把占位符写在ExecStart行内
    ExecStart = "${pkgs.bash}/bin/bash -c 'echo Hi, %u'";
  };
};

方案2:将占位符作为参数传给独立脚本(适合复杂逻辑)

如果你的服务逻辑比较复杂,不想都堆在ExecStart行里,可以先把逻辑写成独立脚本,再在ExecStart调用脚本时把占位符作为参数传入:

let
  # 先编写你的业务脚本,用位置变量接收参数
  myServiceScript = pkgs.writeScriptBin "my-user-service" ''
    #!/${pkgs.bash}/bin/bash
    set -e
    # $1 对应传入的%u展开后的值
    echo Hi, $1
    # 其他复杂逻辑写在这里
  '';
in {
  systemd.services."myuser@" = {
    serviceConfig = {
      Type = "oneshot";
      # 调用脚本时传入systemd占位符,由systemd完成展开后再传给脚本
      ExecStart = "${myServiceScript}/bin/my-user-service %u";
    };
  };
}

补充说明

systemd模板服务常用的占位符可以按需选择:

  • %i:模板实例名,即@后面的字符串,比如myuser@foo.service中%i的值为foo
  • %u:服务运行的用户的用户名
  • %h:服务运行的用户的家目录路径

内容的提问来源于stack exchange,提问作者l0b0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 07:57:03