如何在多用户的MacOS Sierra设置中使用Homebrew

103
我有一台Mac电脑,由两个工程师共享。 他们各自拥有不同的用户帐户。 两个人都需要偶尔运行brew updatebrew install...
我该如何设置才能避免出现像/usr/local must be writable!这样的错误?
当然,我可以让UserA在每次使用brew时取得对/usr/local的权限(UserB也是同样的),但这似乎很麻烦,而且没有必要。

10
被标记为被接受答案的回答是不恰当和安全实践差的。@user4815162342的下面的回答要明智得多。 - Wes Modes
4
请接受一个不同的答案,或者至少取消接受已接受的答案,以便可以删除它。 - Greenonline
10个回答

121

您还可以将组权限更改为管理员或另一个两个用户都在其中的组:

chgrp -R admin /usr/local
chmod -R g+w /usr/local

原始来源:https://gist.github.com/jaibeee/9a4ea6aa9d428bc77925

更新:

在macOS High Sierra中,您无法更改/usr/local的所有者、组或权限。因此,您必须更改子文件夹的组和权限:

chgrp -R admin /usr/local/*
chmod -R g+w /usr/local/*

更新 2018年9月,High Sierra 10.13.6

  1. 确定Homebrew存储文件时使用的路径,即brew前缀的路径
  2. 检查系统上所有需要访问brew的用户是否在admin组中
  3. 可选 将用户添加到管理员组中如果用户需要访问brew

    将需要访问/获得sudo命令的权限

  4. 将brew前缀路径递归地设置为admin组拥有
  5. 将brew前缀路径递归地设置为可以由所有在admin组中的用户进行写入操作
  6. 验证brew前缀的权限
  7. brew

echo $(brew --prefix)
echo $(groups $(whoami))
sudo dseditgroup -o edit -a $(whoami) -t user admin
sudo chgrp -R admin $(brew --prefix) 
sudo chmod -R g+rwX $(brew --prefix)
ls -lah $(brew --prefix)

1
我必须添加 sudo,否则我会收到 Operation not permitted 错误消息。 - FooBar
15
请勿添加sudo以避免出现Operation not permitted错误。在命令中添加/*,例如:sudo chgrp -R admin $(brew --prefix)/*来源 - Juan José Ramírez
4
这个解决方案是正确的,但是一些软件包可能会拒绝使用这样的权限。例如,Postgres 会报错:FATAL: data directory "/usr/local/var/postgres" has group or world access DETAIL: Permissions should be u=rwx (0700). - Leonel Galán
2
这个答案需要进行一些清理...最后的代码块是什么?还有更新吗? - n1000
3
当所有者和权限被调整时,zsh也会抱怨;每次启动新的shell时,compaudit都会出现错误。 - jerryb
显示剩余7条评论

106

尝试以黑客方式获取权限,或使用sudo的每个答案都是错误的。

不要使用sudo,也不要在用户帐户之间共享单个brew安装。

根据Homebrew文档,正确的答案是在一台机器上使用零个或一个全局brew安装,并为所有其他用户安装本地版本的brew。

这在Mac上特别重要,但Linux也适用。

可以通过以下任一方法完成:

  1. Git方法:对源代码库进行git checkout操作
  2. Untar-anywhere方法:将tarball扩展到某个目录中-该目录归您所有

Git方法

对于Git方法,您需要克隆brew

为了任意选择我的用户主目录进行检出:

cd $HOME
git clone https://github.com/Homebrew/brew.git
./brew/bin/brew tap homebrew/core

无处不Untar法

docs.brew.sh所述,在您的主目录中运行此命令,它将创建~/brew

cd $HOME
mkdir brew && curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C brew

结束

无论使用哪种安装方法,您都需要更改PATH以优先使用新的brew二进制目录,将类似以下内容添加到您的shell点文件中。

export PATH=$HOME/brew/bin:$PATH >> ~/.zshrc # or ~/.bashrc

然后运行此命令来重新加载和测试

exec $SHELL
which brew # see that brew is found in your path

由于这是新安装,您需要重新安装所有所需的brew软件包。


2
这对我有用,但在我的情况下必须使用https克隆存储库。 cd $HOME; git clone https://github.com/Homebrew/homebrew-core.git; git clone https://github.com/Homebrew/brew.git - Carlos Pinzón
1
@SebMa 完成了,如果我翻译得对,请告诉我。 - jerryb
5
从文档中翻译:选择另一个前缀,风险自负! - Clintm
6
我终于找到了一个例子,证明我的解决方案并不适用:nvm 不喜欢被放在 /usr/local/bin 之外,但是除此之外,使用这个解决方案多年来没有出现任何问题。 - jerryb
6
然而需要提到的是,这种方法是不受支持的,如果您在他们的错误跟踪器中提出任何问题,它们将被关闭甚至不会查看该问题,文档 https://docs.brew.sh/Installation#untar-anywhere-unsupported, https://docs.brew.sh/Installation#multiple-installations-unsupported 指出了这一点,并且它有一个缺点,即您安装的所有内容都将被编译,不能使用标准瓶子,因为瓶子假定标准brew位置为 /usr/local。 - user637338
显示剩余13条评论

48

为每个用户安装Homebrew

根据Homebrew文档,你可以将其安装在每个用户主目录下。

这样所有的软件包都会留在你的用户文件夹中,不会对其他用户可见或产生影响。一个好处是,如果你删除了该用户,则不会在系统上留下任何垃圾。因此,系统范围的污染最小化。

但是,如果你为多个用户安装相同的软件包,则需要使用更多的存储空间。如果你的SSD非常小,请注意这一点。

指令

  1. 如果你当前已经全局安装了Homebrew,我建议先卸载Homebrew。(你可以运行which brew查看Homebrew的安装位置)

  2. 如果你还没有安装命令行工具,请先运行以下命令:

    xcode-select --install
    
  3. 打开终端并运行:

    • MacOS Catalina 10.15 或更新版本:
  4. cd $HOME
    mkdir homebrew && curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C homebrew
    echo 'export PATH="$HOME/homebrew/bin:$PATH"' >> .zprofile
    
  5. 苹果操作系统Mojave 10.14或更早版本:
    cd $HOME
    mkdir homebrew && curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C homebrew
    echo 'export PATH="$HOME/homebrew/bin:$PATH"' >> .bash_profile
    
  6. 关闭终端窗口

  7. 再次打开终端,运行以下命令以确保您的安装是正确的:

  8. brew doctor
    
  9. 完成!


禁用自动更新

这不是必须的我发现在每次安装软件之前禁用brew自动更新所有软件也很有用。

  • MacOS Catalina 10.15或更新版本
    echo 'HOMEBREW_NO_AUTO_UPDATE=1' >> $HOME/.zprofile
  • MacOS Mojave 10.14或更旧版本
    echo 'HOMEBREW_NO_AUTO_UPDATE=1' >> $HOME/.bash_profile

4
这是唯一一个能够 1. 仅为当前用户安装brew且2. 正确设置PATH以便在重新启动后也能使用的答案!感谢Vitim! - Sliq
1
正如Homebrew安装文档所述:“在macOS Intel上,请将其安装到/usr/local,在macOS ARM上,请将其安装到/opt/homebrew,在Linux上,请将其安装到/home/linuxbrew/.linuxbrew”,并继续说“选择其他前缀是自讨苦吃!”因此,我不确定这种方法是否可行。 - Benji
3
我喜欢这个答案,因为它将brew保留在用户本地(不共享)。但是brew doctor返回以下内容。这是否符合预期?“警告:您的Homebrew前缀不是/usr/local。 一些Homebrew瓶(二进制包)只能与默认值一起使用 前缀(/usr/local)。 您将遇到某些配方的构建失败。 请创建拉取请求,而不是在Homebrew的GitHub上寻求帮助, Twitter或任何其他官方渠道。您负责解决 您在运行此时遇到的任何问题 不受支持的配置。” - hdsenevi
尽管这个答案很好,但它确实有其局限性。1. 如果在$HOME目录中使用多用户自制安装进行特定安装的隔离,并且想要在github actions中使用这样的安装,即homebrew的test-bot将无法执行标准设置的操作。这可以看作是homebrew提供的actions runner的一个限制,但是如果使用vanilla github actions和test-bot brew,则需要在/usr/local中安装brew。 - ipatch
1
我喜欢你包含了git的xcode步骤和brew doctor。 - jerryb

15

macOS Mojave 10.14的黑科技解决方案

这是user4815162342的答案的编辑版本,但它不能直接为我所用。

  1. 在“系统偏好设置”中,转到“用户与群组”,单击左下角的锁形图标以解锁用户/群组创建,然后创建一个名为brew-usergroup的新组。将所有使用brew的用户添加到该组中(如附带的来自德语macOS的截图所示)。

输入图像描述

  1. In terminal, do this:

     echo $(brew --prefix)
     echo $(groups $(whoami))
     sudo dseditgroup -o edit -a $(whoami) -t user brew-usergroup
     sudo chgrp -R brew-usergroup $(brew --prefix)/*
     sudo chmod -R g+rwX $(brew --prefix)/*
     ls -lah $(brew --prefix)
    
请注意,这不再更改brew文件夹的权限(与其他答案不同),而是更改brew文件夹的子文件夹/文件。 brew install 现在应该可以正常工作,没有错误。

3
看起来这是一个优雅的解决方案,但不幸的是它并不比为管理员执行相同操作(而不创建额外的组)更好。无论哪种方式,我都收到这些错误信息:cp:utimes:/usr/local/Cellar/readline/.:操作不允许 cp:chmod:/usr/local/Cellar/readline/.:操作不允许 - Tamas Kalman
1
我同意,我认为最好的方法是推动酿造开发者在核心层面解决整个问题! - Sliq
我刚刚遇到了相同的 cp: utimes: /usr/local/Cellar/XXX/.: Operation not permitted 错误,发现它是由一个组为 "staff" 而不是 "admin" 的文件夹引起的,尽管我运行了 chgrp -R admin /usr/local/... 很奇怪,但问题已解决 :) find /usr/local/ -not -group admin -ls 可能会有所帮助... - DrPsychick

12

Homebrew不适用于不同Unix用户之间的使用。来自常见问题解答:

如果您需要在多用户环境中运行Homebrew,请考虑创建一个专门用于Homebrew使用的单独用户帐户。

chmod解决方案不可行,除非您确保Homebrew前缀中每个新创建的文件也具有组写入权限,这在默认的umask下不是这种情况-或者除非您每次程序写入Homebrew前缀时都运行该 chmod 命令。

为每个用户维护单独的Homebrew安装可以解决权限问题,但会创建许多其他问题,这就是为什么Homebrew不推荐这样做的原因:

但请千万别自找麻烦,请使用安装程序将其安装到默认前缀中。在其他位置安装可能会导致某些内容无法构建。相对于竞争对手,Homebrew之所以正常工作的原因之一就是因为我们推荐在此处进行安装。你可以自由选择其他前缀,但后果自负!


为了方便官方推荐使用专用帐户运行Homebrew,您可以使用sudo轻松模拟该用户帐户。假设您将该用户命名为homebrew:

sudo -H -u homebrew brew update
  • -H 会确保将 HOME 设置为 homebrew 用户的主目录(例如:/Users/homebrew),以便 Homebrew 可以在那里进行其管理工作。
  • -u homebrew 告诉 sudo 模拟 homebrew 用户账户,而不是默认的 root

1
我也需要使用 -i 标志。为了经常使用,设置别名是有帮助的:alias brew='sudo -Hiu $HOMEBREW_MAIN_USER brew' - dijonkitchen
无法使用-i标志来允许无密码sudo - Míng
1
@Val,我很好奇为什么你没有链接你的https://www.codejam.info/2021/11/homebrew-multi-user.html文章。 - P i

12
上述方法可行,但如果您想让新文件自动继承这些权限,请设置一个可被继承的ACL(否则只有倒酒者可以删除它)。在此处找到如何执行此操作的提示:https://gist.github.com/nelstrom/4988643
作为root用户运行一次(假设“admin”组的所有用户都应该具有访问权限):
cd /usr/local
/bin/chmod -R +a "group:admin allow list,add_file,search,add_subdirectory,delete_child,readattr,writeattr,readextattr,writeextattr,readsecurity,file_inherit,directory_inherit" Homebrew Caskroom Cellar bin
/usr/bin/chgrp -R admin Homebrew Caskroom Cellar bin
/bin/chmod -R g+rwX Homebrew Caskroom Cellar bin
ls -lae .

ls命令中的-e选项可以显示ACL。

更新:现在我使用特定的目录(见上文),因为之前失败了(类似于内存不足)。


对于那些在 macOS 上安装了 GNU coreutils 的人,可能需要在前面添加 /bin/chmod - ipatch
太好了!我会试用一下。不过我很好奇,为什么您没有包括其他ACL,比如writesecurity(似乎是必需的,比如说让脚本可执行)。在进行了全新的Homebrew安装后,我最终使用了chmod -R +a 'group:admin allow readattr,writeattr,readextattr,writeextattr,readsecurity,writesecurity,list,search,add_file,add_subdirectory,delete_child,read,write,append,execute,file_inherit,directory_inherit' *命令来针对所有/usr/local目录进行操作。 - zigg

5
这是Homebrew维护者之一的官方答案
创建第三个管理员用户(例如homebrew),然后执行以下操作: sudo chown -R homebrew:admin /usr/local/*
然后,所有进一步的写操作(即安装、更新、升级等)应由其他用户作为该用户进行,通过su或sudo的权限,取决于您的偏好: su homebrew -c 'brew update'
在这方面,Homebrew和系统包管理器之间只有一个区别:前者允许您决定将所有权授予哪个用户,而后者将其固定为root。 我的建议 假设您已经拥有一个名为niki的管理员用户,他拥有/usr/local/*目录的所有权,并且您以另一个管理员用户niki_at_work的身份登录。在这种情况下,您不一定需要为homebrew创建一个新帐户。
创建~/brew.sh文件,并添加以下内容:
#!/bin/bash
comm="brew $@"
su niki -c "$comm"
  • chmod +x ~/brew.sh
  • 将此别名添加到.zshrc或等效文件中:alias brew="~/brew.sh"
  • 现在您可以像以前一样从niki_at_work进行brew操作(它会要求输入niki的密码):

    brew update
    brew install swiftlint
    

    如果你想要为brew使用一个专用的管理员用户,比如brewadmin,你应该首先将brew目录的所有权改为brewadmin:admin: sudo chown -R brewadmin:admin /usr/local/*

    1
    我没有看到回复你的人是官方维护者的证据。但这种策略也类似于我用来维护的一个工具: https://github.com/brewdo/brewdo对于大多数情况,它效果很好,但我几年前停止了维护,因为偶尔会出现不兼容性问题,而且Homebrew本身使用操作系统沙盒技术来防止Homebrew安装之外的更改——这是我启动此工具的早期原因。无论如何,基于经验,我认为这个答案过于简单化,并且在今后可能会有问题。 - zigg
    关于@Mattie的评论“我没有看到回复你的人是官方维护者的证据”,实际上,外部链接的GitHub问题中的评论者确实作为Homebrew组织的一部分列在了GitHub上,截至2023年8月:https://github.com/orgs/Homebrew/people - Ville

    2
    最好的解决方案是添加一个sudoers记录,允许非特权用户'joe'以管理员身份执行任何与'brew'相关的命令。 在/etc/sudoers.d/目录下创建一个名为joe的文件,并加入以下内容:
    joe ALL=(administrator) NOPASSWD: /usr/local/bin/brew
    

    然后你可以这样运行brew:
    sudo -Hu administrator brew install <smth>
    

    听起来很危险。如果“joe”创建了一个有害的Homebrew包怎么办? - Suragch
    4
    @suragch,我猜你无法避免这种危险,如果你允许Joe安装任何系统范围的软件包,不仅是这种方式,而是任何方式。 - Sergey Papyan

    1
    其他在这里分享的答案(尤其是得分较高的)基本上都存在缺陷。
    不好的做法:共享组可写权限
    使用共享组可写权限的方法是不好的,因为Homebrew并不是设计用于多个Unix用户使用的。一个给定的Homebrew安装只能被单个非root用户使用。
    通过给定组赋予写权限,你会产生一个错觉,认为你允许多个用户使用brew。
    但是brew使用的默认umask不会添加组写权限,这意味着当你使用brew时,越来越多的状态部分将无法被你组中的其他用户写入。
    这意味着如果你从不同的用户安装软件包,brew update将很快无法在任何一个用户上运行,因为没有一个用户再拥有对所有内容的访问权限;你将需要一遍又一遍地运行chmod hack。
    不好的做法:分开的Homebrew安装
    分开安装Homebrew的方法是不好的,首先,您需要从源代码构建所有软件包。其次,更重要的是,许多软件包在安装到自定义前缀而不是默认全局前缀时根本无法构建。这种方法完全不受HomeBrew团队支持,他们甚至发出了免责声明:
    “从源代码构建是慢、能源效率低、有错误且不受支持的。Homebrew之所以能正常工作的主要原因是我们使用瓶子(二进制软件包),而大多数瓶子都需要使用默认前缀。如果您决定使用其他前缀:请不要提出任何问题,即使您认为它们与您的前缀选择无关。它们将被关闭且不会得到回应。”
    解决方案:为Homebrew专门分配一个用户帐户
    这是Homebrew FAQ中针对多用户系统的推荐做法!
    “如果您需要在多用户环境中运行Homebrew,请考虑创建一个专门用于Homebrew使用的单独用户帐户。”
    因为Homebrew不是为多个用户使用而设计的,也不是为安装在默认位置以外的任何地方而设计的,所以您要做的是在默认位置安装Homebrew,并使用专用用户切换到该用户以使用它。

    -4

    3
    如果你想使用多个用户,这并不是一个实际的解决方案。你需要在每次用户切换时执行该命令。 - maniexx
    这在多用户环境下不起作用。 - Exploring

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接