I know what is a login shell and the difference between a login shell and a non-login shell.

But what puzzles me is how it is invoked. It is said that a login shell is invoked with a - as argument 0.

How can we pass an argument to a shell that is being invoked, then argument 0 is the name of the shell itself?

# -bash 
-bash: -bash: command not found

Okay nevermind

# bash --login
# echo $0
# bash

I still don't see a -bash.

Only when I SSH in, then I am able to see a -bash when issuing echo $0. But back to my original question,

  1. how does Unix/Linux create a login shell ?
  2. What is the "thing" that creates a login shell during the login process? If it is a "login" process that invokes the bash shell during login, how does it pass argument 0 as - to the bash shell?

Programs like SSH, sudo, su, etc., start the shell using the exec family of system calls. And these system calls allow the calling program to specify every argument, including the function. For example, using sudo to start a login shell:

$ strace -fe execve -o sudo.log sudo -i
root:~ $ echo $0
root:~ $ logout
$ grep bash sudo.log 
19124 execve("/bin/bash", ["-bash"], [/* 31 vars */]) = 0
19140 execve("/bin/ls", ["ls", "/etc/bash_completion.d"], [/* 40 vars */]) = 0

As can be seen in the first execve call, the array of arguments passed to bash is just ["-bash"] - so argument zero is -bash.


This is easy to replicate with zsh, which allows the appropriate argument to the exec(3) call to be specified via ARGV0:

% ARGV0=-bash bash
-bash-4.1$ ps o cmd --pid=$$
-bash-4.1$ exit
% ARGV0=imnotaduck bash
$ ps o cmd --pid=$$
$ exit

In C, as done by login(1), the code would run something along the lines of:

execlp("/usr/local/bin/bash", "-bash", ..., (char *) 0)

to insert the hyphen into the process name. This can be confirmed by either running login and bash under strace, or by inspecting the source code for login.


To login as user usertest, do (being root) :

root:~# login usertest
usertest:~$ echo $0
usertest:~$ exit
root:~# _

That's the formal way in which an user logs in.

Of course, you could allways execute a command for which it's $0 is changed:

bash -c 'echo "hello"; echo $0;' mylogthisshell

Which could allways have an starting dash

bash -c 'echo "hello"; echo $0;' -mylogthisshell

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.