私のスクリプトがログインシェルとして機能しないのはなぜですか?

私のスクリプトがログインシェルとして機能しないのはなぜですか?

私が設計しているデスクトップ環境用のシェルを作成しようとしていますが、設定されたZshだけですが、ログインシェルならどのように渡すべきか混乱します。

これは私のスクリプトです。

#!/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

問題は$0、常にログインシェルではないように見えることです/bin/tiles-shell。いつ始まると思いますか?-ログインシェルでなければなりませんか?

答え1

以前の値はShebangメカニズムによって消去されますargv[0]。カーネルはそれをインタプリタのパスに置き換えます。

ファイルからスクリプトを実行すると、シェルは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

ログインシェルをスクリプトとして使用するには、ログインシェル専用スクリプトとして作成します。

答え2

Gilesの答えに応じてバイナリにし、動作します。

#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    putenv("ZDOTDIR=/etc/tiles/zsh");
    execv("/usr/bin/zsh", argv);
}

関連情報