Can't call a program `log`

For some reason, if I call a writeShellApplication executable log, it doesn’t end up in PATH when I put it in environment.systemPackages.

UPDATE: See here for a VM setup to reproduce, the below nix-shell example is not the problem here.


Initial post (which is not quite the problem, try the VM!)

Consider this simple log.nix:

(import <nixpkgs> { }).writeShellApplication { 
  name = "log";                                
  text = "echo Hi!";                           
}                                              
🐟 ❯ nix-shell log.nix --run log
/tmp/nix-shell-2943114-0/rc: line 3: log: command not found

When I change the name to logg (or anything else, really), it works:

❌127 🐟 ❯ nix-shell log.nix --run logg
Hi!

I tried it in a VM, on a Raspberry Pi 4, on my Desktop, all the same.

Here is a one-liner to test:

yann in yann-desktop-nixos in …/nixconfig on  main [$!] 
🐟 ❯ nix-shell -E 'with import <nixpkgs> {}; writeShellApplication {name="log";text="echo Hi!";}' --run log
/tmp/nix-shell-2968751-0/rc: line 3: log: command not found
yann in yann-desktop-nixos in …/nixconfig on  main [$!] 
❌127 🐟 ❯ nix-shell -E 'with import <nixpkgs> {}; writeShellApplication {name="logg";text="echo Hi!";}' --run logg
Hi!

What in the actual heck? :joy:

EDIT: Wait, a nix-shell is only for the buildInputs… :expressionless: That logg worked must’ve been a local artifact on my machine.

1 Like

I can’t reproduce that:

$ nix-shell -E 'with import <nixpkgs> {}; writeShellApplication {name="logg";text="echo Hi!";}' --run logg
/tmp/nix-shell-829657-0/rc: line 3: logg: command not found

However:

$ nix-shell -p 'with import <nixpkgs> {}; writeShellApplication {name="log";text="echo Hi!";}' --run log
Hi!

(note -p vs -E)

1 Like

That -p and -E difference was a good hint, thanks. However in my VM here (of which I can’t share the entirety) there’s still the weirdness that log won’t work, but everything else… Super weird.

Weird indeed. One thing to try might be to nix-shell -p 'with import <nixpkgs> {}; writeShellApplication {name="log";text="echo Hi!";}' --run "which log", to verify whether the problem is ‘log isn’t found on the PATH at all’ or ‘log is found on the PATH but its interpreter cannot be found’

1 Like

I’d really like to make a VM to reproduce this, but it won’t let me.

Here’s a VM setup to reproduce:

# vm.nix
{ pkgs, config, ... }: {
  users.users.me = {
    isNormalUser = true;
    initialPassword = "asdf";
  };
  services.getty.autologinUser = "me";
  environment.systemPackages = with pkgs;
    let
      myProgram = writeShellApplication {
        name = "log";
        text = "echo Hi!";
      };
    in [ myProgram ];
  system.stateVersion = "nixos-24.05";
}
nix-build '<nixpkgs/nixos>' -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/24.05.tar.gz -I nixos-config=vm.nix -A vm && rm -rf *.qcow && result/bin/run-nixos-vm

It opens QEMU, throws a ridiculous amount of errors about ‘Usespace OOM killer failed’ or something, then fails at autologin (just blinking cursor). Even without autologin, the configured user can’t login.

Any idea how to get it working?

EDIT: rm -rf *.qcow2

May I have a screenshot of these errors, please?

Ah never mind, it was again an error because of the old .qcow2 vm state file :expressionless:

This makes a working VM:

nix-build '<nixpkgs/nixos>' -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/24.05.tar.gz -I nixos-config=vm.nix -A vm && rm -rf *.qcow2 && result/bin/run-nixos-vm

Try removing the nixos.qcow2 file - this is likely a disk image left over from a previous attempt breaking things.

I indeed now see your problem of the program not appearing in /run/current-system/sw/bin when it’s called log, interesting!

1 Like

If I name the program log:

[me@nixos:~]$ log
log: command not found

[me@nixos:~]$ which log
which: no log in (/run/wrappers/bin:/home/me/.nix-profile/bin:/nix/profile/bin:/home/me/.local/state/nix/profile/bin:/etc/profiles/per-user/me/bin:/nix/var/ni)

If I name the program logg:

[me@nixos:~]$ logg
Hi!

So this /bin/log executable doesn’t end up in /var/run/current-system/sw?

Exactly. With name = "log";:

[me@nixos:~]$ which log
which: no log in (/run/wrappers/bin:/home/me/.nix-profile/bin:/nix/profile/bin:/home/me/.local/state/nix/profile/bin:/etc/profiles/per-user/me/bin:/nix/var/ni)

[me@nixos:~]$ ls /run/current-system/sw/bin/log
ls: cannot access '/run/current-system/sw/bin/log': No such file or directory

With name = "logg";:

[me@nixos:~]$ which logg
/run/current-system/sw/bin/logg

Traced it to the call to pkgs.buildEnv that populates the system path, the input has log but the output doesn’t.

Inspecting the implementation made it very obvious where this exclusion is happening: nixpkgs/pkgs/build-support/buildenv/builder.pl at 6f2cc8828aec0f470dd69581d95cb8d54439b707 · NixOS/nixpkgs · GitHub

EDIT: looks like this was originally intended to filter out *log names, but it regressed at some point 14 years ago and stayed like that since then: * First figure out what symlinks need to be created, then create · NixOS/nixpkgs@a6fcf45 · GitHub

5 Likes

Congratulations, @nobodyinperson . Would you be comfortable reporting an issue?

Yeah maybe I find the time later to wrap this up in an issue, but it might take some time.

What would be an ad-hoc solution?

I currently use

programs.bash.shellAliases = { log = "${getExe log-cmd}"; };

But aliases have their own downsides, e.g. watch log doesn’t see it, watch bash -c 'log ...' neigther, it’s just unergonomic.

For some weird reason, the following manual adjustment to PATH also doesn’t work (echo $PATH in a fresh shell doesn’t even contain that adjustment, although it lands in /etc/profile):

programs.bash.shellInit = ''                                                        
  # temporary fix for the bug that programs called 'log' don't land in PATH in NixOS
  # https://discourse.nixos.org/t/cant-call-a-program-log/49868                     
  export PATH="${makeBinPath [log-cmd "$PATH"]}"                                    
'';                                                                                 

Any other ideas? I just want the log command to be available globally…

I guess overriding pkgs.buildEnv would be the right thing to do, at least for this one package to prevent a mass rebuild or something, but I’m not really sure how to do that.

I’d be fine for now with a PATH hack.

I solved it with home-manager for now:

    programs.bash = {
      enable = true;
      bashrcExtra = ''
        # temporary fix for the bug that programs called 'log' don't land in PATH in NixOS
        # https://discourse.nixos.org/t/cant-call-a-program-log/49868
        export PATH="${pkgs.log-cmd}/bin:$PATH"
      '';
    };

Works with watch log or bash -c 'log ...', so good enough. :+1:

1 Like

It goes even further back (18y) and has been there ever since:

It feels like this was supposed to filter out directories called log, not necessarily files called log? :thinking: What programs produce files called log?