Lxc

為什麼如果以使用者身份執行此腳本可以正常工作,但如果從 rc.local 執行則失敗?

  • November 25, 2020

我在 Debian 上使用 lxc 非特權容器時遇到了一些麻煩。我遵循這種方法:

a)我在 /var/lxcunpriv 中創建了具有 home 權限的使用者

useradd -m -d /var/lxcunpriv lxcunpriv

b)我安裝了需要的包

apt -y install lxc libvirt0 libpam-cgroup libpam-cgfs bridge-utils cgroupfs-mount

c)我更改文件 lxc-net vim /etc/default/lxc-net

USE_LXC_BRIDGE="true"

d)我重新啟動 lxc-net

systemctl restart lxc-net

e)檢查,全部為綠色(工作正常)

lxc-checkconfig

f)我應用這個

sh -c 'echo "kernel.unprivileged_userns_clone=1" > /etc/sysctl.d/80-lxc-userns.conf'
sysctl -w -p --system

g) 作為非 root 使用者,我做了

cat /etc/s*id|grep $USER

h) 它返回 100000-165536,所以…

usermod --add-subuids 100000-165536 lxcunpriv
usermod --add-subgids 100000-165536 lxcunpriv

i) 我對 /var/lxcunpriv 給予了一些許可

cd /var/lxcunpriv
setfacl -m u:100000:x . .local .local/share

l)我配置了usernet,bridge1是我的網橋網名

echo "lxcunpriv veth bridge1 10"| tee -i /etc/lxc/lxc-usernet

m)我創建目錄

su - lxcunpriv
mkdir -p .config/lxc

n) 然後..

echo \
'lxc.include = /etc/lxc/default.conf
# Subuids and subgids mapping
lxc.id_map = u 0 100000 65536
lxc.id_map = g 0 100000 65536
# "Secure" mounting
lxc.mount.auto = proc:mixed sys:ro cgroup:mixed
lxc.apparmor.profile = unconfined

# Network configuration
lxc.network.type = veth
lxc.network.link = bridge1
lxc.network.flags = up
lxc.network.hwaddr = 00:FF:xx:xx:xx:xx'>.config/lxc/default.conf

o)我編輯 /etc/lxc/default.conf

lxc.network.type = veth
lxc.network.link = bridge1

p) 更新 .config/lxc/default.conf

lxc-update-config -c .config/lxc/default.conf

q)我創建了第一個容器

lxc-create --name mylinux -t download
lxc-start --name mylinux
lxc-attach --name mylinux

現在的問題是,當我啟動容器時……

lxc-start --name mylinux
lxc-start: mylinux: lxccontainer.c: wait_on_daemonized_start: 833 No such file or directory - Failed to receive the container state
lxc-start: mylinux: tools/lxc_start.c: main: 330 The container failed to start
lxc-start: mylinux: tools/lxc_start.c: main: 333 To get more details, run the container in foreground mode
lxc-start: mylinux: tools/lxc_start.c: main: 336 Additional information can be obtained by setting the --logfile and --logpriority options

在論壇上搜尋我發現了這個解決方法

#!/bin/sh
printf '\n\033[42mCreating cgroup hierarchy\033[m\n\n' &&
for d in /sys/fs/cgroup/*; do
       f=$(basename $d)
       echo "looking at $f"
       if [ "$f" = "cpuset" ]; then
               echo 1 | sudo tee -a $d/cgroup.clone_children;
       elif [ "$f" = "memory" ]; then
               echo 1 | sudo tee -a $d/memory.use_hierarchy;
       fi
       sudo mkdir -p $d/$USER
       sudo chown -R $USER $d/$USER
       # add current process to cgroup
      echo $PPID > $d/$USER/tasks
done

sh workaround.sh

線上給我一個“權限被拒絕” echo $PPID > $d/$USER/tasks 但有效。

lxc-start -n mylinux
echo $?
0

現在的問題。我希望容器在啟動時啟動(它們是非特權的)所以 lxc-autostart 不起作用我創建了文件 /etc/rc.local,但是失敗了我嘗試過這種方式

#!/bin/bash
# Action at boot

start() {
su - lxcunpriv -c "lxc-start -n mylinux"
su - lxcunpriv -c "lxc-start -n myothercontainer"
....
}

在這種情況下失敗並出現錯誤

 lxc-start: mylinux: lxccontainer.c: wait_on_daemonized_start: 833 No such file or directory - Failed to receive the container state
   lxc-start: mylinux: tools/lxc_start.c: main: 330 The container failed to start
   lxc-start: mylinux: tools/lxc_start.c: main: 333 To get more details, run the container in foreground mode
   lxc-start: mylinux: tools/lxc_start.c: main: 336 Additional information can be obtained by setting the --logfile and --logpriority options

這也是從 rc.local 執行“解決方法”腳本

su - lxcunpriv <<EOF
sh workaround.sh
lxc-start -n myothercontainer
EOF

在這種情況下,解決方法執行但 lxc-start 命令失敗並出現相同的錯誤

lxc-start --name mylinux
   lxc-start: mylinux: lxccontainer.c: wait_on_daemonized_start: 833 No such file or directory - Failed to receive the container state...

當然,如果我這樣做

su - lxcunpriv
sh workaround.sh
lxc-start -n mylinux

它可以工作,為什麼不能從 rc-local 工作?

找到解決方案我編輯 rc.local

而不是那些行

su - lxcunpriv <<EOF
sh workaround.sh
lxc-start -n myothercontainer
EOF

正確的線是那些

start() {
su - lxcunpriv <<EOF
/var/lxcunpriv/workaround.sh
lxc-start --name mycontainer
lxc-start --name myothercontainer
...
EOF    
}

容器啟動。問題是腳本之前的單詞“sh”,它啟動了另一個子shell並消失了變通方法腳本的效果。

引用自:https://unix.stackexchange.com/questions/621088