【发布时间】:2021-06-26 16:53:38
【问题描述】:
如果我想自动“包装”一个程序(以便向其中添加一些环境变量),一种解决方案是将程序重命名为myscript-wrapped,并使用以下内容创建一个新文件myscript内容:
#/usr/bin/env bash
export PATH=/my/new/path
exec -a "$0" "myscript-wrapped" "$@"
-a "$0" 用于确保myscript-wrapped 的第一个参数是myscript 而不是myscript-wrapped,"$@" 用于转发参数。
如果myscript-wrapped 是二进制文件,那么一切正常,即它认为第一个参数是myscript。但如果myscript-wrapped 是一个脚本(bash、python、...),例如:
#!/usr/bin/env bash
echo "my name is $0"
然后这会惨遭失败:我得到输出 my name is myscript-wrapped 而不是 my name is myscript。我猜这是因为间接级别的原因:myscript 调用bash,然后bash 调用myscript-wrapped。
避免该问题的最佳方法是什么?如果脚本语言足够好,一种解决方案是编辑脚本 myscript-wrapped 并在开头添加一行 BASH_ARGV0="myscript",但这需要一个相当新的 bash 版本(至少 5,我还在运行我的系统上的第 4 版)。该解决方案的第二个问题是它非常特定于语言,我们需要为任何语言编写不同的解决方案。有更好的主意吗?如果需要,我也很乐意将 myscript 替换为一些已编译的 C。
我的用例是我想改进 Nix 包装器(Nix 包管理器使用大量包装器来确保纯度/确定性)。
-- 编辑 1--
我想我正在尝试做一些不可能的事情。我从https://man7.org/linux/man-pages/man2/execve.2.html 看到(“解释器脚本”部分):
请注意,无法获取传递给 execve() 调用的 argv[0] `
所以我想最好的办法是,当要包装的东西是 bash 脚本时,直接在开头附加“导出”的东西......不是很便携,但我们无法得到更好的东西。
我想如果有人愿意依赖不同的 GLIBC,可以直接修改 GLIBC 以自动搜索二进制/脚本旁边的任何特殊命名的文件,以填充环境变量.. . 但这是一个相当大的变化,可能很难维护^^(并且在 Nix 的范围之外没有多大意义)。
-- 编辑 2--
对于脚本,我终于为我的包装器问题找到了一个更简单的解决方案,它适用于脚本(二进制文件无论如何都不会遇到同样的问题,所以我猜旧的解决方案对它们来说已经足够好了)。请参阅下面的答案。
【问题讨论】:
标签: python bash arguments command-line-arguments