在我们的文件服务器上,我们使用了一堆仍在使用的 Linux 组,需要用 AD 中的对应组来替换。 AD 和 /etc/groups 中的组具有相同的名称,因此(我猜?) chgrp 在这里并没有多大用处。
我的问题是:将文件服务器上特定文件的组所有权更改为指向 AD 中的组而不是 Linux 组的最佳方法是什么?
我正在考虑是否可以通过 GID 而不是组名进行更改,但这似乎会导致灾难。
答案1
chgrp
可以处理数字 GID 以及符号组名称。您需要 100% 确定您的姓名与姓名组匹配完全正确。根据解决问题的方式,可能还需要确保 Linux 数字位于与 AD 数字完全不同的范围内。大多数 AD 管理员这样做的原因显而易见,但请检查以确保确定。然后,您可以chgrp
将所有组所有权从旧的 Linux GID 号重新映射到新的 AD GID 号,一次一个组。但至关重要的是,有零Linux GID 号和 AD GID 号之间存在重叠。
我建议不是在脚本中完成实际工作。相反,编写一个仅输出(长)chgrp
命令字符串的脚本。这样,如果您的脚本出现问题,也不会造成任何损害。您调试脚本,然后仔细检查chgrp
它生成的命令,并确保它们 100% 正确。修复您发现的任何错误。一旦一切看起来都不错,然后将该 s 列表通过管道传输chgrp
到 shell 中。
与 UNIX(或 Linux)中一样,完成一项任务的方法不止一种。您可以迭代每个组,并对每个组的文件层次结构进行一次搜索。如果您没有很多组,层次结构中也没有很多文件,这可能没问题。但它确实要求旧的和新的数字 GID不要重叠。
更有效的方法可能是仅搜索层次结构一次,并一次性处理所有文件,一次处理一个文件。这样做的另一个优点是,只要姓名之间的匹配 100% 正确,数字是否重叠并不重要。为此,首先构建一个表,将旧的数字 Linux GID 映射到旧的符号 Linux 名称(也是新的符号 AD 名称)。接下来,备份/etc/group
并编辑它以删除您要停用的所有 Linux 组名称。
现在您有一个包含 GID -> 名称映射列表的文件,以及层次结构中具有数字 GID 但没有定义的组名称的一堆文件。
您需要做的下一件事是确保您的 AD 组枚举正常工作(wbinfo
通常通过 )。一个简单的测试,例如:
# wbinfo --group-info 'test AD group'
test AD group:x:1597:
# touch /tmp/foo
# chgrp 'test AD group' /tmp/foo
# ls -l /tmp/foo
-rw-r--r-- 1 root test AD group 0 Jun 13 11:06 /tmp/foo
应该足够了。在我所提供的地方,'test AD group'
您应该使用您知道存在的 AD 组名称。使用引号,以防组名称包含空格。
手头的下一个任务是迭代层次结构中的每个文件,并使用 stat 查找其数字GID,这当然是过时的 Linux GID。将该数字 GID 映射到符号组名称(即新的符号 AD 名称),并写出一个chgrp
命令来对该文件进行更改。请务必在组名称两边使用引号,因为 AD 组通常包含空格。这样,您的旧 Linux 组是否foobar
与新 AD 组具有完全相同的 GID就不再重要了farkle
,因为您的脚本将使用旧 GID,找到旧名称foobar
并执行chgrp
命令来重置组按名字成为foobar
。
以下是有关如何创建 GID 到名称映射的建议。它没有经过充分测试,也没有完全优化。它只是为了让您思考如何将问题分解为更小、更易于管理的步骤。在运行任何测试或最终脚本之前,请务必对数据进行完整备份。
假设cups
cas
nagios
和domain users
是您要迁移的组:
# getent group cups cas nagios "domain users" | awk -F: '{print $3 " " $1}'
193 cups
1001 cas
445 nagios
715 domain users
将其保存到文件中,例如numeric-gid-map.txt
现在构建一个接受数字 GID 的函数,并从该文件返回匹配的名称:
map_gid_to_name() {
grep "^$1 " numeric-gid-map.txt | sed -e "s/[^ ]* //"
}
另一个非常简单的函数将接受组名和文件名,并输出命令chgrp
:
do_chgrp() {
printf 'chgrp "%s" "%s"\n' "$1" "$2"
}
将所有这些与一个可以采用单个文件名的函数结合在一起,使用stat
查找数字 GID,找到相应的组名称,然后将chgrp
命令写入 stdout:
do_one_file() {
gid=$(stat -f%g "$1")
gname="$(map_gid_to_name $gid)"
do_chgrp "$gname" "$1"
}
剩下的唯一一步是迭代您的层次结构并将文件一一传递给您的函数。
chgrp_one_file.sh:
#!/usr/bin/env bash
map_gid_to_name() {
grep "^$1 " numeric-gid-map.txt | sed -e "s/[^ ]* //"
}
do_chgrp() {
printf 'chgrp "%s" "%s"\n' "$1" "$2"
}
do_one_file() {
gid=$(stat -f%g "$1")
gname="$(map_gid_to_name $gid)"
do_chgrp "$gname" "$1"
}
do_one_file "$1"
chmod
755 所以它是可执行的。
find /your/path -print0 | xargs -0 -n1 -Ixx ./chgrp_one_file.sh "xx"
再次强调,我不会假装这是经过测试或优化的。这只是一种可能的方法,希望能让您开始了解如何改进它并改变它以满足您的需求。