三 文章首页 实时留言 网络邻居 开往 虫洞
返回

用 xdg-dbus-proxy 解决容器的文件选择器的问题

2026-04-14 23:54:31
分类: Linux 标签: 问题解决

Linux 桌面有时候需要容器开 GUi,并且和系统深度集成(如:调用宿主输入法、桌面系统通知),需要给容器传这些文件(其中 -E 为环境变量,--bind 是挂载):

-E DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$UID/bus"
--bind="$XDG_RUNTIME_DIR"

但有个问题,文件选择器也会调用宿主的,没办法找容器自己的文件。

我使用的是 xdg-dbus-proxy 去解决。

# 1. 在 XDG_RUNTIME_DIR 下生成一个代理 socket 路径
PROXY_SOCKET="$XDG_RUNTIME_DIR/nspawn-bus-proxy-$"

# 2. 启动 xdg-dbus-proxy,开启过滤:只放行 fcitx 相关的通信,拦截其他所有服务(如 Portal)
xdg-dbus-proxy "unix:path=/run/user/$uid/bus" "$PROXY_SOCKET" \
    --filter \
    --own=org.fcitx.* \
    --talk=org.fcitx.* &
PROXY_PID=$!

# 3. 确保脚本退出(容器关闭)时,自动清理后台的代理进程和 socket
trap "kill $PROXY_PID; rm -f $PROXY_SOCKET" EXIT

#  传递的环境变量(这里是 systemd-nspawn 的参数)
-E DBUS_SESSION_BUS_ADDRESS="unix:path=$PROXY_SOCKET" \

我使用的是 systemd-nspawn 容器,完整的启动脚本:

#!/bin/bash

xhost +local:
uid=1000
gid=1000

# 1. 在 XDG_RUNTIME_DIR 下生成一个代理 socket 路径
PROXY_SOCKET="$XDG_RUNTIME_DIR/nspawn-bus-proxy-$"

# 2. 启动 xdg-dbus-proxy,开启过滤:只放行 fcitx 相关的通信,拦截其他所有服务(如 Portal)
xdg-dbus-proxy "unix:path=/run/user/$uid/bus" "$PROXY_SOCKET" \
    --filter \
    --own=org.fcitx.* \
    --talk=org.fcitx.* &
PROXY_PID=$!

# 3. 确保脚本退出(容器关闭)时,自动清理后台的代理进程和 socket
trap "kill $PROXY_PID; rm -f $PROXY_SOCKET" EXIT

# 4. 启动容器,将容器的 DBUS 地址指向这个“被过滤的”代理 Socket
sudo systemd-nspawn  \
    --hostname="$1" \
    --directory="$2" \
    -E DISPLAY="$DISPLAY"  \
    -E LANG="zh_CN.UTF-8" \
    -E PULSE_SERVER="unix:/run/user/$uid/pulse/native" \
    -E DBUS_SESSION_BUS_ADDRESS="unix:path=$PROXY_SOCKET" \
    -E XMODIFIERS="@im=fcitx" \
    -E QT_IM_MODULE="fcitx" \
    -E GTK_IM_MODULE="fcitx" \
    -E INPUT_METHOD="fcitx" \
    -E HSA_OVERRIDE_GFX_VERSION="11.5.1" \
    -E GLFW_IM_MODULE="fcitx" \
    -E SDL_IM_MODULE="fcitx" \
    -E XDG_RUNTIME_DIR="$XDG_RUNTIME_DIR" \
    -E WAYLAND_DISPLAY=$WAYLAND_DISPLAY \
    -E GTK_USE_PORTAL=0 \
    --property=AppArmorProfile=unconfined \
    --capability="all" \
    --bind-ro="/run/dbus/system_bus_socket" \
    --bind-ro="/dev/kfd" \
    --bind-ro="/dev/dri" \
    --bind-ro="/run/udev" \
    --bind="/dev/shm" \
    --bind-ro="/dev/input"  \
    --bind="$XDG_RUNTIME_DIR" \
    --bind-ro="/etc/resolv.conf" \
    -M "$1"