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?
EDIT: Wait, a nix-shell is only for the buildInputs… That logg worked must’ve been a local artifact on my machine.
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’
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.
[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)
[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
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.
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.