我最近从 Ubuntu 16.04 LTS 更改为 18.04 LTS,因为我需要更新版本的 kvm/qemu。
使用 16.04,我可以按照“社区帮助 Wiki”中的说明轻松运行 x11vnc 服务(守护进程):https://help.ubuntu.com/community/VNC/Servers
这有一个设置 x11vnc 守护进程服务所需的脚本,它允许您远程登录计算机,而无需先在本地登录。我需要这个,因为我的机器作为服务器运行,位于地下室,我总是通过 VNC 访问它,而不是本地访问。
最初,我对干净的 18.04 安装没有做任何事,只是systemctl
完全按照“社区帮助 Wiki”的说明添加脚本:“让 x11vnc 在任何环境中通过 systemd 自动启动(Vivid+)”。
当发现这不再起作用时,我根据一些搜索做了以下事情:
/etc/gdm3/custom.conf
通过编辑和设置WaylandEnable=false
此脚本来禁用“Wayland”显示管理器:[daemon] # Uncoment the line below to force the login screen to use Xorg #WaylandEnable=false WaylandEnable=false <--- HERE
将命令更改
/lib/systemd/system/x11vnc.service ExecStart
为使用不同的xauth
指令,因为在 18.04 中似乎没有$HOME/.Xauthority
可以通过指令找到的自动生成的文件-xauth guest
:从:
ExecStart=/usr/bin/x11vnc -auth guess -forever -loop -noxdamage -repeat -rfbauth /home/USERNAME/.vnc/passwd -rfbport 5900 -shared
到:
ExecStart=/usr/bin/x11vnc -auth /run/user/120/gdm/Xauthority -forever -loop -noxdamage -repeat -rfbauth /home/USERNAME/.vnc/passwd -rfbport 5920 -shared
我根据对 Xauthority 的一些阅读和测试做到了这一点,这表明.Xauthority
令牌的位置现在是通过$XAUTHORITY
环境变量给出的。
为了找到这个值,我运行以下“ find
”命令来查找哪些进程XAUTHORITY
定义了环境变量。
注意:这使用 linux/proc/<procid>/environ
文件结构来搜索进程环境变量,
cd /proc
sudo find . -maxdepth 1 -type d -exec sh -c "(test -f '{}'/environ && cat '{}'/environ | tr '\0' '\n' | grep XAUTHORITY= )" \;
这返回了两个不同的结果:
XAUTHORITY=/run/user/120/gdm/Xauthority
XAUTHORITY=/run/user/1000/gdm/Xauthority
然后我使用下面的方法找到相应的进程 ID:
sudo find . -maxdepth 1 -type d -exec sh -c "(test -f '{}'/environ && grep -aH XAUTHORITY= '{}'/environ )" \;
这些相应的过程是:
240 tty1 Sl+ 0:00 /usr/lib/gnome-session/gnome-session-binary --autostart /usr/share/gdm/greeter/autostart
14923 tty2 Sl+ 0:00 /usr/lib/gnome-session/gnome-session-binary --session=ubuntu
其中第一个似乎与登录欢迎屏幕相关,而第二个是用户桌面。
进一步检查环境变量发现一个有USER=gdm
,另一个有USER=<ME>
问题是,如果我使用“greeter”身份验证位置,系统会提示我输入密码,然后屏幕变黑/空白。如果我使用用户身份验证位置,则根本无法获得任何客户端连接,因为状态返回无法打开显示的错误:
13/05/2018 16:19:14 *** XOpenDisplay failed.
因此,看起来您被 xauth 机制的改变所困扰了。
有人可以对此提供一些指导吗?
答案1
Ubuntu 18.04 x11vnc 用户。
这是一个“黑客答案”,它允许您无需登录即可获得 VNC 访问权限。
我之所以说是 hack,是因为它涉及运行 2 个 x11vnc 服务。
第一个是允许通过登录DISPLAY=:0
,第二个是使用 VNC 通过以下方式访问桌面DISPLAY=:1
为了实现这一点,我使用了以下两个守护进程脚本:
第一个是:x11vnc-login.service
仅用于登录问候
[Unit]
Description=Start x11vnc-login at startup.
After=multi-user.target
[Service]
Type=simple
ExecStart=/usr/bin/x11vnc -auth /run/user/120/gdm/Xauthority -forever -loop -noxdamage -repeat -rfbauth /home/<ID>/.vnc/password -rfbport 5922 -shared -display :0
[Install]
WantedBy=multi-user.target
第二个是x11vnc.service for desktop
::
[Unit]
Description=Start x11vnc at startup.
After=multi-user.target
[Service]
Type=simple
ExecStart=/usr/bin/x11vnc -auth /run/user/1000/gdm/Xauthority -forever -loop -noxdamage -repeat -rfbauth /home/<ID>/.vnc/password -rfbport 5920 -shared -display :0
[Install]
WantedBy=multi-user.target
脚本的安装和启用按照社区帮助网站上的文档。
这是一个可怕的黑客攻击,但让我暂时运行,直到找到适当的解决方案。
在使用时,我首先打开 VNC 会话到端口 5922 并登录。登录后,您会看到黑屏。然后,您在端口 5920 上打开 VNC 会话,瞧,您的桌面就出现了。对我来说,这比去服务器机器运行的地方要容易得多……
显然,需要一些脚本对正在运行的进程进行初步搜索,以查看用户是否已登录,如果是,则只需使用现有用户部分中的 XAUTHORITY/DISPLAY 信息(从 /proc/PROCID/environ 中提取,否则使用欢迎程序 XAUTHORITY/DISPLAY 将套接字连接到欢迎程序屏幕,然后以某种方式使用用户桌面 XAUTHOURITY/DISPLAY 值将套接字连接移动到另一个 x11vnc 会话。
我怀疑有一点复杂的 fork/socket/文件描述符编程。
另一种可能性是弄清楚是否有某种方法可以让 18.04 显示管理器按照之前的 16.04 运行。
答案2
我遇到了同样的问题,在对 x11vnc 和 gdm 进行一些调整之后,我决定切换回 lightdm:
apt install lightdm
这应该会调出显示管理器配置。如果没有,请运行:
dpkg-reconfigure lightdm
我现在通过主管运行我的 x11vnc 服务器,配置如下:
$ cat /etc/supervisor/conf.d/x11vnc.conf
[program:x11vnc]
command=/usr/bin/x11vnc -xkb -safer -nopw -once -geometry 1024x768 -auth /var/run/lightdm/root/\:0 -display :0
user=root
autorestart=true
此外,我在上面运行 noVNC(也通过主管),这样我就可以通过浏览器远程访问我的桌面。如果您感兴趣,配置文件如下所示:
$ cat /etc/supervisor/conf.d/novnc.conf
[program:noVNC]
command=/opt/noVNC/utils/launch.sh --vnc localhost:5900
user=root
$ cat /etc/nginx/sites-enabled/novnc
upstream vnc_proxy {
server 127.0.0.1:6080;
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
include snippets/snakeoil.conf;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
auth_pam "Secure Zone";
auth_pam_service_name "nginx";
proxy_pass http://vnc_proxy/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
keepalive_requests 10000;
proxy_read_timeout 61s;
proxy_buffering off;
}
}
您可能需要为其添加一些额外的安全措施。
答案3
答案4
这是另一种解决方法,使用 tmux 使其在 gdm3 上运行而无需切换到 lightdm。在大多数情况下,您可以通过端口 5900 登录。
#!/bin/bash
if [ -z "$1" ]; then echo "Please pass the password you would like to use as an argument to this script"; exit 1 ; else echo "Good start.going ahead."; fi
apt update && apt install tmux -y
password=$1
passwordfile='/etc/x11vnc.pass'
servicefile='/etc/systemd/system/x11vnc.service'
timerfile='/etc/systemd/system/x11vnc.timer'
script='/usr/bin/startxvnc'
apt-get update
apt-get install x11vnc net-tools -y
x11vnc -storepasswd $password $passwordfile
cat >$servicefile <<'EOT'
[Unit]
Description="x11vnc"
Requires=display-manager.service
[Service]
Type=simple
#Environment=XAUTHORITY=$(ps aux | grep -o -E "(-auth)(.*)(Xauth)[a-zA-Z]+")
#ExecStartPre=tmux new -s x11vnc -d
ExecStart=bash -c /usr/bin/startxvnc
#ExecStop=tmux kill-session -t x11vnc
Restart=on-failure
RestartSec=2
[Install]
WantedBy=graphical.target
WantedBy=multi-user.target
EOT
cat >$timerfile <<'EOT'
Unit]
Description=Wait for some time before running X11VNC
[Timer]
OnBootSec=5sec
[Install]
WantedBy=timers.target
EOT
cat >$script <<'EOT'
#!/bin/bash
getxauths()
{
xauths=()
ps aux | grep -o -E "(-auth)(.*)(Xauth)[a-zA-Z]+" | (while IFS= read -r xauth
do
xauths+=("$xauth")
done
printf "%s\n" "${xauths[@]}" | sort -u
) }
getpname()
{
#psp=$(ps -p $(lsof -t -i:5900) -o command)
psp=$(cat /proc/$(lsof -t -i:$1)/cmdline)
echo $psp
}
killproc()
{
pkill -9 $(lsof -t -i:$1)
echo "Killed by port $1"
}
starttmux()
{
xauth=$1
tmux new -s $xauth -d
tmux send-keys -t $xauth:0 "for (( ; ; )) ; do sleep 3s; ((disp ^= 1)) ; /usr/bin/x11vnc -display :\$disp -auth $xauth -rfbauth /etc/x11vnc.pass -shared -forever ; done" Enter
}
#echo $(getpname)
start() {
for (( ; ; )) ; do
#echo $psp
xauths=$(getxauths)
for xauth in $xauths ; do
xauth="$xauth" | xargs
if [[ ${xauth} != *"-auth"* ]];then
unset tsessions
tsessions=($(tmux list-sessions -F '#{session_name}'))
echo "tessions is " ${tsessions[@]}
echo "xauth is " ${xauth}
if [[ ! " ${tsessions[@]} " =~ " ${xauth} " ]]; then
starttmux $xauth
psp=$(getpname 5900)
echo $psp | grep -E -o "(-auth)(.*)(Xauth)[a-zA-Z]+" | (while IFS= read -r xold
do
sessionname=$(echo ${xold#"-auth"} | xargs)
#tmux kill-session -t "$sessionname"
if [[ ! " ${tsessions[@]} " =~ " ${xauth} " ]]; then
if [[ $psp == *"user/125"* ]] ; then killproc 5900 ; tmux kill-session -t "$sessionname" ; echo "session name is $sessionname" ;
fi ; else starttmux $xauth ; sleep 30s ; fi
done)
fi
fi
done
sleep 3s
done
}
start
EOT
chmod u+x $script
sed -i -e 's/WaylandEnable=true/WaylandEnable=false/g' /etc/gdm3/custom.conf
sed -i -e 's/#WaylandEnable=false/WaylandEnable=false/g' /etc/gdm3/custom.conf
systemctl daemon-reload
systemctl enable x11vnc.timer
systemctl stop x11vnc.service
systemctl disable x11vnc.service
systemctl restart x11vnc.timer