Я часто хочу отримати ім’я для входу, пов’язане з ідентифікатором користувача, і тому що це, як виявилося, є звичайним випадком використання, я вирішив написати функцію оболонки для цього. Хоча я в основному використовую дистрибутиви GNU / Linux, я намагаюся писати свої сценарії, щоб вони були максимально портативними і перевіряли, що те, що я роблю, сумісне з POSIX.
Розбираємо /etc/passwd
Перший підхід, який я спробував, був розбір /etc/passwd
(використання awk
).
awk -v uid="$uid" -F: '$3 == uid {print $1}' /etc/passwd
Однак проблема такого підходу полягає в тому, що входи можуть бути не локальними, наприклад, автентифікація користувача може здійснюватися через NIS або LDAP.
Використовуйте getent
команду
Використання getent passwd
є більш портативним, ніж аналіз, /etc/passwd
оскільки це також запитує не локальні бази даних NIS або LDAP.
getent passwd "$uid" | cut -d: -f1
На жаль, getent
утиліта, схоже, не визначена POSIX.
Використовуйте id
команду
id
- це стандартизована POSIX утиліта для отримання даних про особу користувача.
Реалізації BSD і GNU приймають ідентифікатор користувача як операнд:
Це означає, що його можна використовувати для друку імені для входу, пов’язаного з ідентифікатором користувача:
id -nu "$uid"
Однак надання ідентифікаторів користувача як операнду не визначено в POSIX; він лише описує використання імені входу як операнда.
Поєднуючи все вищезазначене
Я розглядав можливість поєднання вищезазначених трьох підходів у щось подібне:
get_username(){
uid="$1"
# First try using getent
getent passwd "$uid" | cut -d: -f1 ||
# Next try using the UID as an operand to id.
id -nu "$uid" ||
# As a last resort, parse `/etc/passwd`.
awk -v uid="$uid" -F: '$3 == uid {print $1}' /etc/passwd
}
Однак це незграбно, неелегантно і - що ще важливіше - не надійно; він закінчується з ненульовим статусом, якщо ідентифікатор користувача недійсний або не існує. Перш ніж написати більш довгий і незграбний сценарій оболонки, який аналізує та зберігає статус виходу кожного виклику команди, я подумав, що запитаю тут:
Чи існує більш елегантний і портативний (сумісний з POSIX) спосіб отримання імені для входу, пов’язаного з ідентифікатором користувача?
getent
не id
поверне нічого, ні минуле першого матчу; Єдиний спосіб їх знайти - це перерахувати всіх користувачів, якщо це дозволяє база даних користувачів. ( /etc/passwd
Очевидно, шукаючи роботи для визначених там користувачів.)
/etc/passwd
і /etc/shadow
перевірив цей сценарій і перевірив, що обидва id
і так getent passwd
поводяться, як ви описуєте. Якщо на якомусь етапі я в кінцевому підсумку використовую систему, де користувач має декілька імен, я зроблю те саме, що ці системні утиліти і просто трактую перше виникнення як канонічне ім'я для цього користувача.
setuid(some_id)
, і немає жодної вимоги, яка some_id
може бути частиною будь-якої бази даних користувачів. З такими речами, як простори імен користувачів в Linux, це може стати несподіваним припущенням для ваших сценаріїв.
getpwuid()
функції, яка ls
використовує для перекладу UID для входу до імен. Відповідь Жиля - це більш прямий і ефективний спосіб досягти цього.