Ubuntu – Parsing `/etc/passwd` file to find users with Interactive shells

command linepython

I want to parse /etc/passwd file to find out if the user can run interactive shell.

I know the 7th field in each line of /etc/passwd file tells the path of shell. But How do you say that, defined shell is interactive?

I am parsing this files in python, I can implement the logic, I just don't know the how to find out how to identify Interactive shell.

PS. I want to find it out using python.

Best Answer

I think you have a basic misconception: talking of a shell that you cannot run interactively but that you can run non-interactively is much like talking of a car that you can't drive but that you can use to listen to the radio.

The main purpose of a shell is running interactively, the fact that it can run non-interactively is the optional, not the other way around.

Closer to the concept of a shell that you cannot run interactively but that you can run non-interactively is an interpreted language which can't be interpreted interactively (though one real example is not occuring to me right now: the most common interpreted languages all can run interactive sessions: Perl, Python, PHP, ...)

That been said if you want to find out whether a user is allowed to login through a shell, you can use this command:

shell=$(getent passwd user | cut -d ':' -f 7); [ "$shell" = "/usr/sbin/nologin" -o "$shell" = "/bin/false" ] && printf 'User is not allowed to login\n' || printf '%s\n' "$shell"

(replace user in the getent passwd user command with the user's username)

In Python you could do:

#!/usr/bin/python
user = "user"
with open("/etc/passwd") as file:
    for line in file:
        if line.split(":")[0] == user:
            if line.rstrip("\n").split(":")[6] in ["/usr/sbin/nologin", "/bin/false"]:
                print("User is not allowed to login")
            else:
                print(line.rstrip("\n").split(":")[6])

(replace user in the user = "user" statement with the user's username)

Or, as suggested by muru, better using the pwd module:

#!/usr/bin/python
from pwd import getpwnam

user = "user"
shell = getpwnam(user)[6]
if shell in ["/usr/sbin/nologin", "/bin/false"]:
    print("User is not allowed to login")
else:
    print(shell)

(replace user in the user = "user" statement with the user's username)

In all of the examples above if the seventh field of the user's /etc/passwd entry is either /usr/sbin/nologin or /usr/bin/false a message saying that the user is not allowed to login is printed; otherwise the user's login shell is printed.

But keep in mind that not being able to login through a shell doesn't mean the user is not allowed to login at all, and that there might be bogus shells other than /usr/sbin/nologin or /bin/false used to forbid the user's login. You should watch out for those too.

Related Question