Як я можу перерахувати всі імена користувачів та / або домашні каталоги?


16

Я хочу перерахувати всі користувачі бруду на машині. Зазвичай я зроблю:

ls -l /home

Але я використовую його в сценарії, який буде розгорнуто на інших машинах, і, можливо, на тих машинах вони не називають його додому (наприклад, myHome). Тому я хочу це узагальнити ls -l ~. Але він просто перераховує домашні dirs моїх користувачів замість всіх користувачів home dirs (в основному я хочу отримати список імен користувачів на машині). Як я можу це узагальнити?


19
Насправді немає жодної гарантії того, що всі домашні каталоги користувачів є підкаталогами будь-якого одного каталогу.
панно

17
@hobbs або що вони навіть існують, поки користувач не ввійде в систему. Це одна з тих, мабуть, простих проблем, які дуже швидко ускладнюються.
EightBitTony

11
Майте на увазі, що ~це, як правило, еквівалент /home/user, а не ( /homeабо, /home/*що здається, ближче до вашого наміру).
Етан Камінський

2
@EightBitTony: ... і немає ніякої гарантії , що домашній каталог існує взагалі . Наприклад, на моїй установці Ubuntu кілька користувачів системи (в тому числі nobody) встановили домашній каталог /nonexistent, який, очевидно, не існує. (Зрозуміло, для цих користувачів також встановлено хеш паролів *і встановлено оболонку /usr/sbin/nologinабо /bin/false, тому вони дійсно не можуть увійти в звичайний сенс для початку.)
Ілмарі Каронен

1
З іншого боку, сервер NFS (старої школи) може обслуговувати домашні каталоги для користувачів, яким невідомо відома його ОС.
rackandboneman

Відповіді:


45

Багато системи мають getentкоманду списку або запросити зміст Ім'я служби баз даних , таких як passwd, group, services, protocols...

getent passwd | cut -d: -f6

Буде перелічено домашні каталоги ( розділене 6- ою товстою кишкою) всіх користувачів у базах даних, які можна перерахувати .

Саме ім’я користувача знаходиться в першому полі, тому для списку імен користувачів:

getent passwd | cut -d: -f1

(зауважте, що це не означає, що ті користувачі можуть увійти до системи або створити їх домашній каталог, але те, що вони відомі системі, вони можуть бути переведені на ідентифікатор користувача).

Для баз даних, які неможливо перерахувати, ви можете спробувати запитувати кожен можливий ідентифікатор користувача окремо:

getent passwd {0..65535} | cut -d: -f1,6

(тут припускаємо, що uids зупиняються на 65535 (деякі системи підтримують більше) та оболонці, яка підтримує zsh- {x..y}форму розширення дужок). Але ви не хотіли б цього робити в системах, де користувальницька база даних є мережевою (і існує обмежене місцеве кешування), наприклад LDAP, NIS +, SQL ..., що може означати багато мережевого трафіку (і завантаження на сервер каталогів) ) зробити всі ці запити.

Це також означає, що якщо є кілька користувачів, які діляться одним ідентичним uid, ви отримаєте лише один запис на кожен uid, тому пропустіть інші.

Якщо у вас немає getent, ви можете вдатися до perl:

perl -le 'while (@e = getpwent) {print $e[7]}'

для getent passwd( $e[0]для імен користувачів) або:

perl -le 'for ($i=0;$i<65536;++$i) {
  if (@e = getpwuid $i) {print $e[0] ": " $e[7]}}'

для getent passwd {0..65535}з тими ж застереженнями.

У оболонках ви можете використовувати ~userдомашній каталог user, але в більшості оболонок це працює лише для обмеженого набору імен користувачів (список дозволених символів в іменах користувачів, що підтримуються для цього ~оператора розширення, варіюється від оболонки до оболонки) та з декілька оболонок (у тому числі bash) ~$userне працюватимуть (вам потрібно вдатися, evalколи ім’я користувача зберігається у змінній). І вам все одно доведеться знайти спосіб отримати список імен користувачів.

Деякі оболонки мають вбудовану підтримку, щоб отримати цей список імен користувачів.

  • bash: compgen -uповертає список користувачів у базах даних, які можна перерахувати.
  • zsh: $userdirsасоціативний масив відображає імена користувачів у їх домашній каталог (також обмежений базами даних, які можна перерахувати, але якщо ви зробите ~userрозширення для користувача, який знаходиться в нечисленній базі даних, до нього буде додано запис $userdirs). Отже, ви можете зробити:

    printf '%s => %s\n' "${(kv@)userdirs}"

    щоб перерахувати користувачів з їх домашнім каталогом.

    Це працює лише тоді, коли zshє інтерактивним .

  • tcsh, fishі yashце три інші оболонки, які можуть заповнювати імена користувачів (наприклад, при заповненні ~<Tab>аргументів), але це не виглядає так, що вони дозволяють отримати цей список імен користувачів програмно.


Завданням для ОП буде те, чи getentбуде вона там, що, певно, певною мірою залежить від сфери їх використання інших машин.
EightBitTony

1
@EightBitTony, я додав perlальтернативу.
Стефан Шазелас

1
На Mac це, мабуть, щось, що стосується Open Directory.
SilverWolf - Відновіть Моніку

@seaturtle, perl -le 'while (@e = getpwent) {print $e[7]}'чудово працює на macOS.
Стефан Шазелас

1
@FloHe, це імена користувачів. Більшість користувачів в системах Unix - це спеціальні користувачі системи, життя яких присвячено запуску системних служб. getent passwdпоказує вам базу даних користувачів. Перше поле - це ім'я користувача, 6-е поле - домашній каталог користувачів.
Стефан Шазелас

17

Кращий спосіб перерахувати домашні каталоги користувачів - проаналізувати /etc/passwdта витягнути їх звідти, а не робити жодних припущень щодо того, де вони можуть бути.

І судячи з вашого другого коментаря, ви насправді хочете імен користувачів, а не їхніх домашніх каталогів, і в цьому випадку /etc/passwdвсе-таки кращий вибір. Зауважте, що на деяких машинах Linux / UNIX будуть налаштовані інші механізми аутентифікації користувачів (наприклад, LDAP), і, в кінцевому підсумку, ваш запит складніший, ніж ви могли спочатку уявити, але /etc/passwdце хороше місце для початку.


9
Дивіться також getentпро системи, які його підтримують.
Kusalananda

6
Так, getentзавжди краще, ніж аналіз /etc/passwd(він вирішує проблему з "іншими механізмами аутентифікації користувача").
Стівен Кітт

@Kusalananda Проблема getentрішення полягає в тому, що він передбачає, що джерело даних може бути перераховано, а не просто запитуватися на певне значення. Це докладно в відповіді Стефана Шазеласа на це запитання , але я хоч би додав коментар для тих, хто переглядає цю сторінку.
Ендрю Генле

7

Коротка відповідь :

compgen -u

Відповідь носія : Оскільки ви користуєтесь bash, ви можете перелічити всі можливі доповнення для ~використання compgen -A user. Це таке звичайне використання, його можна скоротити compgen -u. Як оболонка вбудована, compgenне має власної сторінки людини. Натомість дивіться bash (1) для документації та читайте розділ Програмоване завершення .

Більш ретельна альтернатива

Якщо ви вкрай стурбовані портативністю, можливо, ви навіть не зможете розраховувати на наявність інших машин bash. У цьому випадку зробіть це:

(getent passwd ||
    dscl . -ls /Users dsAttrTypeNative:homeDirectory || 
    nidump passwd  ||
    cat /etc/passwd) 2>/dev/null  |  cut -d: -f6

Пояснення Довга відповідь пробує все, тому вона працюватиме майже на будь-якій системі UNIX, незалежно від того, використовує вона новішу /etc/nsswitch.conf (і GNU / Linux, і BSD getent), традиційний плоский файл UNIX passwd, MacOS Служби каталогів¹ ( dscl) або навіть старіші випуски MacOS X з котячими темами та NeXTSTEP ( nidump).

Простота Але, як вам потрібно портативний? У Unix є багато способів робити речі, а іноді і простіших достатньо. Якщо вам потрібно вибрати один, я рекомендую getent passwd | cut -d: -f6сценарії оболонки


Виноска ¹: Я трохи не використовував MacOS, тому якщо хтось може підтвердити мені, що я отримав правильний синтаксис (а вихідні дані не включають бродячих колонок, які б заплуталися cut), це було б чудово. Спасибі.

Виноска ²: Що я рекомендую і що я роблю, може відрізнятися. Особисто я частіше буду використовувати традиційне cut -d: -f1 /etc/passwdв командному рядку. Після десятиліть повторення мої пальці можуть набрати це, коли мій розум працює над іншими речами.


2
На всіх машинах Mac OS X гарантовано є баш, як це стосується системи. (Як і zsh та кілька інших снарядів.)
SilverWolf - Відновіть Моніку

Щоправда, але коли я використовував MacOS, Apple довго не оновлював bash, і мені завжди довелося замінити якусь крихку версію 3. Чи стало Apple краще в оновленні баш?
hackerb9


Щоправда, не думав про це. Моя версія bash (macOS Sierra 10.12.6) - 3.2.57. (:
SilverWolf - Відновіть Моніку

У всякому разі, bashбуло з compgen -uтих пір 2,04 випущений 2000 року
Stéphane Chazelas

2

Про що ls -l ~/..? Тут перераховані всі каталоги у батьківському домашньому каталозі.


4
Це працює лише в системах, де всі домашні каталоги базуються в одному каталозі, що не так багато (ви можете подумати, що /homeце звичайно для систем Linux, але що відбувається, коли ви запускаєте це як root?). Перерахування домашніх каталогів - це пригода, повна підводних каменів, якщо ви хочете вирішити всі випадки, з якими ви, швидше за все, натрапите, див. Інші відповіді для деталей.
Стівен Кітт

7
Це, мабуть, єдина відповідь на даний момент, яка прямо відповідає на сприйняту проблему ОП . Однак це не відповідає основній проблемі ОП .
труба

1
Цінність цієї відповіді полягає в розумінні того, що вона пропускає, і чому вона не настільки гарна, як інші відповіді з більш високим голосом.
Кріггі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.