我正在尝试为我正在设计的桌面环境制作一个 shell,它只是一个配置好的 Zsh,并且我对如何传递它是否是登录 shell 感到困惑。
这是我的脚本:
#!/bin/sh
case "$0" in
-*) ZDOTDIR=/etc/tiles/zsh exec zsh -l "$@";;
*) ZDOTDIR=/etc/tiles/zsh exec zsh "$@";;
esac
我已将其安装到/bin/tiles-shell
,将该路径添加到/etc/shells
,并将其设为我的外壳chsh
。
问题是它从来都不是登录 shell,因为$0
似乎总是/bin/tiles-shell
。我认为它会从什么时候开始,-
它应该是一个登录外壳?
答案1
shebang 机制会擦除 的旧值argv[0]
:内核将其替换为解释器的路径。
从文件运行脚本时,shell 不会公开argv[0]
as的值。是脚本文件的名称。我不认为 zsh通过任何其他接口公开它。$0
$0
argv[0]
演示脚本(适用于Linux):
#!/bin/zsh
echo "argv[0]=$(</proc/$$/cmdline tr \\0 \\n | head -n 1)"
echo "\$0=$0"
输出:
% ARGV0=foo zsh -c "$(cat a)"
argv[0]=foo
$0=foo
% ARGV0=foo zsh ./a
argv[0]=foo
$0=./a
% ARGV0=foo ./a
argv[0]=/bin/zsh
$0=./a
如果您确实希望登录 shell 成为一个脚本,请将其设为专用于登录 shell 的脚本。
答案2
在贾尔斯的回答之后,我将其制作为二进制文件并且它可以工作。
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
putenv("ZDOTDIR=/etc/tiles/zsh");
execv("/usr/bin/zsh", argv);
}