Creating udev rule fails (dependency issue)

Hi :wave: ,

I am trying to create an udev rule to run a script when certain hardware is detected. So I added an udev rule with:

  services.udev.extraRules = lib.mkMerge [
    # Run dialog script for desktop, if new sound device added
    ''ACTION=="add",	SUBSYSTEM=="sound"	RUN+="/etc/sound-helper.sh"''
  ];

  environment.etc."sound-helper.sh" = {
    source = ../scripts/sound-helper.sh;
    mode = "0755";
  };

Looks like it doesn’t evaluate the environment.etc part first, so I am getting following error on activation:

...
Checking that all programs called by absolute paths in udev rules exist... FAIL
/etc/sound-helper.sh is called in udev rules but is not executable or does not exist

What am I missing? I am not sure how to hint the nix about ordering by “requiring” the file first or something. Or is it just order-in-the-file issue so I should declare environment.etc above services.udev line? (this wasn’t the case :grinning_face_with_smiling_eyes: )

Thanks!

I would try replacing

with:

RUN+="${config.environment.etc."sound-helper.sh"}.target"

maybe that will create a dependency and so the udev rule will be evaluated after the script definition, but I’m not 100% sure.

Thanks for the idea, I thought that would solve it too:

  services.udev.extraRules = lib.mkMerge [
    # Run dialog script for desktop, if new sound device added
    ''ACTION=="add",	SUBSYSTEM=="sound"	RUN+="${config.environment.etc."sound-helper.sh".source.outPath}"''
  ];

But failed with:

error: value is a path while a set was expected

I also tried to escape it with ''${ but it put the string there literally. So I am not still sure.

(using .target still fails and creates: RUN+="sound-helper.sh" as a result, so I tried the outPath)

another edit:
tried the following:

    ''ACTION=="add",	SUBSYSTEM=="sound"	RUN+="${"/etc/" + config.environment.etc."sound-helper.sh".target}"''

which seems to be creating /etc/sound-helper.sh and not creating a dependency. I need to find a way to refer the /nix/store value but couldn’t find a way yet.

If you define the script like

  environment.etc.sound-helper = {
    source = ../scripts/sound-helper.sh;
    mode = "0755";
    target = "sound-helper.sh";
  };

 services.udev.extraRules = lib.mkMerge [
    # Run dialog script for desktop, if new sound device added
    ''ACTION=="add",	SUBSYSTEM=="sound"	RUN+="${config.environment.etc.sound-helper.target}"''
  ];

Does it still fail miserably?

BTW, there’s no need for the script to reside in /etc, you could more simply creating a simple script derivation with pkgs.writeScript and then interpolate that into the RUN+…

Yep, build fails, I caught the generated output and it seems to be:

ACTION=="add",  SUBSYSTEM=="sound"  RUN+="sound-helper"

I think I’ll try the writeScript, thanks.

Yep, was able to redirect to correct script within nix store with writeScript easily. Thanks!