Listar todos os usuários humanos

19

Como posso listar todos os usuários humanos que eu criei? Eu tentei cat /etc/passwde apenas lista muitas coisas.

anatoly techtonik
fonte

Respostas:

18

Os usuários humanos têm UIDs a partir de 1000, para que você possa usar esse fato para filtrar os não humanos:

cut -d: -f1,3 /etc/passwd | egrep ':[0-9]{4}$' | cut -d: -f1

Isso corta o primeiro (nome de usuário) e o terceiro (UID) campos delimitados por dois pontos /etc/passwd, depois filtra as linhas resultantes que terminam com dois pontos e quatro dígitos, depois corta o primeiro campo (nome de usuário), deixando-o com uma lista de usuários com UIDs entre 1000 e 9999.

Se você tiver mais de nove mil usuários em seu sistema, isso falhará - mas é necessário restringir o resultado a UIDs de quatro dígitos para não capturar nobody(UID 65534).


fonte
15

Isso faz praticamente o que a resposta aceita faz, apenas em um comando, em vez de três:

awk -F: '$3 >= 1000 && $1 != "nobody" {print $1}' /etc/passwd

E graças a Karel nos comentários, o nobodyusuário também é filtrado.

Oli
fonte
@karel Sim, talvez. Em vez de filtrar por UID, estou filtrando esse nome de usuário explicitamente. Pode haver uma razão para ter um usuário legítimo com uma UID que a alta ... Quem sabe;)
Oli
9

Eu pessoalmente gosto de usar apenas:

ls /home

É certo que essa não é uma lista de usuários, mas uma lista de seus diretórios pessoais. Atualmente, os usuários humanos existentes no sistema terão diretórios pessoais /home, mas você também pode ver os diretórios pessoais de usuários anteriores que foram removidos.

Isso funciona para os meus propósitos e pode funcionar para os seus também. Por exemplo, se você deseja excluir uma conta de usuário que não existe mais ( nonexistent-user) e executar o comando

sudo deluser nonexistent-user

apenas informará que esse usuário não existe.

Sam Hamblin
fonte
+1 Dessa maneira, é simples, é o que os usuários mais experientes realmente fazem e acho que não é menos robusto do que os métodos que verificam uma variedade de UIDs. Parece menos provável que um usuário humano tenha um diretório pessoal fora /home(que não é vinculado a /home) do que um usuário humano tenha um UID abaixo de 1000 (afinal, esse é o método mais comum para impedir que um gerente de exibição liste um usuário na tela de login, que às vezes pode ser feito para um usuário humano). A única desvantagem relativamente menor aqui é que lost+foundserá listada em sistemas com /homepartições separadas .
Eliah Kagan
Pequeno problema: o que acontece se o usuário foi criado useradd --no-create-home username?
Sergiy Kolodyazhnyy 01/05/19
@Erg Acho que tudo se resume à ambiguidade inerente na descrição do problema. Uma conta sem diretório inicial realmente representa um usuário humano? Na prática, essas contas são geralmente - embora nem sempre sejam reconhecidas - usadas para tarefas altamente especializadas (geralmente por pessoas com suas próprias contas separadas) ou para usuários destinados a acessar o sistema apenas por meio de serviços restritos e específicos. É claro que há outro caso de uso para useradd --no-create-home- o diretório inicial pode já existir ou ser criado logo em seguida - mas o ls /homemétodo funciona bem nesses casos.
Eliah Kagan
4

Embora possa parecer uma idéia clara, na verdade há ambiguidade no significado de usuário humano . Uma conta de usuário é ocultada deliberadamente da tela de login porque é usada apenas para fins especializados (mas humanos), um usuário humano? E o ubuntuusuário (UID 999) no CD ao vivo? E as contas de convidado no Ubuntu são criadas on-the-fly e destruídas após o logout; eles são usuários humanos? Mais exemplos podem ser criados.

Portanto, é adequado que várias respostas não equivalentes tenham sido fornecidas. A solução de Saige Hamblin para executar ls /homeé o que as pessoas realmente fazem e, a menos que você esteja escrevendo um script, provavelmente deve usá-lo.

Tornando ls /homemais robusto

Mas talvez você tenha usuários que foram removidos, mas cujos diretórios pessoais ainda existem /home, e evite listá-los. Ou talvez por algum outro motivo, você deve garantir que apenas as entradas /homecorrespondentes a contas reais sejam listadas.

Nesse caso, sugiro passando os nomes de tudo em /homeque getent(para recuperar as passwdentradas de usuários com esses nomes), apenas o campo de nome de usuário, em seguida, isolado e display (com grep, sedou awk, de acordo com sua preferência). Qualquer um deles fará:

getent passwd $(ls /home) | grep -o '^[^:]*'
getent passwd $(ls /home) | sed 's/:.*//'
getent passwd $(ls /home) | awk -F: '{print $1}'

Isso deve funcionar bem, pois você não deve ter contas de usuário com espaços em branco ou caracteres de controle em seus nomes; não pode, sem reconfigurar o Ubuntu para permitir ; e se o fizer, você terá problemas maiores. Portanto, os problemas usuais com a análise lssão inaplicáveis. Mas mesmo que esteja tudo bem aqui, se você considerar substituições de comando com lsesteticamente desagradável ou apenas um mau hábito, você pode preferir:

getent passwd $(basename -a /home/*) | grep -o '^[^:]*'
getent passwd $(basename -a /home/*) | sed 's/:.*//'
getent passwd $(basename -a /home/*) | awk -F: '{print $1}'

Eles não acomodam espaços em branco nem caracteres de controle. Eu os forneço apenas porque $(ls /home)parece errado, mesmo quando está certo, e, assim, atrapalha muitos usuários da maneira errada. Na maioria das situações, existem boas e reais razões para evitar a análisels e, nessas situações, a análise basename -ageralmente é apenas um pouco menos ruim. Nessa situação, no entanto, devido à limitação de quais caracteres podem ocorrer praticamente nos nomes de usuários , os dois estão bem.

Explicação, Benefícios e Desvantagens

Uso getentprincipalmente porque ele aceita nomes de usuário como argumentos para restringir sua saída, mas também porque é um pouco mais universal do que examinar /etc/passwddiretamente, caso as instalações de autenticação e o banco de dados de senhas sejam fornecidos pelos serviços de rede.

Esse método tem o benefício adicional de ls /homeque, em sistemas com uma /homepartição separada , lost+foundgeralmente aparece na saída de ls /home.

  • Com o método mais robusto apresentado acima, lost+foundsó aparecerá se houver um usuário (humano ou não) chamado lost+found, o que é improvável.
  • Mas se você estiver digitando comandos interativamente, em vez de escrever um script, tudo bem ls /home- você sabe que não tem um usuário humano chamado lost+found.

Raramente, esse método (em qualquer uma das variações acima) produzirá resultados insatisfatórios:

  • Se o diretório pessoal de um usuário existir fora /homeou não existir , isso sugere, mas não implica que a conta não deva ser considerada um usuário humano. Este método lista apenas os usuários quando existe um diretório com o mesmo nome /home.
  • Se você criou diretórios adicionais no diretório pessoal de /homeninguém e eles têm o mesmo nome que um usuário não humano existente - ou consistem em palavras separadas por espaço em branco, um ou mais deles têm o mesmo nome como usuário não humano existente - alguns usuários não humanos podem ser incluídos na saída.
    (Esse método pode ser implementado com um loop e getentinvocações separadas , portanto, a divisão de palavras não produz resultados espúrios. Mas a complexidade não é garantida; fundamentalmente, se você usar /homecomo algo diferente de um local para os diretórios pessoais dos usuários, esse método será não produza uma saída confiável.)

Simplificando a verificação de UID

Se você optar por um método que verifique os IDs de usuário para garantir que eles estejam no intervalo provável de contas que representam seres humanos, como na resposta aceita ou na resposta de Oli , sugiro isso por uma questão de brevidade:

getent passwd | grep -oP '^[^:]+(?=:x:\d{4}:)'

Isso usa uma expressão regular Perl ( -P) para mostrar:

  • texto no início de uma linha ( ^) que não contém :s ( [^:]+) - este é o primeiro campo, assim como :o separador de campos empasswd
  • que precede, mas não inclui ( (?= )) o campo de senha x- sempre deve ser x, pois no Ubuntu os hashes de senha são armazenados no shadowbanco de dados, não no passwdbanco de dados legível pelo mundo
  • e um campo UID que consiste exatamente em 4 dígitos ( :\d{4}:).

Essa é, portanto, uma variante significativamente mais curta e um pouco mais simples da técnica na resposta aceita . (A técnica descrita lá também funciona bem e tem o benefício de ser portátil para sistemas não-GNU / Linux grepque não suportam -P.)

Reconsiderando a faixa UID "Humana"

Se você deseja acomodar UIDs muito altos e procurar nobodyexplicitamente, pode usar o método na resposta de Oli . Você pode considerar, no entanto, se usuários com UIDs muito altos realmente devem ser considerados humanos, ou se é mais provável que sejam outros usuários não humanos para fins especiais (como nobody). Na prática, esses usuários - além de - nobodysão incomuns, então, na verdade, essa é uma decisão de sua parte.

Um possível comprometimento é listar usuários no intervalo de UIDs que estão sendo atribuídos a usuários recém-criados que não são do "sistema". Você pode verificar isso emadduser.conf :

$ grep -E '^(FIRST|LAST)_UID' /etc/adduser.conf
FIRST_UID=1000
LAST_UID=29999

Aqui estão duas maneiras de listar usuários cujos UIDs variam de 1000 a 29999:

getent passwd | grep -oP '^[^:]+(?=:x:[12]?\d{4}:)'
getent passwd | awk -F: '999<$3 && $3<30000 {print $1}'
Eliah Kagan
fonte
Se você quer ser estilisticamente agradável, basenameé feio. Não é melhor que ls. A principal razão pela qual não analisamos é que é um trabalho que pode ser feito por outras ferramentas de maneira muito mais segura e limpa, sem estilo. Neste caso, o shell: cd /home; getent passwd *.
Muru
Concordo que você não seja confiável em casa (é inútil para mim, veja minha resposta). Só estou dizendo que, se você vai pregar sobre estilo, espere um pouco.
Muru
@muru Vejo como meu fraseado original pode induzir as pessoas a pensar que evitar a análise lsgeralmente é sobre estilo. O segundo ponto sobre "resultados insatisfatórios" abordou a questão, mas aparece em uma seção posterior. Eu reformulei para esclarecer por que a análise lsé apropriada nessa situação . Embora cd /home; getent passwd *assuma uma forma geralmente indicativa de uma abordagem mais sólida, eu a evitei para não levar os leitores a acreditar que o conteúdo dos /homediretórios, com entradas adicionadas estranhas que não correspondam a usuários reais, ainda pudesse ser de alguma forma considerado como um guia para o que existem usuários.
Eliah Kagan
1

TL; DR : somente usuários humanos têm SystemAccount = false

Uma outra maneira é listar a saída enquanto ignora o root ls /var/lib/AccountsService/users/ | grep -v root. Agora, existe uma peculiaridade - gdm, uma tela de boas-vindas / login (ou, mais formalmente, gerenciador de desktop) também é listada como usuário. Então, apenas a partir da lista, não podemos dizer se o gdm é humano ou não.

Uma abordagem mais eficiente e correta é pesquisar os arquivos nessa pasta e descobrir quais usuários estão listados como tendo SystemAccount=false. O one-liner abaixo alcança que

grep SystemAccount=false /var/lib/AccountsService/users/* | awk -F '/' '{gsub(":","/");print $6}'

Sergiy Kolodyazhnyy
fonte
1
Embora às vezes útil, isso falha em alguns cenários relativamente comuns. Por exemplo, no meu sistema mínimo Ubuntu 15.04 (instalado a partir mini.isoe sem gerenciadores de tela ou X11 instalado), tenho uma conta de usuário humano - ainda /var/lib/AccountsService/usersé um diretório vazio. Eu espero que isso também não funcione em uma instalação pronta do Ubuntu Server. Além disso, quando isso funciona, o faz sob uma noção um tanto restritiva do que torna uma conta de usuário "humana": tornar um usuário com useradd, mesmo sem --system , não cria um arquivo AccountsService/users.
Eliah Kagan
1

Juntando-me à parte, supervisiono os sistemas de rede usando LDAP, tendo diretórios /homepessoais externos e UIDs (devido a uma falha de script) na casa dos milhões. Nenhuma das respostas atuais, portanto, funciona. O teste que funciona para mim é verificar se o usuário possui um shell de login válido. Um shell válido é aquele listado em /etc/shells. A forma mais simples:

getent passwd | grep -wFf /etc/shells

O arquivo pode conter comentários (ou linhas vazias); portanto, pode ser necessário filtrá-los:

getent passwd | grep -wFf <(grep '^/' /etc/shells)
muru
fonte
+1 Essa pode ser a abordagem mais robusta sugerida até o momento. Embora tenha a desvantagem de mostrar root(que provavelmente não deve ser considerado um usuário humano, uma vez que os humanos geralmente se tornam raiz temporariamente e para fins específicos, em vez de usá-lo em seu trabalho regular), parece que é o menos provável que isso ocorra de qualquer maneira importante. Os métodos em outras respostas (incluindo as minhas) podem falhar, dependendo do método, se os diretórios pessoais não estiverem em/home , outros tipos de lixo é no /home, UIDs são estranhos, ou o sistema não usa um DM. Essa resposta funciona muito bem em todos esses cenários.
Eliah Kagan
1

Nos sistemas buntu, usuários regulares (usuários humanos, ou seja) têm UIDs começando com 1000, que são atribuídos sequencialmente a eles quando suas contas são criadas. O que tudo isso se resume é que a primeira conta criada em um sistema Ubuntu possui um UID de 1000. A próxima criada tem um UID de 1001. E assim por diante.

Portanto, na minha opinião, a maneira mais simples de listar todas as contas de usuários humanos presentes no sistema é verificar se a terceira coluna no /etc/passwdarquivo que contém o UID do usuário é maior ou igual a 1000 e menor que, digamos, 2000 (é muito improvável que um PC de mesa típico tenha mais de mil contas de usuário, não acha?):

$ awk -F$':' '{ if ($3 >= 1000 && $3 < 2000) print $1; }' /etc/passwd
misha
fonte
Obrigado por explicar a resposta de Oli com detalhes. Você também precisa filtrar nobody. =)
anatoly techtonik
1
Você não precisa, porque ninguém tem um UID de 65534 e, portanto, é automaticamente filtrado como todas as outras contas de usuário não humanas.
Misha