У вас уже есть подходящий ответ, и это нормально. Я хотел обратиться к другой части вашего вопроса, которая спрашивает, почему функциональность --include
не работает так, как вы ожидаете.
Прежде всего, давайте посмотрим, как работают фильтры --include
и --exclude
.
aaa
будет применяться к любому файлу или каталогу с именемaaa
/aaa
будет применяться к любому файлу или каталогу с именем aaa
в начале исходного пути aaa/
будет применяться к любому каталогу с именемaaa
Вы можете комбинировать их, поэтому путь bbb/ccc/
указывает на любой каталог ccc
, который является дочерним по отношению к каталогуbbb
в любом месте исходного дерева , но /bbb/ccc/
является каталогом ccc
внутри каталога bbb
, который привязан к вершине исходного дерева .
Операции включения и исключения обрабатываются слева направо (первая операция важнее второй, а вторая важнее третьей ).
Теперь давайте посмотрим на ваш конкретный пример:
rsync -ah --include="data/foo*" --exclude="*.zip" --exclude="*" "/path/to/data" "/mnt/backup/drive"
Правила фильтрации говорят, что по порядку:
foo
, которые находятся в каталоге с именемdata
ниже исходного пути . *.zip
файлы (или каталоги ). Первое включение будет соответствовать /path/to/data/data/foo1
, но не будет соответствовать /path/to/data/foo1
. Подозреваю, что это основное недоразумение.
Вы можете сопоставить свои /foo*
каталоги с очень похожим решением:
rsync -ah --include="/foo*/" --exclude="*.zip" --exclude="*" "/path/to/data/" "/mnt/backup/drive"
Но на самом деле,если бы я писал это, я бы, вероятно, включил каталоги /foo*
в спецификацию исходного пути (, обратите внимание, что foo*
не заключен в кавычки, поэтому оболочка может получить подстановочный знак )и беспокоиться только об исключении нежелательных zip-файлов:
rsync -ah --exclude="*.zip" /path/to/data/foo*/ /mnt/backup/drive
$ псевдоним sudo="echo sudon't "
$ sudo su -корень
sudon't su -корень
Это просто сломает его там, где он вызывает sudo, если только он не вызывает полный путь, такой как /usr/bin/sudo
Ваша идея может быть легко реализована с помощью небольшой программы «установить -userID -root», которая будет выполнять setgroups(2)
только со всеми текущими группами (согласно getgroups(2)
), кроме sudo
один, эффективно отбрасывая его. Набор -userID -root требуется, поскольку setgroups(2)
является привилегированной операцией.
В Linux это может быть даже проще, так как вы можете использовать capabilities(7)
и сделать исполняемую программуsetcap(8)
-ed равной CAP_SETGID
, а не устанавливать -userID -root. В этот момент такой специализированной программе нужно будет только capset(2)
выполнить эту функцию перед выполнением setgroups(2)
.
С другой стороны , тем не менее, остерегайтесь непреднамеренного удаления/изменения членства в группе , потому что членство в группе также используется для ограничения прав доступа, например.к файлам и каталогам через целенаправленно размещенные ACL.
Тем не менее, используя (специфичную для Linux)setpriv(1)
команду (, если она доступна в вашей системе, )вы можете использовать доказательство -концепции -, выполненной в виде функции оболочки, например ниже, в котором я использую сам sudo
(, учитывая, что выNOPASSWD
)в качестве «установить -userID -корневой активатор»:
# NOTE: this one uses Bash facilities
dropgrp() {
local groups grp="${1:?Specify group to drop}" IFS=; shift
IFS=: read -ra grent < <(getent group "$grp")
groups=(${GROUPS[@]/${grent[2]}})
IFS=,; sudo setpriv --reuid "$EUID" --regid "$GROUPS" --groups "${groups[*]}" "$@"
}
Затем вы запустите$ dropgrp sudo bundle
(sudo
там относится к имени группы, а не к команде ), и когда эта bundle
программа вызоветsudo
(команду ), она запросит ваш пароль для продолжения.