Перевірте, чи існує користувач


165

Я хочу створити сценарій, щоб перевірити, чи існує користувач. Я використовую логіку нижче:

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

Отже, якщо користувач існує, то ми маємо успіх, інакше користувач не існує. Я поставив вище команду в скрипті bash, як нижче:

#!/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

Тепер мій сценарій завжди говорить про те, що користувач існує незалежно від того, що:

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

Чому вищезазначена умова завжди оцінюється як ПРАВИЛЬНА і каже, що користувач існує?

Де я помиляюся?

ОНОВЛЕННЯ:

Прочитавши всі відповіді, я знайшов проблему в своєму сценарії. Проблема полягала в тому, як я переспрямовував getentвихід. Тому я видалив усі матеріали про переадресацію та зробив getentлінію таким чином:

getent passwd $user  > /dev/null

Зараз мій сценарій працює чудово.


Я думаю, що при використанні $?ви отримуєте код повернення testкоманди. Дивіться відповідь нижче.
user000001

Це точний код, який ви працюєте? Немає викликів налагодження "відлуння" між викликом getentта вашим ifзаявою? Це призведе $?до перевірки статусу виходу echo, а не до вашого дзвінка getent.
чепнер

4
Так, я думаю, ви маєте на увазі 2>&1замість цього 2&>1.
Тім Людвинський

Код працює на не порожньому введенні, але якщо $1його не встановлено, оператор if поверне справжнє значення. З мого тестування, рішення було б обернути $1в подвійних лапках: getent passwd "$1" > /dev/null 2&>1.
Вінс

Будь ласка, позначте відповідь
Ефрен

Відповіді:


292

Ви також можете перевірити користувача за idкомандою.

id -u nameдає вам ідентифікатор цього користувача. якщо користувача не існує, ви отримали команду return value ( $?)1


3
Саме цим я і користуюся. Дивіться superuser.com/questions/336275/find-out-if-user-name-exists
guettli

24
чудова відповідь - просто незначне налаштування, яке чудово працює ... user_exists = $ (id -u користувач> / dev / null 2> & 1; echo $?) user_exists = 0, якщо "користувач" існує, або 1, якщо ні
Pancho

5
@Pancho Я думаю, що вашу змінну слід назвати user_doesnt_exist
Буде Шеппард

1
@WillSheppard: На загальному рівні булева керованість в баші, на мій погляд, менш чітка, і я зазвичай уникаю неявних булевих висновків у своєму коді. Нижче зроблено цікаве читання, і що цікаво як прихильність 0 = true, так і <not 0> = false для цілей bash, і, хоча не фактично, вирівняйте ім'я змінної, яку я використав з булевої точки зору також: stackoverflow.com/a/5431932 / 3051627 . stackoverflow.com/questions/2933843/… .
Панчо

2
Завдяки коментарю @ Pancho, я міг цього досягти, просто надіславши помилку в порожнечу і зробивши це validuser(){ [[ -n $(id -u "$1" 2>/dev/null) ]] && echo 1 || echo 0; }. Це, майже, повертає 1, якщо користувач існує, або 0, якщо цього немає.
lu1s

32

Чому ви просто не використовуєте

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

Він поверне 1 (оскільки користувач має максимум 1 запис), якщо користувач існує, і 0, якщо цього немає.


19
Це не працює, якщо сервер використовує іншу систему для управління такими видами, як NIS або LDAP. У цьому випадку ви можете скористатисяgetent passwd | grep -c '^username:'
Toby Jackson

1
це поверне 1, якщо у вас є ім’я користувача, скажімо, "test1" і хочете створити нове ім'я користувача, яке називається "test".
Марін Недея

2
@MarinNedea двокрапка :після імені користувача захищає від узгодження підрядків шляхом збігу з роздільником поля, тому описаний вами ефект не відбудеться.
Стефан Гурішон

30

Не потрібно чітко перевіряти вихідний код. Спробуйте

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

Якщо це не працює, з вами щось не так getent, або у вас визначено більше користувачів, ніж ви думаєте.


23

Це те, що я закінчив робити в Freeswitchсценарії запуску bash:

# 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

14

Я пропоную використовувати команду id, оскільки вона перевіряє дійсне введення користувача wrt passwd файл, який не потрібен, означає те саме:

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

Примітка: 0 - це кореневий uid.


12

Я використовував це таким чином:

if [ $(getent passwd $user) ] ; then
        echo user $user exists
else
        echo user $user doesn\'t exists
fi

9

На сьогодні найпростіше рішення:

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

>/dev/null 2>&1Може бути скорочений до &>/dev/nullв Bash.


Так дякую!
Зейн Хічкокс

7

Сценарій, щоб перевірити, чи існує користувач Linux чи ні

Сценарій Для перевірки існування користувача чи ні

#! /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

2
Навіщо використовувати cat? grep $USER_NAME /etc/passwd >/dev/null 2>&1
Алекс Рош

Так, Алекс Рош, немає необхідності використовувати кішку, я маю використання для того, щоб мати кращий спосіб візуалізації концепції для початківця.
Бакул Гупта


3

Насправді я не можу відтворити проблему. Сценарій, написаний у запитанні, працює чудово, за винятком випадків, коли 1 долар порожній.

Однак у скрипті є проблема, пов’язана з перенаправленням stderr. Хоча дві форми &>і >&EXIST, в вашому випадку , якщо ви хочете використовувати >&. Ви вже перенаправлені stdout, тому форма &>не працює. Ви можете легко підтвердити це таким чином:

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

Ви побачите файл, названий 1у поточному каталозі. Ви хочете використовувати 2>&1замість цього або використовувати це:

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

Це також переспрямовує stdoutі stderrна /dev/null.

Попередження Перенаправлення stderrщоб /dev/nullможе бути не такою гарною ідеєю. Коли все піде не так, ви не матимете поняття, чому.


3

інформація користувача зберігається в / etc / passwd, тому ви можете використовувати "grep 'usename" / etc / passwd ", щоб перевірити, чи існує ім'я користувача. тим часом ви можете використовувати команду оболонки "id", вона надрукує ідентифікатор користувача та ідентифікатор групи, якщо користувача не існує, він надрукує повідомлення "немає такого користувача".


2

Вхід на сервер. grep "ім'я користувача" / etc / passwd Це відобразить дані користувача, якщо вони є.


3
Це також відповідатиме будь-якому імені користувача, яке містить "ім'я користувача". Наприклад, "деяке ім'я_користувача". Ви хотіли б зробитиif grep -q "^username:" /etc/passwd; then ...
maedox

2

Використання sed:

username="alice"
if [ `sed -n "/^$username/p" /etc/passwd` ]
then
    echo "User [$username] already exists"
else
    echo "User [$username] doesn't exist"
fi

1

Залежно від вашої реалізації оболонки (наприклад, Busybox проти дорослого), [оператор може почати процес, змінюючись $?.

Спробуйте

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

зміна $?дає мені той самий вихід. Це баш-версія:GNU bash, version 4.1.5(1)-release (i486-pc-linux-gnu)
slayedbylucifer

Спробуйтеif test "$RES" == "0"; then ...
Євген Рік

1
$?буде розширено перед [запуском, тому це не проблема.
чепнер

1
Замість тестування на результат команди, ви можете перевірити команду безпосередньо: if getent passwd $1 > /dev/null 2&>1; then echo "yes the user exists" else echo "No, the user does not exist" fi
GMartinez

1

Нижче наведено скрипт для перевірки розподілу ОС та створення користувача, якщо його немає, і нічого не робити, якщо існує.

#!/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

0

Створіть системного користувача, some_userякщо його не існує

if [[ $(getent passwd some_user) = "" ]]; then
    sudo adduser --no-create-home --force-badname --disabled-login --disabled-password --system some_user
fi

0

Мені подобається це приємне рішення з одного рядка

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

та в сценарії:

#!/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

використання:

[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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.