Shell scripts/zh: Difference between revisions
Appearance
Created page with "另见:" |
Created page with "函数 <code>writeShellScript</code> 可用于向 Nix 表达式中添加 Shell 脚本。" Tags: Mobile edit Mobile web edit |
||
| (2 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
<languages/> | <languages/> | ||
函数 <code>writeShellScript</code> 可用于向 Nix 表达式中添加 Shell 脚本。 | |||
<syntaxHighlight lang="nix"> | <syntaxHighlight lang="nix"> | ||
| Line 20: | Line 18: | ||
</syntaxHighlight> | </syntaxHighlight> | ||
< | <span id="External_builder.sh_script"></span> | ||
== | == 外部 builder.sh 脚本 == | ||
较长的 Bash 脚本通常会保存为外部脚本文件,并在 Nix 中调用: | |||
{{file|default.nix|nix|3= | {{file|default.nix|nix|3= | ||
Latest revision as of 18:08, 2 August 2026
函数 writeShellScript 可用于向 Nix 表达式中添加 Shell 脚本。
someBuildHelper = { name, sha256 }:
stdenv.mkDerivation {
inherit name;
outputHashMode = "recursive";
outputHashAlgo = "sha256";
outputHash = sha256;
builder = writeShellScript "builder.sh" ''
echo "hi, my name is ''${0}" # escape bash variable
echo "hi, my hash is ${sha256}" # use nix variable
echo "hello world" >output.txt
'';
};
外部 builder.sh 脚本
较长的 Bash 脚本通常会保存为外部脚本文件,并在 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"; };
};
}
≡︎ builder.sh
jq -r '.dst') $someNumber" >$out
另见:
runCommand + builder.sh
除了使用 stdenv.mkDerivation 之外,还可以通过 runCommand 来调用外部的 Bash 脚本:
❄︎ 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);
}
打包
示例:
# nix-build -E 'with import <nixpkgs> { }; callPackage ./default.nix { }'
{ stdenv
, lib
, fetchFromGitHub
, bash
, subversion
, makeWrapper
}:
stdenv.mkDerivation {
pname = "github-downloader";
version = "08049f6";
src = fetchFromGitHub {
# https://github.com/Decad/github-downloader
owner = "Decad";
repo = "github-downloader";
rev = "08049f6183e559a9a97b1d144c070a36118cca97";
sha256 = "073jkky5svrb7hmbx3ycgzpb37hdap7nd9i0id5b5yxlcnf7930r";
};
buildInputs = [ bash subversion ];
nativeBuildInputs = [ makeWrapper ];
installPhase = ''
mkdir -p $out/bin
cp github-downloader.sh $out/bin/github-downloader.sh
wrapProgram $out/bin/github-downloader.sh \
--prefix PATH : ${lib.makeBinPath [ bash subversion ]}
'';
}
wrapProgram 会将原始脚本移动到 .github-downloader.sh-wrapped。
命令未找到
例如,脚本会抛出错误 svn: command not found,这是因为缺少依赖包 subversion。
当某个命令缺失时,可以使用 nix-locate 来查找对应的软件包名称。例如,stat 命令:
$ nix-locate bin/stat | grep 'bin/stat$'
coreutils.out 0 s /nix/store/vr96j3cxj75xsczl8pzrgsv1k57hcxyp-coreutils-8.31/bin/stat
调试嵌入脚本
当 Bash 脚本执行失败时,它只会输出错误信息,而不会显示出错的代码位置。
要跟踪命令和行号,可以使用
❄︎ 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
''
$ 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
POSIX shell
某些环境(例如基于 BusyBox 的 OpenWRT)仅提供“受限” Shell(使用 sh 而非 bash)
在 NixOS 上,POSIX shells 由软件包 dash 和 posh 提供。