使用以下方法分配用户的辅助组列表时:

# usermod -G <grouplist> <user>


是否可以强制该组分配在不注销所有正在运行的会话的情况下生效?

这在存在许多正在运行的Shell的Screen会话的情况下非常有用,因为本质上需要破坏整个会话以使组分配生效。

我想我可以更改使用newgrp命令在运行的外壳程序中创建用户的主要组-是否有一些替代方案可用于次要组?

理想情况下,我希望某些东西可以在每个shell中生效,而不必在每个shell中手动运行,但是如果失败了,也许可以通过某种方式强制Screen在每个shell中执行相同的命令。 />

评论

我知道,至少对于某些窗口/会话管理器而言,这样做是可能的,这样会话可以选择新组,并且可用于从菜单,面板按钮或其他任何开始的任何新进程。我刚刚来到这里只是想再次找到它,所以现在不能说怎么做,这可能是特定于窗口管理器的。

#1 楼

骇人听闻,但您可以使用两层newgrp来实现特定组的功能:

id -g


...将为您提供当前的主要组ID。在本示例中,我们将其称为orig_group
然后:

newgrp <new group name>


...会将您切换到该组作为主要组并添加到groupsid -G返回的组列表中。
现在,进一步:

newgrp <orig_group>


...将为您提供一个外壳,您可以在其中使用查看新组,而主要组是原始组。

这太可怕了,一次只能为您添加一个组,但是它帮助了我几次,却没有添加组注销/进入我的整个X会话(例如,将熔丝作为一个组添加到用户,以便sshfs可以工作)。

编辑:这也不需要您输入密码, su将。

评论


我发现做newgrp <新组名>就足够了。这是Ubuntu 14.04

–爱德华·福克
16年3月18日在21:42

@EdwardFalk正确,但您不想(可能不希望)将该组作为主要人员...

– mimoralea
16年5月26日在22:08

请注意,每个newgrp都会创建一个新的shell,因此当您需要从会话中完全退出时,您需要执行“ exit exit exit”来完全退出(:

– jwd
17年1月4日在17:45



有关如何在脚本中执行此操作,请参见stackoverflow.com/a/10080117/925978。您需要heredocs。

–crockeea
19年5月1日在21:58

@jwd您可以避免退出;出口;退出,您可以使用exec替换当前的shell,例如exec newgrp new_group,然后使用exec newgrp orig_group。

–塔卡罗伊
19年9月6日在6:41

#2 楼

从外壳程序内部,您可以发出以下命令

su - $USER



id


评论


我认为这在许多情况下是最好的方法,但是原始海报确实希望在屏幕会话中更新多个外壳。该解决方案将在每个外壳上完成。

–阿德里安·拉特纳帕拉(Adrian Ratnapala)
2011-12-13 8:57

原始解决方案也只能修复屏幕中的单个shell会话。我刚刚测试过。该解决方案有效的原因是因为您正在生成一个完整的新会话,而不是从原始环境继承。

– Dror
2014年2月6日5:24



您可以使命令更加通用,例如:su-$ USER

– bmaupin
15年3月26日在22:32

但是,这需要您输入密码,如果尝试在多个会话中输入密码,可能会很尴尬/不想要。

– Legooolas
16年4月15日在13:20

您能解释一下这是什么吗?为什么会更好或与其他解决方案(例如newgrp-和exec su -l $ USER)的区别也将是很棒的。

– Pablo A
17年7月23日在17:32

#3 楼



exec su -l $USER


我想我会把它张贴在这里,因为我每次忘记如何做时,这是第一个链接出现在Google中。

评论


+1用于不将用户置于子外壳中;您可以像往常一样注销/退出。另外,如果在/ etc / sudoers中设置了NOPASSWD:,则可以改用exec sudo su -l $ USER以避免提示输入密码。

–伊凡X
2014年8月9日15:06

请注意:系统将要求您输入sudo密码。如果弄错了,终端将关闭。

–泰勒·科利尔(Tyler Collier)
15年2月26日在18:57

@TylerCollier Ivan确实提到了NOPASSWD:

– pepoluan
16 Dec 16'在15:27

这仅适用于交互式外壳,如果尝试在运行此命令后立即将其放入bash.sh脚本中,则脚本将停止。关于这个相关问题,unix.stackexchange.com / questions / 18897 /…,吉尔斯指出,这只是Linux进程的工作方式。 Ansible将允许您刷新组,但它仅适用于ssh连接,不适用于localhoststackoverflow.com/questions/26677064/…对于localhost,我已通过使用EC2的Userdata在我的首次登录前预添加组来解决了该问题。

–neokyle
19年12月30日在4:15

有两个注意事项:(1)运行此命令后,无法在此Shell中打开X应用程序[Archlinux,Surface Book 2]。 (2)这仅适用于当前shell。否则,这是一个很好的解决方案。

–errolflynn
5月4日20:55



#4 楼

1.使用新组的外壳程序而无需注销并再次登录
如果仅添加一个组,则使用以下命令:
exec sg <new group name> newgrp `id -gn`

这是Legooolas的两个版本的变体,层newgrp技巧,但它是一行,不需要您手动输入主组。
sg是newgrp,但接受以新组ID执行的命令。 exec意味着新的Shell会替换现有的Shell,因此您无需两次“注销”。
与使用su不同,您无需输入密码。它还不会刷新您的环境(除了添加组之外),因此您将保留当前的工作目录等。
2。在会话的所有Screen窗口中执行命令
Screen中的at命令在您指定的任何窗口中运行命令(请注意,这是Screen命令,而不是shell命令)。
您可以使用以下命令命令以将命令发送到所有现有的Screen会话:
screen -S <session_name> -X at \# stuff "exec sg <new_group_name> newgrp \`id -gn\`^M"

请注意,需要使反引号转义以使id在Screen会话中运行,而^ M可以使Screen进入“ enter”在命令末尾。
请注意,屏幕的stuff命令只是代表您键入命令文本。因此,如果其中一个屏幕窗口在命令提示符下具有半写命令或正在运行除外壳程序以外的应用程序(例如emacs,顶部),则可能会发生奇怪的事情。如果这是一个问题,我有一些想法:

要摆脱任何半写命令,可以在命令开头添加“ ^ C”。
避免运行在emacs窗口等中的命令,您可以要求`at'过滤窗口标题等(在上面的示例中,我使用“#”,它匹配所有窗口,但是您可以按窗口标题,用户等进行过滤)要在特定窗口(由窗口号标识)中运行命令,请使用以下命令:
screen -S <session_name> -p 0 -X stuff "exec sg <new_group_name> newgrp \`id -gn\`^M"


评论


真是个好答案。较小的更正:sg期望命令是单个参数,并且忽略其他参数(尝试sg some_group echo test)。所以sg new_group_name newgrp`id -gn`实际上等效于sg new_group_name newgrp。它似乎起作用的原因是,在不带任何参数的情况下调用newgrp时,它使用/ etc / passwd中的默认组,该组通常与当前组匹配。解决方法是引用命令:sg new_group_name“ newgrp`id -gn`”

–tom
3月17日6:21



#5 楼

使用newgrp命令为我解决了问题:

newgrp <GroupName>


此博客文章有详细的说明。

评论


这是最好的答案!!!

– Alex
12月7日13:43

#6 楼

您可以执行此操作。

使用usermod -G添加任意数量的组。然后,作为具有正在运行的会话的用户,请仅使用'-'参数运行newgrp -

这会将组ID重新初始化为默认值,但同时也会设置辅助组。您可以通过在groupsusermod之前和之后从当前会话运行newgrp来验证这一点。

必须在每个打开的会话中运行-我对屏幕了解不多。但是,如果可以遍历所有打开的会话并运行newgrp,那应该很好。您不必担心知道组或组ID。

祝您好运。

评论


在X会话中的xterm上尝试过,但是没有用

–苦恼
2012年7月10日19:27

尝试在tmux中的一个会话上,它在那里也不起作用

–迈克尔
13年2月12日,下午3:32

在Amazon Linux 2上尝试过,它不起作用

–西里尔·杜尚(Cyril Duchon-Doris)
18 Mar 28 '18 at 14:53

newgrp-开始一个新的shell进程

– Piotr Findeisen
18年4月24日在13:05

根据您对Mister_Tom答案的评论,与其他所有答案一样,这是一种解决方法。 Mister_Tom的答案仍然正确。

–胆小
19/09/13在9:28

#7 楼

组通常是在登录时枚举的,我知道没有办法强迫它在不注销并重新登录的情况下重新进行组枚举。

这里投票的很多答案似乎都使​​用了一种解决方法调用具有新环境的新Shell(与再次登录相同)。通常,在干净注销并登录后,从新的shell重新调用之前,父shell和所有其他连续运行的程序通常不会获得新的组成员身份。

评论


说实话,我很确定这不是真的-之前我已经在Linux机器上找到了一种方法来做到这一点。但是,对于我的一生,我不记得命令是什么。如果找到它,我将其发布。编辑:刚找到它,我将其发布为答案。

–午餐
2012年1月30日在16:11



感谢您指出这一点,这也是我的理解。此处的所有其他答案都只是打开一个新的外壳程序,而不管它是替换一个打开的外壳程序还是重新启动屏幕等等。没有神奇的灵丹妙药可以发出命令或脚本,并且每个正在运行的会话(包括X会话)都可以反映新的组成员身份。

–胆小
19年9月13日在9:30

#8 楼

总结:

exec newgrp <newlyaddedgroupname1>
exec newgrp <newlyaddedgroupname2>
...
exec newgrp -


使用'exec'意味着用newgrp命令启动的新外壳替换现有外壳(因此退出新外壳会使您注销)。

需要最终的newgrp -来恢复正常的主要组,因此以后创建的文件将具有该组的所有者身份。

注意:原始发布者的问题是如何使新添加的组在现有过程中可见。 gpasswdusermod命令不会影响现有进程;新添加(或删除!)的组会出现在您的帐户中(或从中消失),即在/ etc / group和/ etc / gshadow文件中,但现有进程的权限不会更改。要删除权限,您必须终止所有正在运行的进程。 newgrp -将不会重新读取/ etc / group并重置组列表;相反,它似乎仅使用先前与该流程关联的组。

评论


顺便说一句,exec su-可以用来获取带有组设置的新登录shell,但是在脚本中不起作用,因为新的shell将从终端读取命令。您可以使用su -c“ command ...” 重新启动脚本,但是结果进程没有控制终端,因此,如果尝试使用屏幕编辑器或其他交互式命令,则会发生错误。

– Jimav
17-2-10在23:30



为什么这被否决?有人可以解释一下这是什么坏事,因为那是我的经历,我想我最喜欢它?

– jasonmp85
17 Mar 8 '17 at 0:02

Gah,我在测试前将其投票通过。 newgrp-不替换“主要组”。帕特里克·康海蒂(Patrick Conheady)的答案是最好的答案,因为它既不分叉也不改变主要群体。

– jasonmp85
17 Mar 8 '17 at 0:30

#9 楼

如果您有sudo,这可以解决问题,并且在某些情况下可以避免再次输入密码:

sudo su $USER


评论


唯一让我工作的原因是尝试让docker在不重新启动的情况下工作,因为我正在运行大量工作

–山姆·约翰逊(Sam Johnson)
3月11日1:57

#10 楼

我有类似的问题,但也适用于未登录的用户。重启nscd并没有帮助,但是执行以下命令可以:nscd -i group。那应该指示nscd(缓存守护程序)重新加载组文件。

#11 楼

我无法使newgrp命令正常工作。我不确定这是否取决于/ etc / sudoers,但是通常我必须输入sudo的密码,并且无需输入密码即可使用该密码:

[leo60228@leonix:~]$ groups
users wheel

[leo60228@leonix:~]$ sudo echo hi
[sudo] password for leo60228:
hi

[leo60228@leonix:~]$ sudo -k # reset sudo timeout

[leo60228@leonix:~]$ exec sudo -i -u $(whoami) # no password necessary

[leo60228@leonix:~]$ groups
users wheel docker


#12 楼

要重新生成终端但保持GUI应用程序正常运行,请尝试exec su -p $USER。这样可以保留环境变量(包括Xorg的东西),但可以重新加载组。
也可以删除exec以生成子shell,而不是替换当前的shell。

评论


有趣!这是为数不多或唯一的会话,不会产生新的会话。

–弗兰克·诺克(Frank Nocke)
12月26日晚上11:24

#13 楼

我需要在shell脚本中执行此操作(脚本将当前用户添加到组中,然后运行需要该组成员身份的命令)。 newgrp命令很脆弱,因为它只能运行一个新的外壳程序,而不能运行一个任意命令(我想使用原始命令行参数重新运行当前的外壳程序脚本)。

这是我的解决方案,它使用很多bash-isms :(请注意,周围的脚本需要某种分支才能仅在所需组当前未处于活动状态时才运行此功能):

(注意:该脚本暗示其运行了sudo adduser $user docker,这意味着它也可以只在所有地方而不是sudo docker处运行docker,但这在这种情况下是不希望的)。

 # 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=""
  local command="q4312079q"
  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"
}
 


#14 楼

如果需要保留环境变量,请尝试exec sudo -E -u "$USER" "$SHELL"exec用新的外壳替换当前的shell,-E保留环境,-u "$USER"将用户更改为您自己,$SHELL指定该外壳是要使用的命令。

#15 楼

已经有很多正确的答案,但是,这对我在基于Debian的系统上很好用:
sudo -s -u ${USER}

此命令将在sudo环境中完成此工作。
-s标志运行外壳程序按照/ etc / passwd文件中的配置。

#16 楼

可接受的答案是正确的,但这仅对交互式shell有用,并且在脚本中不起作用。
为了解决这个问题,我使用了以下方法:
newgrp <GroupName> << END
my_command
END

这将打开与更新的组,运行命令,然后将您带回到第一个会话,您仍不在该组中。
这将允许您创建组并在同一脚本中使用它。