为什么我的脚本不能用作登录 shell?

为什么我的脚本不能用作登录 shell?

我正在尝试为我正在设计的桌面环境制作一个 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$0argv[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);
}

相关内容