I needed to do this in a shell script (script adds current user to a group, runs later commands that require that group membership). The newgrp
command is brittle in that it can only run a new shell rather than an arbitrary command (I want to re-run the current shell script with original commandline args).
Here's my solution, which uses lots of bash-isms: (note the surrounding script needs some sort of branch to only run this function if the required group is not currently active):
(note: the script implies that it ran sudo adduser $user docker
, which means it could also just run sudo docker
everywhere instead of docker
but that was undesirable in this case)
# save these for later
ORIGINAL_ARGS=("$@")
# This function is a little insane. The problem is this: user running
# this script is not a member of docker group, but used 'sudo' to add
# themselves to group. Without logging out and back in, the only way
# to gain access to that group is via the 'newgrp' command, which
# unfortunately starts a new shell rather than an arbitrary command...
#
# Also, we're going to newgrp twice: first to add the new group and
# again to restore the original group (but the new group remains in
# the 'groups' output).
#
# So this horrendous hack dups stdin to fd3 for later. Then runs
# 'newgrp' piping in a script that runs 'newgrp' a second time, piping
# in another script that restores stdin from fd3 and execs the
# original command...
restart-newgrp-newgrp() {
# dup original stdin to fd3
exec 3<&0
local group="$1"
local command="$0"
local arg
for arg in "${ORIGINAL_ARGS[@]}"; do
printf -v command "%s %q" "$command" "$arg"
done
# restore original stdin from fd3; also replace any single-quote in
# command with '"'"' to embed it in a single-quoted string
local script
printf -v script "exec newgrp %q <<<'exec <&3-; exec %s'" "$(id -gn)" "${command//\'/\'\"\'\"\'}"
exec newgrp "$group" <<<"$script"
}
I know that at least for some window / session managers it's possible to do this such that the session picks up the new group and it's available to any new processes started from the menus, panel buttons or whatever. I came here just now looking to find that again, so can't say just now how to do it, and it's probably specific to the window manager. – mc0e – 2015-11-09T14:27:17.137