Я часто хочу получить имя для входа в систему, связанное с идентификатором пользователя, и, поскольку это часто встречается, я решил написать для этого функцию оболочки. Хотя я в основном использую дистрибутивы 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 в имена для входа. Ответ Жиля - более прямой и эффективный способ сделать это.