Sprawdź, czy użytkownik istnieje


165

Chcę utworzyć skrypt, aby sprawdzić, czy użytkownik istnieje. Używam poniższej logiki:

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

Więc jeśli użytkownik istnieje, to mamy sukces, w przeciwnym razie użytkownik nie istnieje. Powyższe polecenie umieściłem w skrypcie bash, jak poniżej:

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

Teraz mój skrypt zawsze mówi, że użytkownik istnieje bez względu na wszystko:

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

Dlaczego powyższy warunek zawsze jest PRAWDZIWY i mówi, że użytkownik istnieje?

Gdzie się mylę?

AKTUALIZACJA:

Po przeczytaniu wszystkich odpowiedzi znalazłem problem w swoim skrypcie. Problem polegał na sposobie przekierowywania getentdanych wyjściowych. Usunąłem więc wszystkie przekierowania i sprawiłem, że getentlinia wygląda tak:

getent passwd $user  > /dev/null

Teraz mój skrypt działa dobrze.


Myślę, że kiedy używasz $?, otrzymasz kod zwrotny testpolecenia. Zobacz odpowiedź poniżej.
user000001

Czy to jest dokładnie ten kod, który używasz? Brak instrukcji debugowania „echo” między wywołaniem getenta ifinstrukcją? To spowodowałoby $?sprawdzenie statusu wyjścia echo, a nie twojego wywołania getent.
chepner

4
Tak, myślę, że masz na myśli 2>&1zamiast 2&>1.
Tim Ludwinski

Kod działa na niepustych danych wejściowych, ale jeśli $1nie jest ustawiony, instrukcja if zwróci wartość true. Z moich badań, rozwiązaniem byłoby zawinąć $1w cudzysłowach: getent passwd "$1" > /dev/null 2&>1.
Vince,

Proszę zaznaczyć odpowiedź
Efren

Odpowiedzi:


292

możesz również sprawdzić użytkownika za pomocą idpolecenia.

id -u namepodaje identyfikator tego użytkownika. jeśli użytkownik nie istnieje, otrzymałeś polecenie zwracające wartość ( $?)1



24
świetna odpowiedź - tylko drobna poprawka, która działa ładnie ... user_exists = $ (id -u użytkownik> / dev / null 2> & 1; echo $?) user_exists = 0, jeśli istnieje „user”, lub 1, jeśli nie
Pancho

5
@Pancho Myślę, że twoja zmienna powinna nazywać się user_doesnt_exist
Will Sheppard

1
@WillSheppard: Na poziomie ogólnym obsługa wartości boolowskich w bashu jest moim zdaniem mniej niż jasna i zazwyczaj unikam ukrytych wniosków logicznych w moim kodzie. Poniższe informacje są interesujące i interesujące zarówno faworyzują 0 = true, jak i <not 0> = false dla celów basha, i chociaż nie de facto, są zgodne z nazwą zmiennej, której użyłem z perspektywy logicznej: stackoverflow.com/a/5431932 / 3051627 . stackoverflow.com/questions/2933843/… .
Pancho

2
Dzięki komentarzowi @ Pancho mogłem to osiągnąć, po prostu wysyłając błąd do pustki i robiąc validuser(){ [[ -n $(id -u "$1" 2>/dev/null) ]] && echo 1 || echo 0; }. To prawie zwraca 1, jeśli użytkownik istnieje, lub 0, jeśli nie.
lu1s

32

Dlaczego po prostu nie użyjesz

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

Zwróci 1 (ponieważ użytkownik ma maksymalnie 1 wpis), jeśli użytkownik istnieje, i 0, jeśli nie.


19
To nie działa, jeśli serwer używa innego systemu do zarządzania zastosowaniami, takimi jak NIS lub LDAP. W takim przypadku możesz użyćgetent passwd | grep -c '^username:'
Toby Jackson,

1
zwróci to 1, jeśli masz nazwę użytkownika, powiedzmy „test1” i chcesz utworzyć nową nazwę użytkownika o nazwie „test”.
Marin Nedea

2
@ MarinNedea dwukropek :po nazwie użytkownika chroni przed dopasowywaniem podciągów przez dopasowanie do separatora pól, więc opisywany efekt nie wystąpi.
Stéphane Gourichon

30

Nie ma potrzeby jawnego sprawdzania kodu zakończenia. Próbować

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

Jeśli to nie zadziała, coś jest nie tak z Twoim getent lub masz zdefiniowanych więcej użytkowników, niż myślisz.


23

Oto, co zrobiłem w Freeswitchskrypcie startowym 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

Proponuję użyć polecenia id, ponieważ testuje on prawidłowe istnienie użytkownika z wpisem w pliku passwd, który nie jest konieczny, oznacza to samo:

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

Uwaga: 0 to identyfikator użytkownika root.


12

Używałem tego w ten sposób:

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

9

Zdecydowanie najprostsze rozwiązanie:

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

>/dev/null 2>&1Można skrócić do &>/dev/nullbash.


Tak dziękuję!
Zane Hitchcox

7

Skrypt sprawdzający, czy użytkownik Linuksa istnieje, czy nie

Skrypt Aby sprawdzić, czy użytkownik istnieje, czy nie

#! /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
Dlaczego używać cat? grep $USER_NAME /etc/passwd >/dev/null 2>&1
Alexx Roche

Tak, Alexx Roche, nie ma potrzeby używania kota, mam zastosowanie, aby mieć lepszy sposób na wizualizację koncepcji dla początkującego.
Bakul Gupta,


3

Właściwie nie mogę odtworzyć problemu. Skrypt napisany w pytaniu działa dobrze, z wyjątkiem przypadku, gdy $ 1 jest pusty.

Jednak w skrypcie występuje problem związany z przekierowaniem stderr. Chociaż dwie formy &>i >&istnieją, w Twoim przypadku chcesz użyć >&. Już przekierowałeś stdout, dlatego formularz &>nie działa. Możesz to łatwo zweryfikować w ten sposób:

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

Zobaczysz plik o nazwie 1w bieżącym katalogu. Zamiast tego chcesz użyć 2>&1lub użyj tego:

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

To również przekierowuje stdouti stderrdo /dev/null.

Ostrzeżenie Przekierowanie stderrdo /dev/nullmoże nie być dobrym pomysłem. Kiedy coś pójdzie nie tak, nie będziesz miał pojęcia, dlaczego.


3

informacje o użytkowniku są przechowywane w / etc / passwd, więc możesz użyć „grep 'nazwa_użytkownika' / etc / passwd”, aby sprawdzić, czy nazwa użytkownika istnieje. w międzyczasie możesz użyć polecenia powłoki „id”, wypisze ono identyfikator użytkownika i identyfikator grupy, a jeśli użytkownik nie istnieje, wyświetli komunikat „nie ma takiego użytkownika”.


2

Zaloguj się do serwera. grep "nazwa użytkownika" / etc / passwd Spowoduje to wyświetlenie szczegółów użytkownika, jeśli są obecne.


3
Będzie to również pasowało do każdej nazwy użytkownika, która zawiera „nazwę użytkownika”. Np. „Nazwa_użytkownika”. Chciałbyś to zrobićif grep -q "^username:" /etc/passwd; then ...
maedox

2

Korzystanie z seda:

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

1

W zależności od implementacji powłoki (np. Busybox czy dorosły) [operator może rozpocząć proces, zmieniając się $?.

Próbować

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

zmiana $?daje mi ten sam wynik. To jest wersja basha:GNU bash, version 4.1.5(1)-release (i486-pc-linux-gnu)
slayedbylucifer

Spróbujif test "$RES" == "0"; then ...
Eugen Rieck,

1
$?zostanie rozwinięty przed [uruchomieniem, więc nie stanowi to problemu.
chepner

1
Zamiast testować wynik polecenia, możesz przetestować polecenie bezpośrednio: 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

Poniżej znajduje się skrypt, który sprawdza dystrybucję systemu operacyjnego i tworzy użytkownika, jeśli nie istnieje, i nie robi nic, jeśli użytkownik istnieje.

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

Utwórz użytkownika systemowego, some_userjeśli nie istnieje

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

0

Podoba mi się to ładne, jednokreskowe rozwiązanie

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

i w scenariuszu:

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

posługiwać się:

[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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.