так как соединение ssh
повторно использовало какой-то процесс со старыми настройками группы
После того, как вы упомянули совместное использование SSH-соединения, становится очевидным, что это виновник. Чтобы понять проблему, давайте посмотрим, как процесс в Linux несет информацию о своем владельце.
Порождая новые процессы
Все процессы происходят от процесса с PID 1 (init
upstart
или systemd
, Который принадлежит пользователю root
. Процесс может дублировать себя, смотрите man 2 fork
; или он может заменить свой собственный образ другим, см. man 3 exec
. Обычный способ для программы A порождать программу B - это разветвление, поэтому временно существует два экземпляра A , а затем exec для B (новый A становится B). Теперь есть A (родительский процесс) и B (дочерний процесс).
Каждый процесс несет информацию о своем владельце и группах, см. man 2 getuid
, man 2 getgid
, man 2 getgroups
. Когда порождается дочерний процесс, он обычно наследует эту информацию.
Чтобы создать процесс, принадлежащий пользователю, отличному от root
, в какой-то момент привилегированный процесс должен сменить своего владельца. Он использует setuid(2)
, setgid(2)
, setgroups(2)
и аналогичные для достижения этой цели. Обычно задается желаемый UID, и из него выводятся группы (включая дополнительные группы). Это момент, когда новая группа становится активной.
После запуска непривилегированного процесса его дочерние элементы (если таковые имеются) просто наследуют информацию, не запрашивая ОС для текущего набора групп, к которым принадлежит пользователь. В этот момент новая группа не может стать активной. Есть исключения: такие программы, как su
, sg
или sudo
с установленным флагом и принадлежащие пользователю root
запускаются как привилегированные. После того, как они удостоверились, что пользователю разрешено выполнить действие, ситуация идентична уже обсужденной, где новая группа становится активной.
Поэтому su - myuser
замечает новую группу, потому что она меняет пользователей за кулисами. Получение текущего набора групп, к которым принадлежит пользователь, является частью этого процесса.
С другой стороны, id
показывает, что он унаследовал от оболочки. Эта информация старая; это время, когда его привилегированный предок манипулировал своим идентификатором пользователя.
Примечание id myuser
заметит новую группу. Единственный id
извлекает информацию, связанную с ним (с помощью getgroups(2)
и т.д.), В то время как id myuser
запрашивает у ОС текущую информацию о выбранном пользователе.
Вывод таков: ваша оболочка (и ее дочерние элементы) заметят новую группу, если она является потомком какого-то привилегированного процесса, поэтому переход между пользователем root
и вашим пользователем произошел после добавления группы. (Формальное примечание: переход от root
к root
ничем не отличается; важен акт установки владельца заново).
На практике
/dev/tty2
или около того (без SSH)
Я могу войти через стандартную текстовую консоль (/dev/tty2
или около того). Соответствующая часть дерева процессов:
systemd───login───bash───pstree
^^^^^^^^^^^^^^^ these are owned by root
^^^^^^^^^^^^^ these are owned by my user
После того, как я добавлю своего пользователя в новую группу и войду в другой tty:
systemd─┬─login───bash
└─login───bash───pstree
^^^^^^^^^^^^^^^ these are owned by root
^^^^^^^^^^^^^ these are owned by my user
Поскольку второй bash
был создан после привилегированного login
после того, как я внес изменение, он будет знать о новой группе. В этом базовом случае работает подход "выйти и снова войти".
GUI (все еще без SSH)
Рассмотрим примерную часть дерева процессов:
systemd───plasmashell───konsole───bash
^^^^^^^ this is owned by root
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ these are owned by my user
После добавления моего пользователя в новую группу новая оболочка (новая вкладка) в konsole
не увидит изменения. И не будет xterm
, если я создам его из плазмы KDE (plasmashell
). Но если бы я войти через /dev/tty2
правильно установить и экспортировать переменную DISPLAY
затем икру xterm
оттуда, оболочка в xterm
будет видеть изменения. В обоих случаях xterm
отображается на том же рабочем столе KDE, но первый происходит (косвенно) из привилегированного процесса, который давно переключил пользователей, до изменения; последний происходит (косвенно) из привилегированного процесса, который переключил пользователей минуту назад, после изменения.
SSH
В моих ветках Debian sshd
(SSH daemon) снова и снова вилки, соответствующая часть дерева процессов выглядит так:
systemd───sshd───sshd───sshd───bash
^^^^^^^^^^^^^^^^^^^^^ these are owned by root
^^^^^^^^^^^ these are owned by my user
После того, как я подключился во второй раз, без совместного использования подключения:
systemd───sshd─┬─sshd───sshd───bash
└─sshd===sshd───bash───pstree
^^^^^^^^^^^^^^^^^^^^^ these are owned by root
^^^^^^^^^^^^^^^^^^^^ these are owned by my user
Предположим, я добавил своего пользователя в новую группу. Ссылка, которую я обозначил ===
означает, что какой-то привилегированный sshd
породил непривилегированный после изменения. Последний и его потомки знают о новой группе.
С подключением обмена это отличается:
systemd───sshd───sshd───sshd─┬─bash
└─bash───pstree
^^^^^^^^^^^^^^^^^^^^^ these are owned by root
^^^^^^^^^^^^^^^^^^^^ these are owned by my user
В этом случае новый bash
появился из старого sshd
принадлежащего моему пользователю. Этот sshd
содержит старую информацию о моих группах, новый bash
унаследовал ее.
Я верю, что то же самое происходит в вашем случае.
tmux
Проблема не ограничивается sshd
. Возьми tmux
. В общем случае использования tmux
, после входа пользователя tmux
может быть запущен непосредственно как оболочка входа или косвенно из (не tmux
) оболочки входа (вручную или как .bashrc
; с или без exec
). Инструмент подключается как клиент к серверу tmux
принадлежащему пользователю. Если для данного пользователя еще нет сервера, он будет запущен. Именно сервер запускает "финальную" оболочку. Дерево процессов может выглядеть так:
systemd─┬─login───bash───tmux: client
└─tmux: server─┬─3*[bash]
└─bash───pstree
После того, как я добавлю своего пользователя в новую группу, новый bash
созданный при login
, увидит группу. Новый сервер tmux
и его дети увидят его. Но уже работающий сервер tmux
и его дочерние элементы этого не делают; это верно даже для потомка (оболочки), порожденного после добавления моего пользователя в новую группу.
Для ясности: клиент и сервер tmux
не имеют ничего общего с клиентом и сервером SSH; они оба работают на одной машине. tmux
будет иметь значение только в том случае, если он запускается там, где было внесено изменение. Вы упомянули tmux
на стороне клиента SSH, а изменение было сделано на стороне сервера SSH; так что в вашем случае tmux
имеет значения.
Предположим, у меня есть tmux
где было сделано изменение. Чтобы новые оболочки внутри tmux
заметили новую группу, мне нужно завершить (не отсоединять, действительно выйти) все, что уже запущено внутри tmux
, так что мой сервер tmux
завершает работу, чтобы его можно было порождать заново. Убийство сервера должно работать, но это имеет очевидные недостатки.
Запуск отдельного сервера tmux
технически возможен. Если мне не нужно присоединяться к уже запущенному сеансу, это путь. Смотрите -L
и -S
в man 1 tmux
. Если tmux
запускается автоматически после входа в систему, мне может понадобиться обойти это, чтобы передать -L
, например:
ssh -t user@host tmux -L foo