LXC容器運行X Server(續2-端口轉發)

上篇介紹了只讀mount宿主/tmp/.X11-unix到vm1容器/var/lib/lxc/vm1/rootfs/tmp/.X11-unix,實現容器運行X桌面環境,並因只讀,保護了宿主/tmp/.X11-unix不被容器破壞,但卻因此容器的X Server沒能創建套接字文件,導致某些應用如ssh的X11轉發依賴套接字文件而在容器無法使用

socat是一強大的端口轉發工具,可以實現套接字轉發,就如ssh的X11轉發,本篇就是實現socat轉發X,使容器既能運行X桌面環境,又保持容器/var/lib/lxc/vm1/rootfs/tmp/.X11-unix可寫

1.回顧上篇(https://blog.51cto.com/13752418/2461908)
宿主啓動Xephyr創建了套接字文件(在/tmp/.X11-unix/下)和抽象unix域
只讀mount宿主/tmp/.X11-unix/到容器/tmp/.X11-unix/,即宿主套接字文件共享給了容器
容器只能通過宿主套接字文件和宿主通信,無法通過宿主抽象unix域
容器啓動Xephyr運行在宿主Xephyr之上(通過宿主套接字文件),並創建了容器抽象unix域,因只讀/tmp/.X11-unix/所以容器無法創建套接字文件
容器的圖形程序通過容器抽象unix域運行在容器Xephyr之上
而ssh的X11轉發恰好只能通過套接字文件,無法通過抽象unix域





1)宿主

linlin@debian:~$ netstat -lp |grep X
(Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.)
Active UNIX domain sockets (only servers)
unix  2      [ ACC ]     STREAM     LISTENING     19548    -                    @/tmp/.X11-unix/X0
unix  2      [ ACC ]     STREAM     LISTENING     19549    -                    /tmp/.X11-unix/X0
unix  2      [ ACC ]     STREAM     LISTENING     29044    Xephyr               /tmp/.X11-unix/X1
unix  2      [ ACC ]     STREAM     LISTENING     29043    Xephyr               @/tmp/.X11-unix/X1
linlin@debian:~$

X1爲宿主Xephyr

2)容器

linlin@vm1:~$ ls -a /tmp |grep X*lock
.X30-lock
linlin@vm1:~$ ls   /tmp/.X11-unix
X0
X1
linlin@vm1:~$ netstat -lp |grep X
Active UNIX domain sockets (only servers)
unix  2      [ ACC ]     STREAM     LISTENING     29054    Xephyr              @/tmp/.X11-unix/X30
linlin@vm1:~$

X0、X1爲宿主
X30爲容器Xephyr,只有抽象unix域,沒有套接字文件

2.在宿主編輯容器配置文件/var/lib/lxc/vm1/config
添加下面一行
lxc.mount.entry = /tmp/.X11-unix tmp/.X11-unix-host none bind,ro,optional,create=dir

與上篇同樣只讀mount宿主/tmp/.X11-unix,但容器裏的路徑變爲tmp/.X11-unix-host,路徑名隨便取,只要不是tmp/.X11-unix
即容器裏的原有/tmp/.X11-unix路徑不要被mount --bind

3.宿主
普通用戶運行下面命令

linlin@debian:~$ ls /tmp/.X11-unix/
X0
linlin@debian:~$

X0表示存在顯示號0

運行Xephyr並新建顯示號1
linlin@debian:~$ Xephyr :1

4.容器
1)安裝socat
root@vm1:/# apt-get install socat

2)列出顯示號

linlin@vm1:~$ ls /tmp/.X11-unix-host
X0  X1
linlin@vm1:~$

可見mount --bind後宿主的X0、X1

linlin@vm1:~$ ls -l /tmp/.X11-unix
(空)
linlin@vm1:~$ 

可見容器還沒有顯示號

3)將X1從/tmp/.X11-unix-host轉發到路徑/tmp/.X11-unix/下

linlin@vm1:~$ socat UNIX-LISTEN:/tmp/.X11-unix/X20,fork UNIX-CONNECT:/tmp/.X11-unix-host/X1&
linlin@vm1:~$ ls -l /tmp/.X11-unix
srwxr-xr-x 1 linlin linlin 0 3月  22 02:40 X20
linlin@vm1:~$ 

可見/tmp/.X11-unix/下已創建了套接字文件X20,即顯示號X20(也即宿主的[Xephyr :1])

4)運行Xephyr
指定創建顯示號30

linlin@vm1:~$ DISPLAY=:20 Xephyr :30 &
  458 pts/1    00:00:00 Xephyr
linlin@vm1:~$ ls -l /tmp/.X11-unix
srwxr-xr-x 1 linlin linlin 0 3月  22 02:40 X20
linlin@vm1:~$ netstat  |grep X
Active UNIX domain sockets (w/o servers)
unix  3      [ ]         STREAM     CONNECTED     321359   /tmp/.X11-unix/X20
linlin@vm1:~$ netstat -lp |grep X
Active UNIX domain sockets (only servers)
unix  2      [ ACC ]     STREAM     LISTENING     318282   451/socat            /tmp/.X11-unix/X20
linlin@vm1:~$ 

沒見到X30

linlin@vm1:~$ DISPLAY=:30 xlogo
Can't open display: :30
linlin@vm1:~$ 

在X30運行圖形程序失敗,因爲不存在顯示號30

可見Xephyr雖然在運行,但沒創建套接字文件X30,也沒創建抽象unix域
也就是說,使用socat轉發,Xephyr無法創建顯示號X30

5)運行其它圖形程序
linlin@vm1:~$ DISPLAY=:20 xlogo
這個圖形程序在顯示號X20運行正常
X20實際是宿主的X1,雖然容器中的圖形程序可在[Xephyr :1]上正常運行,但我的目的是要運行完整的容器桌面環境,要在容器先運行一個X Server,圖形程序在容器自己的X Server上運行


6)容器中用Xnest代替Xephyr,宿主仍用Xephyr
root@vm1:/# apt-get install xnest

指定創建顯示號30,並在[:20]上運行
linlin@vm1:~$ DISPLAY=:20 Xnest :30 &
[2] 435
linlin@vm1:~$ ls -l /tmp/.X11-unix
srwxr-xr-x 1 linlin linlin 0 3月 22 03:11 X20
srwxrwxrwx 1 linlin linlin 0 3月 22 03:12 X30




linlin@vm1:~$ netstat -lp |grep X
Active UNIX domain sockets (only servers)
unix  2      [ ACC ]     STREAM     LISTENING     403819   435/Xnest            /tmp/.X11-unix/X30
unix  2      [ ACC ]     STREAM     LISTENING     403818   435/Xnest            @/tmp/.X11-unix/X30
unix  2      [ ACC ]     STREAM     LISTENING     401403   431/socat            /tmp/.X11-unix/X20
linlin@vm1:~$ 

Xnest成功創建了套接字文件X30,也創建了抽象unix域
linlin@vm1:~$ DISPLAY=:30 jwm &
在[Xnest :30]上運行圖形程序正常
linlin@vm1:~$ exit
註銷用戶linlin,因是&後臺運行,註銷登錄後Xnest、socat仍在運行的



7)登錄管理器
由xdm來啓動Xnest
將容器的/etc/X11/xdm/Xservers中
:0 local /usr/bin/X :0 vt7 -nolisten tcp
一行修改爲
:30 local /usr/bin/Xnest -geometry 800x600+0+0 :30




其中:30是指定Xnest創建的顯示號,屏幕尺寸800x600

root@vm1:~# DISPLAY=:20 xdm -nodaemon &

已成功啓動xdm對話框.運行xdm指定的環境變量顯示號是20,但這個顯示號20應該主要是傳遞到Xnest.Xnest運行在[:20]之上,即socat轉發的宿主[Xephyr :1]

參考宿主xdm啓動/usr/bin/X,宿主xdm對話框必定在其/usr/bin/X的顯示號之上.容器xdm對話框應該運行在容器[Xnest :30]之上,而非環境變量[:20]

root@vm1:~# ps -e
   進程號
...
    117 pts/2    00:00:00 bash
    125 pts/4    00:00:00 socat
    126 pts/5    00:00:00 xdm
    129 ?        00:00:00 Xnest
    130 pts/4    00:00:00 socat
    133 ?        00:00:00 xdm
    291 pts/2    00:00:00 ps
root@vm1:~#

socat有兩個進程,分別125和130進程號;xdm也有兩個進程,分別126和133進程號,126號xdm運行在pts/5,133號xdm是守護進程
從上面進程號順序體現了命令進程啓動的先後次序,可見在終端運行xdm(126)命令啓動了Xnest,隨Xnest之後啓動的xdm(133)也應該是由xdm(126)啓動的
因此應該xdm(133)纔是運行在[Xnest :30]之上的xdm登錄對話框

root@vm1:~# netstat -lp |grep X
Active UNIX domain sockets (only servers)                進程號/命令名
unix  2      [ ACC ]     STREAM     LISTENING     127087   129/Xnest            @/tmp/.X11-unix/X30
unix  2      [ ACC ]     STREAM     LISTENING     127085   125/socat            /tmp/.X11-unix/X20
unix  2      [ ACC ]     STREAM     LISTENING     127088   129/Xnest            /tmp/.X11-unix/X30
root@vm1:~# netstat -p |grep X
Active UNIX domain sockets (w/o servers)
unix  3      [ ]         STREAM     CONNECTED     126180   -                    /tmp/.X11-unix/X20
unix  3      [ ]         STREAM     CONNECTED     126183   129/Xnest            @/tmp/.X11-unix/X30
unix  3      [ ]         STREAM     CONNECTED     124810   130/socat            /tmp/.X11-unix/X20
unix  3      [ ]         STREAM     CONNECTED     127090   129/Xnest            
unix  3      [ ]         STREAM     CONNECTED     124817   129/Xnest            @/tmp/.X11-unix/X30
root@vm1:~# 

安裝lsof,查看打開文件
root@vm1:~# apt-get install lsof

root@vm1:~# lsof -U |grep xdm 
         進程號           描述符
xdm       133       root    4u  unix 0x0000000050f42d76      0t0 124814 type=STREAM
xdm       133       root    5u  unix 0x000000005a6b92b7      0t0 126189 type=STREAM
root@vm1:~# 

查看到xdm(133,守護進程)使用了unix域進程間通信,沒發現xdm(126,命令行)使用unix域

root@vm1:~# lsof /tmp/.X11-unix/X30
(空)
root@vm1:~#
查看套接字文件X30打開情況,結果爲空,不懂


通過netstat和lsof還是無法看出xdm(133)對話框在[:20]還是[Xnest :30]之上,我也找不出什麼方法途徑可查看那些進程打開了套接字文件,所以我只能根據進程啓動順序猜測xdm(133)對話框運行在[Xnest :30]之上

root@vm1:~# kill -9 133
殺死xdm(133)進程,可見又立即重啓xdm對話框,125和126號進程保持不動,其它殺掉重啓了

root@vm1:~# ps -e
    PID TTY          TIME CMD
...
    117 pts/2    00:00:00 bash
    125 pts/4    00:00:00 socat
    126 pts/5    00:00:00 xdm
        以下新的進程
    331 ?        00:00:00 Xnest  
    332 pts/4    00:00:00 socat
    335 ?        00:00:00 xdm
    343 pts/2    00:00:00 ps
root@vm1:~# 

每次的桌面會話註銷/登錄,伴隨着重新創建新的守護進程xdm

5.小結
1)只讀mount宿主/tmp/.X11-unix/到容器/tmp/.X11-unix-host/
2)容器/tmp/.X11-unix/保持原樣可讀寫
3)容器使用socat將X從/tmp/.X11-unix-host/轉發到/tmp/.X11-unix/
4)容器使用Xnest代替Xephyr



( 附:LXC容器圖形前端 fglxc-ver0.2.1.zip 源代碼 下載地址 http://u.163.com/m8BXHXFWv 提取碼: i1bG8PwH )

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章