- What’s the difference between /sbin/nologin and /bin/false
- 8 Answers 8
- Difference between /bin/false & /sbin/nologin
- What is the Difference between /bin/false & /sbin/nologin?
- nologin or false, which is better?
- What is the difference between /sbin/nologin and /bin/false?
- Find below all possible solutions or suggestions for the above questions..
- Purpose of #!/bin/false in bash script
- 2 Answers 2
What’s the difference between /sbin/nologin and /bin/false
Technically, unless pam is set up to check your shell with pam_shells neither of these can actually prevent your login, if you’re not on the shell. On my system they are even different sizes, so I suspect they actually do something. So what’s the difference? why do they both exist? Why would I use one over the other?
-rwxr-xr-x 1 root root 21K Feb 4 17:01 /bin/false -rwxr-xr-x 1 root root 4.7K Mar 2 14:59 /sbin/nologin
I’m curious why /bin/false takes 21k of code to return a «1» return code! (and /sbin/nologin only takes 4.7k)
@nxnev Yeah didn’t think about the overhead of ELF. And from my old IBM days there was a program IEFBR14 that was a simple one op-code assembly instruction: BR 14 — Branch to register 14, which would terminate the program with the return code set to whatever was in register 14!
8 Answers 8
When /sbin/nologin is set as the shell, if user with that shell logs in, they’ll get a polite message saying ‘This account is currently not available.’ This message can be changed with the file /etc/nologin.txt .
/bin/false is just a binary that immediately exits, returning false, when it’s called, so when someone who has false as shell logs in, they’re immediately logged out when false exits. Setting the shell to /bin/true has the same effect of not allowing someone to log in but false is probably used as a convention over true since it’s much better at conveying the concept that person doesn’t have a shell.
Looking at nologin ‘s man page, it says it was created in 4.4 BSD (early 1990s) so it came long after false was created. The use of false as a shell is probably just a convention carried over from the early days of UNIX.
nologin is the more user-friendly option, with a customizable message given to the user trying to log in, so you would theoretically want to use that; but both nologin and false will have the same end result of someone not having a shell and not being able to ssh in.
Difference between /bin/false & /sbin/nologin
I have seen few system administrators using /sbin/nologin and few use /bin/false to deny shell access to a particular user in Unix machines. But I have been wondering what’s the difference between /bin/false & /sbin/nologin and what is the right way of denying a shell access to a user. Well, this tutorial will explain what is the difference between /bin/false & /sbin/nologin.
What is the Difference between /bin/false & /sbin/nologin?
First of all, i should say in terms of functionality there is no difference between /bin/false & /sbin/nologin . It means, both denies a shell access to a particular user account.
General usage of /sbin/login & /bin/false
test:x:2935:2936::/home/test:/sbin/nologin
test:x:2935:2936::/home/test:/bin/false
But there’s a slight difference –
/bin/false does nothing and it just exits with a status code indicating failure when a user attempts to login to the machine. It does not output any message indicating that the user account does not have shell access.
Whereas, /sbin/nologin politely denies a shell access for a particular user account and exists with a status code of non-zero. For example, when a user account is set to /sbin/nologin as shell, then nologin displays ‘This account is currently not available‘.
#su - test This account is currently not available.
nologin can also read a custom message from /etc/nologin.txt , if present.
Enter a custom message say “This is not a valid login account – Administrator“.
Both /bin/false & /sbin/nologin will log the login attempts in /var/log/secure .
Oct 26 09:43:37 test.tg.in su: pam_unix(su-l:session): session opened for user test Oct 26 09:43:37 test.tg.in su: pam_unix(su-l:session): session closed for user test
Looking at man pages of nologin and false.
nologin or false, which is better?
false is a traditional approach, which came much before nologin . /sbin/nologin has the ability to display a custom message, so any administrator would want to use that. In functionality wise, both does the same of not allowing a shell access.
So which one are you using? Tell us in the comment section.
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?
Find below all possible solutions or suggestions for the above questions..
Suggestion: 1:
/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.
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.
Purpose of #!/bin/false in bash script
While working on a project written in bash by my former colleague, I noticed that all .sh files contain nothing but function definitions start with #!/bin/false , which is, as I understand, a safety mechanism of preventing execution of include-only files. Example: my_foo.sh
#!/bin/bash ./my_foo.sh # does nothing foo # error, no command named "foo" . ./my_foo.sh foo # prints "foontastic"
However when I don’t use #!/bin/false , effects of both proper and improper use are exactly the same: Example: my_bar.sh
#!/bin/bash ./my_bar.sh # spawn a subshell, defines bar and exit, effectively doing nothing bar # error, no command named "bar" . ./my_bar.sh bar # prints "barvelous"
Since properly using those scripts by including them with source in both cases works as expected, and executing them in both cases does nothing from the perspective of a parent shell and generate no error message concerning invalid use, what is exactly the purpose of #!/bash/false in those script?
You said it yourself : with the false shebang, the content is not executed. It is a safety, in case the script is error-prone when used in the wrong context or ressource heavy. Most likely, it is an habit your colleague has picked up, that has no influence on the code in most cases but that could be usefull in more complex circumstances.
Also it should be worth noted that, the she-bang line #!/bin/true or #!/bin/false has no impact on the script when you invoke the shell interpreter directly as bash my_script.sh , this syntax runs the script with bash no-matter what and echoes the output foontastic
./my_bar.sh does not spawn a subshell : it spawns a whole new shell. This is not just a technicality : subshells receive a copy of all variables of the main shell (including those that are not marked for export), while a separate shell receives only the exported variables. Subshells are launched in other ways, for instance by enclosing statements parentheses () , initiating pipes | , process/command substitution $() () .()>
2 Answers 2
In general, let’s consider a file testcode with bash code in it
#!/bin/bash if [ "$0" = "$" ]; then echo "You are executing $" else echo "You are sourcing $" fi
you can do three different things with it:
$ ./testcode You are executing ./testcode
This works if testcode has the right permissions and the right shebang. With a shebang of #!/bin/false , this outputs nothing and returns a code of 1 (false).
$ bash ./testcode You are executing ./testcode
This completely disregards the shebang (which can even be missing) and it only requires read permission, not executable permission. This is the way to call bash scripts from a CMD command line in Windows (if you have bash.exe in your PATH. ), since there the shebang machanism doesn’t work.
$ . ./testcode You are sourcing ./testcode
This also completely disregards the shebang, as above, but it is a complete different matter, because sourcing a script means having the current shell execute it, while executing a script means invoking a new shell to execute it. For instance, if you put an exit command in a sourced script, you exit from the current shell, which is rarely what you want. Therefore, sourcing is often used to load function definitions or constants, in a way somewhat resembling the import statement of other programming languages, and various programmers develop different habits to differentiate between scripts meant to be executed and include files to be sourced. I usually don’t use any extension for the former (others use .sh ), but I use an extension of .shinc for the latter. Your former colleague used a shebang of #!/bin/false and one can only ask them why they preferred this to a zillion other possibilities. One reason that comes to my mind is that you can use file to tell these files apart:
$ file testcode testcode2 testcode: Bourne-Again shell script, ASCII text executable testcode2: a /bin/false script, ASCII text executable
Of course, if these include files contain only function definitions, it’s harmless to execute them, so I don’t think your colleague did it to prevent execution.
Another habit of mine, inspired by the Python world, is to place some regression tests at the end of my .shinc files (at least while developing)
. function definitions here . [ "$0" != "$" ] && return . regression tests here .
Since return generates an error in executed scripts but is OK in sourced scripts, a more cryptic way to get the same result is
. function definitions here . return 2>/dev/null || : . regression tests here .