240

I want to create a script to check whether a user exists. I am using the logic below:

# getent passwd test > /dev/null 2&>1
# echo $?
0
# getent passwd test1 > /dev/null 2&>1
# echo $?
2

So if the user exists, then we have success, else the user does not exist. I have put above command in the bash script as below:

#!/bin/bash

getent passwd $1 > /dev/null 2&>1

if [ $? -eq 0 ]; then
    echo "yes the user exists"
else
    echo "No, the user does not exist"
fi

Now, my script always says that the user exists no matter what:

# sh passwd.sh test
yes the user exists
# sh passwd.sh test1
yes the user exists
# sh passwd.sh test2
yes the user exists

Why does the above condition always evaluate to be TRUE and say that the user exists?

Where am I going wrong?

UPDATE:

After reading all the responses, I found the problem in my script. The problem was the way I was redirecting getent output. So I removed all the redirection stuff and made the getent line look like this:

getent passwd $user  > /dev/null

Now my script is working fine.

Alison R.
  • 4,204
  • 28
  • 33
slayedbylucifer
  • 22,878
  • 16
  • 94
  • 123
  • I think that when you use `$?` you get the return code of the `test` command. See answer below. – user000001 Feb 11 '13 at 12:53
  • Is that the *exact* code you are running? No "echo" debug statements between the call to `getent` and your `if` statement? That would cause `$?` to check the exit status of `echo`, not your call to `getent`. – chepner Feb 11 '13 at 14:09
  • 5
    Yeah I think you mean `2>&1` instead of `2&>1`. – Tim Ludwinski May 02 '16 at 17:05
  • Code works on non-empty input, but if `$1` is not set, the if statement will return true. From my testing, solution would be to wrap `$1` in double quotes: `getent passwd "$1" > /dev/null 2&>1`. – Vince Jul 24 '17 at 14:28
  • Please mark an answer – Efren Sep 03 '18 at 03:41
  • @slayedbylucifer The reason your `getent` command does not work is that you have a typo: `2&>1` __is not a valid redirection__. – jimis Feb 11 '21 at 16:09

19 Answers19

384

You can also check user by id command.

id -u name gives you the id of that user. if the user doesn't exist, you got command return value ($?)1

And as other answers pointed out: if all you want is just to check if the user exists, use if with id directly, as if already checks for the exit code. There's no need to fiddle with strings, [, $? or $():

if id "$1" >/dev/null 2>&1; then
    echo 'user found'
else
    echo 'user not found'
fi

(no need to use -u as you're discarding the output anyway)

Also, if you turn this snippet into a function or script, I suggest you also set your exit code appropriately:

#!/bin/bash
user_exists(){ id "$1" &>/dev/null; } # silent, it just sets the exit code
if user_exists "$1"; code=$?; then  # use the function, save the code
    echo 'user found'
else
    echo 'user not found' >&2  # error messages should go to stderr
fi
exit $code  # set the exit code, ultimately the same set by `id`
Agostino
  • 2,723
  • 9
  • 48
  • 65
Kent
  • 189,393
  • 32
  • 233
  • 301
  • 3
    That's what I use. See http://superuser.com/questions/336275/find-out-if-user-name-exists – guettli Oct 11 '13 at 11:09
  • 24
    great answer - just a minor tweak that works nicely... user_exists=$(id -u user > /dev/null 2>&1; echo $?) user_exists=0 if "user" exists, or 1 if not – Pancho Jun 02 '15 at 22:37
  • Thats great, id command is available even in yocto images, while getent is not. – HimanshuR Apr 04 '16 at 06:46
  • 5
    @Pancho I think your variable should be named user_doesnt_exist – Will Sheppard Aug 31 '16 at 09:22
  • @WillSheppard - the variable as named is correct. Run the command from the bash shell and you will see that it returns 0 if the user exists and 1 if the user doesn't exist. This is as distinct from boolean logic which I assume you are referring to. If you want to get fancy and make the response align that's great, but it's not necessary in order to achieve the distinction. (look at Kent's answer above and you will see my comment simply expands on his answer) – Pancho Aug 31 '16 at 14:44
  • @Pancho Can you show any example code which uses the variable, where your name makes sense? – Will Sheppard Aug 31 '16 at 15:20
  • @WillSheppard : echo $(id -u RUBBISHUSER > /dev/null 2>&1; echo $?) ....the output is 1 (because RUBBISHUSER doesn't exist) then: echo $(id -u root > /dev/null 2>&1; echo $?) ...the output is 0 (because the root user exists). It's really not rocket science, not sure why you don't just open a bash shell and test it yourself. Again, I am not attempting to apply boolean logic here simply extending the original answer. – Pancho Aug 31 '16 at 18:19
  • 1
    @WillSheppard : At a general level boolean handling in bash is in my opinion less than clear and I typically avoid implicit boolean inferences in my code. The following make interesting reading and interestingly both favour 0 = true and = false for bash purposes, and while not de facto, align with the variable name I have used from a boolean perspective also: http://stackoverflow.com/a/5431932/3051627 . http://stackoverflow.com/questions/2933843/why-0-is-true-but-false-is-1-in-the-shell . – Pancho Aug 31 '16 at 18:53
  • Thanks for highlighting the difference between boolean and return/error code. Your variable name $user_exists implies boolean. Perhaps it should be called $user_check_error :-) #namingishard – Will Sheppard Sep 01 '16 at 09:28
  • 1
    Is it a vanilla linux command? Or does it come with an optional package? I think it's in "coreutils" so it's not universal. – Sandburg Jul 12 '19 at 06:59
  • 2
    Thanks to @Pancho's comment I could achieve that, just by sending the error to the void and doing ```validuser(){ [[ -n $(id -u "$1" 2>/dev/null) ]] && echo 1 || echo 0; }```. That, pretty much returns 1 if user exists, or 0 if it does not. – lu1s Feb 06 '20 at 19:11
  • 1
    The status code of the last executed command inside the function is what function returns in bash. So simply put the command inside the function: `user_exists() { id -u $1 > /dev/null 2>&1 }` (this is not a one liner) and use it `if ! user_exists username; then....` – muratgozel Jul 09 '20 at 08:54
  • @muratgozel: your function can perfectly be a one-liner if you just add a `; ` before the closing `}` – MestreLion Aug 16 '20 at 04:00
  • This will be error "permission denied" on create /dev/null. – vee Aug 14 '21 at 14:31
40

There's no need to check the exit code explicitly. Try

if getent passwd $1 > /dev/null 2>&1; then
    echo "yes the user exists"
else
    echo "No, the user does not exist"
fi

If that doesn't work, there is something wrong with your getent, or you have more users defined than you think.

chepner
  • 497,756
  • 71
  • 530
  • 681
37

Why don't you simply use

grep -c '^username:' /etc/passwd

It will return 1 (since a user has max. 1 entry) if the user exists and 0 if it doesn't.

poitroae
  • 21,129
  • 10
  • 63
  • 81
27

This is what I ended up doing in a Freeswitch bash startup script:

# Check if user exists
if ! id -u $FS_USER > /dev/null 2>&1; then
    echo "The user does not exist; execute below commands to crate and try again:"
    echo "  root@sh1:~# adduser --home /usr/local/freeswitch/ --shell /bin/false --no-create-home --ingroup daemon --disabled-password --disabled-login $FS_USER"
    echo "  ..."
    echo "  root@sh1:~# chown freeswitch:daemon /usr/local/freeswitch/ -R"
    exit 1
fi
Daniel Sokolowski
  • 11,982
  • 4
  • 69
  • 55
24

By far the simplest solution:

if id -u "$user" >/dev/null 2>&1; then
    echo 'user exists'
else
    echo 'user missing'
fi

The >/dev/null 2>&1 can be shortened to &>/dev/null in Bash, and if you only want to know if a user does not exist:

if ! id -u "$user" >/dev/null 2>&1; then
    echo 'user missing'
fi
Fleshgrinder
  • 15,703
  • 4
  • 47
  • 56
14

I suggest to use id command as it tests valid user existence wrt passwd file entry which is not necessary means the same:

if [ `id -u $USER_TO_CHECK 2>/dev/null || echo -1` -ge 0 ]; then 
echo FOUND
fi

Note: 0 is root uid.

13

I was using it in that way:

if [ $(getent passwd $user) ] ; then
        echo user $user exists
else
        echo user $user doesn\'t exists
fi
Craig S. Anderson
  • 6,966
  • 4
  • 33
  • 46
Takeda
  • 139
  • 1
  • 3
  • 1
    A bad approach. You can get rid of both `[ ]` and `$()` and simply check for `getent`'s _exit code_ directly instead of using its _output_ – MestreLion Aug 16 '20 at 03:31
7

Script to Check whether Linux user exists or not

Script To check whether the user exists or not

#! /bin/bash
USER_NAME=bakul
cat /etc/passwd | grep ${USER_NAME} >/dev/null 2>&1
if [ $? -eq 0 ] ; then
    echo "User Exists"
else
    echo "User Not Found"
fi
Bakul Gupta
  • 103
  • 1
  • 5
6

Late answer but finger also shows more information on user

  sudo apt-get finger 
  finger "$username"
jackotonye
  • 3,537
  • 23
  • 31
5

Using sed:

username="alice"
if [ `sed -n "/^$username/p" /etc/passwd` ]
then
    echo "User [$username] already exists"
else
    echo "User [$username] doesn't exist"
fi
Stephane
  • 4,978
  • 9
  • 51
  • 86
4

Actually I cannot reproduce the problem. The script as written in the question works fine, except for the case where $1 is empty.

However, there is a problem in the script related to redirection of stderr. Although the two forms &> and >& exist, in your case you want to use >&. You already redirected stdout, that's why the form &> does not work. You can easily verify it this way:

getent /etc/passwd username >/dev/null 2&>1
ls

You will see a file named 1 in the current directory. You want to use 2>&1 instead, or use this:

getent /etc/passwd username &>/dev/null

This also redirects stdout and stderr to /dev/null.

Warning Redirecting stderr to /dev/null might not be such a good idea. When things go wrong, you will have no clue why.

Christian Hujer
  • 17,035
  • 5
  • 40
  • 47
4

user infomation is stored in /etc/passwd, so you can use "grep 'usename' /etc/passwd" to check if the username exist. meanwhile you can use "id" shell command, it will print the user id and group id, if the user does not exist, it will print "no such user" message.

Yu Chai
  • 77
  • 4
  • IT is stored in /etc/passwd IF nsswitch.conf's passwd setting is set to files... This approach breaks if network-based logins are involved... – Gert van den Berg Oct 06 '20 at 10:09
3

Depending on your shell implementation (e.g. Busybox vs. grown-up) the [ operator might start a process, changing $?.

Try

getent passwd $1 > /dev/null 2&>1
RES=$?

if [ $RES -eq 0 ]; then
    echo "yes the user exists"
else
    echo "No, the user does not exist"
fi
Eugen Rieck
  • 64,175
  • 10
  • 70
  • 92
2

Login to the server. grep "username" /etc/passwd This will display the user details if present.

syam
  • 799
  • 1
  • 12
  • 30
  • 5
    This will also match any username which contains "username". E.g. "some_username". You would want to do `if grep -q "^username:" /etc/passwd; then ...` – maedox Jun 12 '18 at 10:58
1

Below is the script to check the OS distribution and create User if not exists and do nothing if user exists.

#!/bin/bash

# Detecting OS Ditribution
if [ -f /etc/os-release ]; then
    . /etc/os-release
    OS=$NAME
elif type lsb_release >/dev/null 2>&1; then
OS=$(lsb_release -si)
elif [ -f /etc/lsb-release ]; then
    . /etc/lsb-release
    OS=$DISTRIB_ID
else
    OS=$(uname -s)
fi

 echo "$OS"

 user=$(cat /etc/passwd | egrep -e ansible | awk -F ":" '{ print $1}')

 #Adding User based on The OS Distribution
 if [[ $OS = *"Red Hat"* ]] || [[ $OS = *"Amazon Linux"* ]] || [[ $OS = *"CentOS"*  
]] && [[ "$user" != "ansible" ]];then
 sudo useradd ansible

elif [ "$OS" =  Ubuntu ] && [ "$user" != "ansible" ]; then
sudo adduser --disabled-password --gecos "" ansible
else
  echo "$user is already exist on $OS"
 exit
fi
Santosh Garole
  • 1,419
  • 13
  • 23
1

Create system user some_user if it doesn't exist

if [[ $(getent passwd some_user) = "" ]]; then
    sudo adduser --no-create-home --force-badname --disabled-login --disabled-password --system some_user
fi
luchaninov
  • 6,792
  • 6
  • 60
  • 75
1

I like this nice one line solution

getent passwd username > /dev/null 2&>1 && echo yes || echo no

and in script:

#!/bin/bash

if [ "$1" != "" ]; then
        getent passwd $1 > /dev/null 2&>1 && (echo yes; exit 0) || (echo no; exit 2)
else
        echo "missing username"
        exit -1
fi

use:

[mrfish@yoda ~]$ ./u_exists.sh root
yes
[mrfish@yoda ~]$ echo $?
0

[mrfish@yoda ~]$ ./u_exists.sh
missing username
[mrfish@yoda ~]$ echo $?
255

[mrfish@yoda ~]$ ./u_exists.sh aaa
no
[mrfish@indegy ~]$ echo $?
2
nir vizel
  • 21
  • 5
0
echo "$PASSWORD" | su -c "cd /" "$USER"
if [ "$?" = "0" ];then
 echo "OK"
else
 echo "Error"
fi
NuLo
  • 1,298
  • 1
  • 11
  • 16
0
#!/bin/bash
read -p "Enter your Login Name: " loginname
home=`grep -w $loginname /etc/passwd | cut -ef:6 -d:`
if [ $home ]
    echo "Exists"
else
    echo "Not Exist"
fi