Shell Scripts: Difference between revisions

imported>Milahu
+ Packaging example
fix link
 
(7 intermediate revisions by one other user not shown)
Line 14: Line 14:
       '';
       '';
     };
     };
</syntaxHighlight>
== External builder.sh script ==
Longer bash scripts are usually stored as external script files, and called from Nix:
<syntaxHighlight lang="nix">
# default.nix
{
  outputTxtDrv = stdenv.mkDerivation rec {
    name = "output.txt";
    # disable unpackPhase etc
    phases = "buildPhase";
    builder = ./builder.sh;
    nativeBuildInputs = [ coreutils jq ];
    PATH = lib.makeBinPath nativeBuildInputs;
    # only strings can be passed to builder
    someString = "hello";
    someNumber = builtins.toString 42;
    someJson = builtins.toJSON { dst = "world"; };
  };
}
</syntaxHighlight>
<syntaxHighlight lang="bash">
# builder.sh
echo "$someString $(echo "$someJson" | jq -r '.dst') $someNumber" >$out
</syntaxHighlight>
See also
* [https://github.com/NixOS/nixpkgs/issues/23099 make a derivation with no source]
* [https://nixos.org/guides/nix-pills/working-derivation.html Nix Pills: Chapter 7. Working Derivation]
=== runCommand + builder.sh ===
Instead of <code>stdenv.mkDerivation</code>, we can also use <code>runCommand</code> to call an external bash script:
<syntaxHighlight lang="nix">
# default.nix
{
  outputTxtDrv = runCommand "output.txt" {
    nativeBuildInputs = [ coreutils jq ];
    # only strings can be passed to builder
    someString = "hello";
    someNumber = builtins.toString 42;
    someJson = builtins.toJSON { dst = "world"; };
  } (builtins.readFile ./builder.sh);
}
</syntaxHighlight>
</syntaxHighlight>


Line 48: Line 97:
         --prefix PATH : ${lib.makeBinPath [ bash subversion ]}
         --prefix PATH : ${lib.makeBinPath [ bash subversion ]}
     '';
     '';
   };
   }
</syntaxHighlight>
 
<code>wrapProgram</code> will move the original script to <code>.github-downloader.sh-wrapped</code>
 
=== Command not found ===
 
for example, the script throws the error <code>svn: command not found</code>, because the dependency <code>subversion</code> is missing.
 
when a command is missing, you can use <code>nix-locate</code> to find the package name. for example, the <code>stat</code> command:
 
<syntaxHighlight lang="console">
$ nix-locate bin/stat | grep 'bin/stat$'
coreutils.out                                        0 s /nix/store/vr96j3cxj75xsczl8pzrgsv1k57hcxyp-coreutils-8.31/bin/stat
</syntaxHighlight>
</syntaxHighlight>


when the dependency <code>subversion</code> is missing, the script throws the error <code>svn: command not found</code>
== Debugging embedded scripts ==
 
When a bash script fails, it prints only an error message, but no code location.
 
To trace commands and line numbers, we can use
 
<syntaxHighlight lang="nix">
# test-trace.nix
{ runCommand, coreutils }:
  runCommand "output.txt" {
    nativeBuildInputs = [ coreutils ];
  } ''
    # line 5 in nix file = line 1 in bash script -> offset 4
    PS4='+ Line $(expr $LINENO + 4): '
    set -o xtrace # print commands
 
    echo hello >$out # line 9 in nix file
 
    set +o xtrace # hide commands
  ''
</syntaxHighlight>


<code>wrapProgram</code> will move the original script to <code>.github-downloader.sh-wrapped</code>
<syntaxHighlight lang="console">
$ nix-build -E 'with import <nixpkgs> { }; callPackage ./test-trace.nix { }'
this derivation will be built:
  /nix/store/2v5biwny8plpyk2bv6cfr41ppp0a1i4k-output.txt.drv
building '/nix/store/2v5biwny8plpyk2bv6cfr41ppp0a1i4k-output.txt.drv'...
++ Line 9: echo hello
++ Line 11: set +o xtrace
/nix/store/ppidmnpd5m762x9kqj8jd3g7df7dknrz-output.txt
</syntaxHighlight>


== Posix Shell ==
== Posix Shell ==
Line 64: Line 154:


* [https://nixos.org/manual/nixpkgs/stable/#ssec-stdenv-functions Shell functions section in the Nixpkgs manual]
* [https://nixos.org/manual/nixpkgs/stable/#ssec-stdenv-functions Shell functions section in the Nixpkgs manual]
* [https://gist.github.com/travisbhartwell/f972aab227306edfcfea nix-shell and Shebang Lines]
* [https://ertt.ca/nix/shell-scripts/ Shell Scripts with Nix]