login shell

2020-05-20T19:53:05+08:00

login shell 本意很简单,就是用户登录系统之后进入的 shell,比如从 SSH 登陆,自然而然 login shell 进程将会是该用户的第一个进程。但桌面环境下 login shell 就没意义了,用户登陆之后运行的不是 shell,而是窗口管理器。

macOS Terminal.app 为什么还用 login shell?

上文提到桌面环境 login shell 失去了意义,但是 macOS Terminal.app 默认依旧使用 login shell(iTerm 似乎模仿了这个做法),不知道为什么?

我首先想到的理由是 login shell 和 non-login shell 的初始化配置不同,比如 login bash 执行 profile 而 nonlogin bash 执行 bashrc,并且 macOS 偏好 profile。但再想一想这个猜测站不住脚。

bash - Why are interactive shells on OSX login shells by default? - Unix & Linux Stack Exchange 问题底下也有没我满意的答案,或许只有 Apple 自己才知道。

shell 自身如何区分 login 和 non-login?

启动 shell 的程序决定了 login 还是 non-login shell,比如 Terminal.app 默认用 login shell,而 Emacs M-! 用 non-login shell。

调用程序通过在 ARGV[0] 前加一个 -(短横)来告知 shell 这是一个 login shell,比如:

// login.c
#include <unistd.h>

int
main(int argc, char* argv[])
{
    execl("./bash", "-bash", NULL);
}
// bash.c
#include <stdio.h>

int
main(int argc, char* argv[])
{
    printf("$0 = %s, ", argv[0]);
    if (argv[0][0] == '-')
        printf("login shell\n");
    else
        printf("non-login shell\n");
}

演示:

~ $ cc bash.c -o bash
~ $ cc login.c -o login
~ $ ./login
$0 = -bash, login shell
~ $