У меня установлена установка сервера Ubuntu 14.04, которая действует как хост LXC. Он имеет двух пользователей: user1 и user2.
user1 владеет непривилегированным контейнером LXC, который использует каталог (внутри /home/user1/.local / …) в качестве хранилища резервных копий.
Как сделать полную копию контейнера для пользователя2? Я не могу просто скопировать файлы, потому что они сопоставлены с владельцами от 100000 до 100000 + что-то, что связано с user1.
Кроме того, я считаю, в основном, тот же вопрос, как я могу безопасно сделать резервную копию контейнера LXC моего user1, чтобы восстановить его позже на другом компьютере и / или пользователе?
Теперь я знаю, как это сделать. Если вы не можете следовать этому объяснению, пожалуйста, спросите назад, но также убедитесь, что вы прочитали об ошибках в показаниях, которые я даю внизу
Я буду придерживаться следующих предположений, простирающихся от того, что у меня есть из вашего вопроса:
user1
и user2
, если информация не является конкретной для одного, мы будем использовать userX
$container
user1
и user2
будут указаны в обозначениях, известных из Bash как ~user1
и ~user2
. $container
будет отображаться как $rootfs
, независимо от того, где она закончится ( ~userX/.local/share/lxc/$container/rootfs
) ~userX/.local/share/lxc/$container/config
Существуют два релевантных фрагмента данных, которые управляют контейнерами:
$container
/etc/sub{uid,gid}
для учетной записи пользователя (управляются через usermod --{add,del}-sub-{uid,gid}s
) и lxc.id_map
в $container
( ~userX/.local/share/lxc/$container/config
) соответственно
userX
пользователя имеет 65536 подчиненных GID и UID, возможно, будет возможно назначить от 5000 до 65 разных контейнеров, но я не тестировал эту гипотезу. Таким образом, суть в том, что вам необходимо убедиться, что владелец файла / папки и группа для контейнера соответствуют конфигурации, которая, в свою очередь, должна быть допустимым подмножеством подчиненных GID / UID хоста, назначенных пользователю1 и user2
соответственно.
Например, если вы используете Bash, вы можете использовать $((expression))
для арифметических выражений и let
назначать арифметические выражения для переменных. Это очень полезно, если вы знаете базовое значение (100000 и 200000 соответственно) и GID / UID для «внутренних» пользователей.
Основные моменты:
CAP_CHOWN
либо права суперпользователя Вот сценарий, который, вероятно, понадобится еще немного хонингования (пример: переход из созданного корнем контейнера в непривилегированный), но он работает для меня с этой целью:
#!/usr/bin/env bash function syntax { echo "SYNTAX: ${0##*/} <from-user> <to-user> <container-name>" [[ -n "$1" ]] && echo -e "\nERROR: ${1}." exit 1 } # Checks [[ -n "$1" ]] || syntax "<from-user> is not set" [[ -n "$2" ]] || syntax "<to-user> is not set" [[ -n "$3" ]] || syntax "<container-name> is not set" [[ "$UID" -eq "0" ]] || syntax "${0##*/}" "You must be superuser to make use of this script" # Constants with stuff we need readonly USERFROM=$1 readonly USERTO=$2 shift; shift readonly CONTAINER=${1:-*} LXCLOCAL=".local/share/lxc" readonly HOMEFROM=$(eval echo ~$USERFROM) readonly HOMETO=$(eval echo ~$USERTO) readonly LXCFROM="$HOMEFROM/$LXCLOCAL" readonly LXCTO="$HOMETO/$LXCLOCAL" readonly GIDBASEFROM=$(awk -F : "\$1 ~/$USERFROM/ {print \$2}" /etc/subgid) readonly UIDBASEFROM=$(awk -F : "\$1 ~/$USERFROM/ {print \$2}" /etc/subuid) readonly GIDSIZEFROM=$(awk -F : "\$1 ~/$USERFROM/ {print \$3}" /etc/subgid) readonly UIDSIZEFROM=$(awk -F : "\$1 ~/$USERFROM/ {print \$3}" /etc/subuid) readonly GIDBASETO=$(awk -F : "\$1 ~/$USERTO/ {print \$2}" /etc/subgid) readonly UIDBASETO=$(awk -F : "\$1 ~/$USERTO/ {print \$2}" /etc/subuid) readonly GIDSIZETO=$(awk -F : "\$1 ~/$USERTO/ {print \$3}" /etc/subgid) readonly UIDSIZETO=$(awk -F : "\$1 ~/$USERTO/ {print \$3}" /etc/subuid) unset LXCLOCAL # More checks [[ -d "$LXCFROM" ]] || syntax "Could not locate '$LXCFROM'. It is not a directory as expected" [[ -e "$LXCTO" ]] && syntax "Destination '$LXCTO' already exists. However, it must not" for i in GIDBASEFROM UIDBASEFROM GIDBASETO UIDBASETO; do (($i > 0)) || syntax "Could not determine base/offset of subordinate UID/GID range" done for i in GIDSIZEFROM UIDSIZEFROM GIDSIZETO UIDSIZETO; do (($i > 0)) || syntax "Could not determine length of subordinate UID/GID range" done echo "Going to migrate container: $CONTAINER" echo -e "\tfrom user $USERFROM ($HOMEFROM): subUID=${UIDBASEFROM}..$((UIDBASEFROM+UIDSIZEFROM)); subGID=${GIDBASEFROM}..$((GIDBASEFROM+GIDSIZEFROM))" echo -e "\tto user $USERTO ($HOMETO): subUID=${UIDBASETO}..$((UIDBASETO+UIDSIZETO)); subGID=${GIDBASETO}..$((GIDBASETO+GIDSIZETO))" while read -p "Do you want to continue? (y/N) "; do case ${REPLY:0:1} in y|Y) break; ;; *) echo "User asked to abort." exit 1 ;; esac done # Find the UIDs and GIDs in use in the container readonly SUBGIDSFROM=$(find -H "$LXCFROM" -printf '%G\n'|sort -u) readonly SUBUIDSFROM=$(find -H "$LXCFROM" -printf '%U\n'|sort -u) # Change group for gid in $SUBGIDSFROM; do let GIDTO=$(id -g "$USERTO") if ((gid == $(id -g "$USERFROM"))); then echo "Changing group from $USERFROM ($gid) to $USERTO ($GIDTO)" find -H "$LXCFROM/$CONTAINER" -gid $gid -exec chgrp $GIDTO {} + elif ((gid >= GIDBASEFROM )) && ((gid <= GIDBASEFROM+GIDSIZEFROM)); then let GIDTO=$((gid-GIDBASEFROM+GIDBASETO)) echo "Changing group $gid -> $GIDTO" find -H "$LXCFROM/$CONTAINER" -gid $gid -exec chgrp $GIDTO {} + else echo "ERROR: Some file/folder inside '$LXCFROM/$CONTAINER' has a group not assigned to $USERFROM (assigned subordinate GIDs)." echo -e "Use:\n\tfind -H '$LXCFROM/$CONTAINER' -gid $gid\nto list those files/folders." exit 1 fi done # Change owner for uid in $SUBUIDSFROM; do let UIDTO=$(id -u "$USERTO") if ((uid == $(id -u "$USERFROM"))); then echo "Changing owner from $USERFROM ($uid) to $USERTO ($UIDTO)" find -H "$LXCFROM/$CONTAINER" -uid $uid -exec chown $UIDTO {} + elif ((uid >= UIDBASEFROM )) && ((uid <= UIDBASEFROM+UIDSIZEFROM)); then let UIDTO=$((uid-UIDBASEFROM+UIDBASETO)) echo "Changing owner $uid -> $UIDTO" find -H "$LXCFROM/$CONTAINER" -uid $uid -exec chown $UIDTO {} + else echo "ERROR: Some file/folder inside '$LXCFROM/$CONTAINER' has an owner not assigned to $USERFROM (assigned subordinate UIDs)." echo -e "Use:\n\tfind -H '$LXCFROM/$CONTAINER' -uid $uid\nto list those files/folders." exit 1 fi done mv "$LXCFROM/$CONTAINER" "$LXCTO/" || { echo "ERROR: failed to move to destination: ${LXCTO}/${CONTAINER}."; exit 1; }
В дополнение к условиям лицензии сети StackExchange, я помещаю это в общественное достояние. Поэтому повторное использование и изменение в какой бы то ни было целях, но оно предоставляется без каких-либо гарантий, и я не должен нести ответственность за его использование или злоупотребление.
Применение
SYNTAX: lxc-reassign-userns.sh <from-user> <to-user> <container-name>
Он предполагает, что вы find
, sort
, uniq
, awk
( mawk
и gawk
), id
, bash
, chown
, chmod
и т. Д., Чтобы понять все используемые им ключи командной строки. Для Bash readonly
и let
и арифметические выражения предполагаются понятными. Для find
предполагает, что +
является допустимым терминатором для -exec
действия.
Этот список, вероятно, не завершен.
Да, вы можете создавать резервные копии и восстанавливать их в другом месте, если вы также соответствующим образом настроите владельца файла и группу.
Однако, предполагая, что вы используете что-то вроде tar
, есть предостережение: tar
игнорирует сокеты, поэтому $rootfs/dev/log
будет представлять проблему – другие могут также создать аналогичную проблему.
subuid(5)
subgid(5)
newuidmap(1)
newgidmap(1)
user_namespaces(7)
fuidshift
был создан для этой цели. Кажется, это часть LXD.
http://manpages.ubuntu.com/manpages/xenial/man1/fuidshift.1.html