2015-01-14
What /etc/shells
is and isn't
In traditional Unix, /etc/shells
has only one true purpose: it
lists programs that chsh
will let you change your shell to (if
it lets you do anything). Before people are tempted to make other
programs use this file for something else, it is important to
understand the limits of /etc/shells
. These include but are
not limited to:
- Logins may have
/etc/passwd
entries that list other shells. For example, back when restricted shells were popular it was extremely common to not list them in/etc/shells
so you couldn't accidentallychsh
yourself into a restricted shell and then get stuck.Some but not all programs have used the absence of a shell from
/etc/shells
as a sign that it is a restricted shell (or not a real shell at all) and they should restrict a user with that shell in some way. Other programs have used different tests, such as matching against specific shell names or name prefixes.(It's traditional for the FTP daemon to refuse access for accounts that do not have a shell that's in
/etc/shells
and so this is broadly accepted. Other programs are on much thinner ice.) - On the other hand, sometimes you can find restricted shells
in
/etc/shells
; a number of systems (Ubuntu and several FreeBSD versions) includerbash
, the restricted version of Bash, if it's installed. - Not all normal shells used in
/etc/passwd
or simply installed on the system necessarily appear in/etc/shells
for various reasons. In practice there are all sorts of ways for installed shells to fall through the cracks. Of course this makes them hard to use as your login shell (since you can'tchsh
to them), but this can be worked around in various ways.For example, our Ubuntu systems have
/bin/csh
and/bin/ksh
(and some people use them as their login shells) but neither are in/etc/shells
. - The (normal and unrestricted) shell someone's actually using isn't
necessarily in either
/etc/shells
or their/etc/passwd
entry. Unix is flexible and easily lets you use$SHELL
and some dotfile hacking to switch basically everything over to running your own personal choice of shell, per my entry on using an alternate shell.(Essentially everything on Unix that spawns what is supposed to be your interactive shell has been clubbed into using
$SHELL
, partly because the code to use$SHELL
is easier to write than the code to look up someone's/etc/passwd
entry to find their official login shell. This feature probably came into Unix with BSD Unix, which was basically the first Unix to have two shells.) - Entries in
/etc/shells
don't necessarily exist. - Entries in
/etc/shells
are not necessarily shells. Ubuntu 14.04 listsscreen
. - Not all systems even have an
/etc/shells
. Solaris and derivatives such as Illumos and OmniOS don't.
In the face of all of this, most programs should simply use $SHELL
and assume that it is what the user wants and/or what the sysadmin
wants the user to get. It's essentially safe to assume that $SHELL
always exists, because it is part of the long-standing standard
Unix login environment. As a corollary, a program
should not change $SHELL
unless it has an excellent reason to
do so.
Note particularly that a user's $SHELL
not being listed in
/etc/shells
means essentially nothing. As outlined above, there
are any number of non-theoretical ways that this can and does happen
on real systems that are out there in the field. As a corollary
your program should not do anything special in this case unless it
has a really strong reason to do so, generally a security-related
reason. Really, you don't even want to look at /etc/shells
unless
you're chsh
or ftpd
or sudo
or the like.
(This entry is sadly brought to you by a program getting this wrong.)