What is the difference between /sbin/nologin and /bin/false?
I have often heard it recommended that a user account should be disabled by setting its shell to /bin/false
. But, on my existing Linux systems, I see that a great number of existing accounts (all of them service accounts) have a shell of /sbin/nologin
instead.
I see from the man page that /sbin/nologin
prints a message to the user saying the account is disabled, and then exits. Presumably /bin/false
would not print anything.
I also see that /sbin/nologin
is listed in /etc/shells
, while /bin/false
is not.
The man page says that FTP will disable access for users with a shell not listed in /etc/shells
and implies that other programs may do the same. Does that mean that somebody could FTP in with an account that has /sbin/nologin
as its shell?
What is the difference here? Which one of these should I use to disable a user account, and in what circumstances? What other effects does a listing in /etc/shells
have?
/bin/false
is a utility program, companion to /bin/true
, which is useful in some abstract sense to ensure that unix is feature-complete. However, emergent purposes for these programs have been found; consider the BASH statement /some/program || /bin/true
, which will always boolean-evaluate to true ($? = 0
) no matter the return of /some/program
.
An emergent use of /bin/false
, as you identified, is as a null shell for users not allowed to log in. The system in this case will behave exactly as though the shell failed to run.
POSIX (though I may be wrong and it may the the SUS) constrains both these commands to do exactly nothing other than return the appropriate boolean value.
/sbin/nologin
is a BSD utility which has similar behaviour to /bin/false
(returns boolean false), but prints output as well, as /bin/false
is prohibited from doing. This is supposed to help the user understand what happened, though in practice many terminal emulators will simply close when the shell terminates, rendering the message all but unreadable anyway in some cases.
There is little purpose to listing /sbin/nologin
in /etc/shells
. The standard effect of /etc/shells
is to list the programs permissible for use with chsh
when users are changing their own shell (and there is no credible reason to change your own shell to /sbin/nologin
). The superuser can change anyone's shell to anything. However, you may want to list both /sbin/nologin
and /bin/false
in /etc/rsh
, which will prohibit users with these shells from changing their shell using chsh
in the unfortunate event that they get a shell.
FTP daemons may disallow access to users with a shell not in /etc/shells, or they may use any other logic they wish. Running FTP is to be avoided in any case because sftp
(which provides similar functionality) is similar but secure. Some sites use /sbin/nologin
to disable shell access while allowing sftp access by putting it in /etc/shells
. This may open a backdoor if the user is allowed to create cronjobs.
In either case, scp
will not operate with an invalid shell. scponly
can be used as a shell in this instance.
Additionally, the choice of shell affects the operation of su -
(AKA su -l
). Particularly, the output of /sbin/nologin
will be printed to stdout if it is the shell; this cannot be the case with /bin/false
. In either case commands run with su -cl
will fail.
Finally, the answer:
To disable an account, depend on neither of these, but set the shell to /sbin/nologin
for informational purposes (unless /sbin/nologin
is in /etc/shells
, at which point you should use /bin/false
, which shouldn't be). Instead, set the password field in /etc/passwd
to !
, which is guaranteed by crypt
to be valid for no passwords. Consider setting the hash in /etc/shadow
the same way to avoid bugs. passwd -l
will do this for you.
A third way to disable an account is to set the account expiration date field to an ancient date (eg. usermod --expiredate 1
). This will prevent logins in case your setup allows users to authenticate against their unix account without a password and the service they are using requires no shell.
After doing some research on this, the method you use depends on what you have to lock out . If a user logs in with this set to the shell then they will get a message displayed to the effect of This account is currently unavailable.
Note that you can change this by creating the file /etc/nologin.txt
at least on RHEL derivatives.
As you know /bin/false
is not a shell. They way it works is that it returns false which logs out immediately after the binary exits. Note that /bin/true
would achieve the same effect.
Regarding your FTP question: Yes, you are correct in that having the shell set to /sbin/nologin
will allow users to login to FTP while /bin/false
or /bin/true
will completely prevent the user from logging into any service.
Therefore, /bin/false
or /bin/true
is best to prevent a user from logging into any service, while /sbin/nologin
will still allow users to log into services other than SSH or local console while providing feedback to the user that the account is inactive and is best used when only SSH/local console need to be locked out.