Вопрос или проблема
Установка переменной USERNAME в zsh не имеет эффекта. Обращение к переменной всегда возвращает текущего вошедшего пользователя.
james@localhost:~$ USERNAME=foo
james@localhost:~$ echo $USERNAME
james
Я не смог найти ссылок или документации, которые объясняют это поведение. Похоже, что $USERNAME – это своего рода специальная переменная. Есть ли другие? Где это задокументировано или объяснено?
Похоже, вы используете Z Shell, по крайней мере, описанное вами поведение воспроизводимо там:
zsh$ echo $USERNAME
user1
zsh$ USERNAME=test
zsh$ echo $USERNAME
user1
zsh$
В мануале zshparam дается причина:
USERNAME
Имя пользователя, соответствующее реальному идентификатору пользователя процесса оболочки. Если у вас достаточно полномочий, вы можете изменить имя пользователя (а также идентификатор пользователя и идентификатор группы) оболочки, присвоив это параметру.
Также (при наличии достаточных полномочий) вы можете запустить одну команду под другим именем пользователя (а также идентификатором пользователя и идентификатором группы), используя ‘(USERNAME=username; command)’.
Таким образом, при достаточных полномочиях, например, как root, это работает, но только если user1
является действительным именем пользователя:
su
zsh# echo $USERNAME
root
zsh# USERNAME=user1
zsh# echo $USERNAME
user1
zsh# id
uid=1001(user1) gid=1000(users)
groups=1000(users),...
Да, есть и другие специальные переменные, обратите внимание на маркировку <S>
в man zshparam
, чтобы упомянуть лишь несколько примеров:
$?
код завершения, возвращаемый последней командой$$
идентификатор процесса этой оболочки$EGID
эффективный идентификатор группы процесса оболочки$SECONDS
количество секунд с момента вызова оболочки
Переменные USER и LOGNAME рассматриваются в мануале environ(7). login(1) — это процесс, который устанавливает эти переменные.
Переменные USER и LOGNAME могут быть изменены, и последующий доступ возвращает новое значение.
Нигде не нашел ссылки для USERNAME, и эта переменная не установлена в bash 4.3. Bash определяет UID как переменную только для чтения. Попытка изменить эту переменную в bash не удалась.
linux manpage говорит, что USER “используется некоторыми программами, основанными на BSD”, в то время как LOGNAME “используется некоторыми программами, основанными на System-V”, а apple manpage утверждает, что USER устарел.
Ответ или решение
Установка переменной USERNAME
в оболочке Zsh не оказывает эффекта, так как эта переменная является специальной и связана с идентификатором пользователя, который запустил оболочку. Давайте рассмотрим эту проблему более подробно.
Пояснение поведения переменной USERNAME
Когда вы задаете значение переменной USERNAME
, как в вашем примере:
USERNAME=foo
echo $USERNAME
Вы получаете james
, потому что переменная USERNAME
в Zsh автоматически связывается с фактическим именем пользователя, который запустил текущую оболочку. Это поведение зафиксировано в документации, где указано, что USERNAME
соответствует имени пользователя, соответствующему реальному идентификатору пользователя процесса оболочки.
Цитата из документации
В соответствии с мануалом zshparam
:
USERNAME: Имя пользователя, соответствующее реальному идентификатору пользователя процесса оболочки. При наличии достаточных привилегий вы можете изменить имя пользователя (а также идентификатор пользователя и группу) оболочки, присвоив это значение.
Это означает, что в обычном режиме, без соответствующих привилегий (например, в качестве пользователя root
), вы не сможете изменить значение USERNAME
.
Пример с повышенными привилегиями
Если вы получите доступ к оболочке от имени пользователя с достаточными правами (например, root
), вы сможете изменить USERNAME
:
su
echo $USERNAME
root
USERNAME=user1
echo $USERNAME
user1
id
Здесь id
показывает, что идентификатор пользователя изменился на user1
, так как мы используем root
.
Другие специальные переменные
Существуют и другие специальные переменные в Zsh, которые имеют фиксированные значения. Они отмечены знаком <S>
в документации. Примеры таких переменных:
$?
— статус завершения последней команды.$$
— идентификатор процесса текущей оболочки.$EGID
— эффективный идентификатор группы процесса оболочки.$SECONDS
— количество секунд с момента запуска оболочки.
Переменные USER
и LOGNAME
В отличие от USERNAME
, переменные USER
и LOGNAME
могут быть изменены и новое значение будет доступно. Эти переменные используются различными программами, и их поведение более предсказуемо.
Документация по этим переменным можно найти в environ(7)
. Процесс login(1)
устанавливает эти переменные при входе в систему.
Заключение
Таким образом, переменная USERNAME
в Zsh играет особую роль и не подлежит изменению в обычных условиях. Если требуется управлять переменными пользователя, возможно, стоит обратить внимание на использование USER
и LOGNAME
, которые более гибкие в этом отношении.