Problem :
When assigning a user’s secondary group list using:
# usermod -G <grouplist> <user>
is it possible to force this group assignment to take effect without logging out all running sessions?
This would be very useful in the situation where a Screen session exists with many running shells, as the entire session essentially needs to be destroyed to make the group assignment take effect.
I think I can change the user’s primary group in a running shell using the newgrp
command – is there some alternative that would work for secondary groups?
Ideally, I’d want something that would take effect in each shell without being run manually in every one, but failing that, maybe some way of forcing Screen to execute the same command in each.
Solution :
Horribly hacky, but you could use two layers of newgrp
to achieve this for a particular group:
id -g
…will give you the current primary group ID. We’ll call this orig_group
for the purposes of this example.
Then:
newgrp <new_group_name>
…will switch you to that group as the primary and add it to the list of groups returned by groups
or id -G
.
Now, a further:
newgrp <orig_group_name>
…will get you a shell in which you can see the new group and the primary is the original one.
This is horrible and will only get you one group added at a time, but it has helped me out a couple of times to get groups added without logging out/in my whole X session (e.g. to get fuse added as a group to a user so that sshfs will work).
Notes:
-
This doesn’t require you to type your password either, which
su
will -
Each call to
newgrp
launches a new shell (as a child of the current shell) -
The current shell can be “replaced” with the
exec
commandexec newgrp <new_group_name>
-
Using
exec
will resolve the caching issue for the current branch of thepstree
I.e. if you are logged in to a window manager, every new terminal you launch will be a child of an earlier branch than the one “corrected” by this exercise and will therefore inherit the cached gid map.
From inside a shell, you can issue the following command
su - $USER
id will now list the new group:
id
This nifty trick from this link works great!
exec su -l $USER
I figured I’d post it here as every time I forget how to do this, this is the first link that come up in google.
1. Getting a shell with the new group without logging out and in again
If you’re only adding one group, I used the following:
exec sg <new group name> newgrp `id -gn`
This is a variation on Legooolas’s two-layer newgrp trick, but it is in one line and doesn’t require you to manually enter your primary group.
sg
is newgrp but accepting a command to execute with the new group ID. The exec
means that the new shell replaces the existing shell, so you don’t need to “logout” twice.
Unlike using su, you don’t need to type in your password. It also doesn’t refresh your environment (other than adding the group), so you retain your current working directory etc.
2. Executing the command in all Screen windows in a session
The at
command in Screen runs a command in whatever windows you specify (note this is a Screen command, not a shell command).
You can use the following command to send the command to all an existing Screen sessions:
screen -S <session_name> -X at # stuff "exec sg <new_group_name> newgrp `id -gn`^M"
Note the need to escape the backticks to get id
to run in the Screen session, and the ^M to get Screen to hit ‘enter’ at the end of your command.
Note also that screen’s stuff
command simply types the command text on your behalf. Therefore something strange may happen if one of the screen windows has a half-written command at a command prompt or is running an application other than a shell (e.g. emacs, top). If this is an issue, I have some ideas:
- To get rid of any half-written command, you can add “^C” to the start of the command.
- To avoid running the command in an emacs window, etc, you could ask `at’ to filter on window title etc (in the example above, I use “#”, which matches all windows, but you can filter by window title, user, etc).
To run the command in a specific window (identified by window number), use the following:
screen -S <session_name> -p 0 -X stuff "exec sg <new_group_name> newgrp `id -gn`^M"