When I add scripts to my nixos-config(flake) I manually guess the runtimeInputs
Is there a way to get a list from nix?
In the example below rsync should be added but there is no error during building.
I’m using a similar setup for python scripts.
{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.ncfg.scripts;
bashScript = name: scriptDependencies: (
pkgs.writeShellApplication {
name = "${name}";
runtimeInputs = scriptDependencies;
text = builtins.readFile ../../scripts/${name}.sh;
}
);
s-helloworld = bashScript "helloworld" (with pkgs; [
coreutils util-linux gnugrep
]);
in {
config = {
environment.systemPackages = with pkgs; [
s-helloworld
];
}
];
}
#!/usr/bin/env bash
lsblk # ok
rsync --help
Hypothetically yeah, practically though it’s pretty tough.
You use ptrace
and monitor read
calls to find a lot of missing deps, and an index to query packages that might satisfy them; but making that a robust solution in the general case is going to be a mountain to climb.
1 Like
This is a lot more complex than it sounds (in part because Shell is a fairly complex ball of strings), but I think you are looking for resholve
and more specifically something like resholve.writeScriptBin
.
resholve will block the build until you provide the dependencies, and then replace the invocations with store paths. Together, these help ensure all of the deps get found and specified. It also keeps them out of your global environment.
4 Likes
I tried:
bashScript = name: scriptDependencies: (
pkgs.resholve.writeScriptBin
"${name}"
{
interpreter = "${pkgs.bash}/bin/bash";
inputs = scriptDependencies;
fake.external = [ "sudo" ];
}
(builtins.readFile ../../scripts/${name}.sh)
);
But how would one handle such errors:
rsync -ah "${og_path}/" "${backup_path}"
> /nix/store/xxxx-nixcfg:455: 'rsync' _might_ be able to execute its arguments, and I don't have any command-specific rules for figuring out if this specific invocation does or not.
ssh -t "root@${remote_ip}" "notify-send 'Rebooting in 3' --urgency normal --expire-time 950" ; sleep 1
> /nix/store/xxxx-nixcfg:532: 'ssh' _might_ be able to execute its arguments, and I don't have any command-specific rules for figuring out if this specific invocation does or not.
nix-collect-garbage -d
> /nix/store/xxxx-nixcfg:312: 'nix-collect-garbage' _might_ be able to execute its arguments, and I don't have any command-specific rules for figuring out if this specific invocation does or not.
nix log:
^_^_^_[resholve context] : invoking resholve with PWD=/build
^_^_^_[resholve context] RESHOLVE_LORE=/nix/store/zrddbgl5ajvlbs1c2cbb40b8cydr3513-more-binlore
^_^_^_[resholve context] RESHOLVE_FAKE='external:'\''sudo'\'''
^_^_^_[resholve context] RESHOLVE_INPUTS=/nix/store/5imadx3sbb1f2gqhxhw5rq5idwqj4mib-coreutils-9.0/bin:/nix/store/xh167z0h1pqpp9nvbz2v0qgyh0rq9l4f-util-linux-2.37.4-bin/bin:/nix/store/nq0l53cjilxvsj2cm6qavn9xmcdvwsvr-openssh-9.0p1/bin:/nix/store/0vk1n9vxiwrpkf6csl6x7z6z624xyc1d-rsync-3.2.3/bin:/nix/store/sylw93hwxdmw3pvwijsw21hrqjxs84is-cryptsetup-2.4.3-bin/bin:/nix/store/fg0a35schqdja6315a4krrdi8cvc9ibc-gnugrep-3.7/bin:/nix/store/74v34rhghgysaq1b9ya2ia9pffki0vgx-syslinux-unstable-20190207/bin:/nix/store/w1q0zcdnsd6g9ic0zfi68m9pgcfqmajq-nix-2.8.1/bin:/nix/store/3ikpw7kg11la74c74bjvml4czsvqv2x9-drvi/bin
^_^_^_[resholve context] RESHOLVE_INTERPRETER=/nix/store/07ln9bxp9k8nds669r24fsywf4d1jlly-bash-5.1-p16/bin/bash
^_^_^_[resholve context] /nix/store/86chbix6qy9x6pbdpjr5fpgiv4hqbc54-resholve-0.8.0/bin/resholve --overwrite /nix/store/5s6634chicrm035n4lgiljlq148vvs1x-nixcfg
nix-collect-garbage -d
^~~~~~~~~~~~~~~~~~~
/nix/store/5s6634chicrm035n4lgiljlq148vvs1x-nixcfg:312: 'nix-collect-garbage' _might_ be able to execute its arguments, and I don't have any command-specific rules for figuring out if this specific invocation does or not.
The ideal solution is to get support for recognizing execable args in all of those commands built into resholve.
That said, all of these specific invokations look fine, so you can just add override lore for them. I am on phone atm so it won’t be easy to type them out, but there’s a section on lore in the readme, and here’s an example:
1 Like
it works:
bashScript = name: scriptDependencies: (
pkgs.resholve.writeScriptBin
"${name}"
{
interpreter = "${pkgs.bash}/bin/bash";
inputs = scriptDependencies;
fake.external = [ "sudo" "ping" "mount" "umount" ];
execer = [
"cannot:${pkgs.gzip}/bin/uncompress"
"cannot:${pkgs.networkmanager}/bin/nmcli"
"cannot:${pkgs.nixos-install-tools}/bin/nixos-generate-config"
"cannot:${pkgs.nixos-install-tools}/bin/nixos-install"
"cannot:${pkgs.nixos-rebuild}/bin/nixos-rebuild"
"cannot:${pkgs.nix}/bin/nix"
"cannot:${pkgs.nix}/bin/nix-collect-garbage"
"cannot:${pkgs.openssh}/bin/ssh"
"cannot:${pkgs.p7zip}/bin/7z"
"cannot:${pkgs.p7zip}/bin/7za"
"cannot:${pkgs.procps}/bin/pkill"
"cannot:${pkgs.rsync}/bin/rsync"
"cannot:${pkgs.sway}/bin/swaymsg"
"cannot:${pkgs.systemd}/bin/systemctl"
"cannot:${pkgs.util-linux}/bin/swapon"
"cannot:${pkgs.wl-clipboard}/bin/wl-copy"
"cannot:${pkgs.wpa_supplicant}/bin/wpa_passphrase"
];
}
(builtins.readFile ../../scripts/${name}.sh)
# pkgs.writeShellApplication {
# name = "${name}";
# runtimeInputs = scriptDependencies;
# text = builtins.readFile ../../scripts/${name}.sh;
# }
);
1 Like