问题描述:ubuntu桌面版在做服务器情况不带显示器的情况下与向日葵等远程办公软件不兼容,引入虚拟显示器方式,但是后续如果要使用物理显示器的话又需要将配置的虚拟显示器文件conf删除(否则物理显示器黑屏或卡死),操作繁琐。本文旨在做一套自动检测,切换配置的脚本教程,解决部分特定场景的需要。
脚本设置
1. 修改脚本(服务将以 root 权限运行)
#!/bin/bash
# Ubuntu 虚拟显示器自动控制脚本
# 功能:自动检测显示器状态并相应启用/禁用虚拟显示器
CONFIG_PATH="/usr/share/X11/xorg.conf.d/xorg.conf"
CONFIG_CONTENT='
Section "Monitor"
Identifier "Monitor0"
HorizSync 28.0-80.0
VertRefresh 48.0-75.0
Modeline "1920x1080_60.00" 172.80 1920 2040 2248 2576 1080 1081 1084 1118 -HSync +Vsync
EndSection
Section "Device"
Identifier "Card0"
Driver "dummy"
VideoRam 256000
EndSection
Section "Screen"
DefaultDepth 24
Identifier "Screen0"
Device "Card0"
Monitor "Monitor0"
SubSection "Display"
Depth 24
Modes "1920x1080_60.00"
EndSubSection
EndSection
'
# 检测是否有真实显示器连接
has_real_display() {
# 尝试使用xrandr检测连接的显示器
if command -v xrandr >/dev/null 2>&1; then
# 检查是否有已连接的显示器(排除虚拟显示器)
if xrandr --listmonitors 2>/dev/null | grep -v "dummy" | grep -q " connected"; then
return 0 # 有真实显示器
fi
fi
# 备用检测方法:检查DRM设备
if [ -d "/sys/class/drm" ]; then
for card in /sys/class/drm/card*-*; do
if [ -e "$card/status" ] && [ "$(cat "$card/status" 2>/dev/null)" = "connected" ]; then
if ! echo "$card" | grep -q "dummy"; then
return 0 # 有真实显示器
fi
fi
done
fi
return 1 # 没有真实显示器
}
# 创建虚拟显示器配置
create_virtual_display() {
echo "正在创建虚拟显示器配置..."
mkdir -p /usr/share/X11/xorg.conf.d/
echo "$CONFIG_CONTENT" | tee "$CONFIG_PATH" > /dev/null
if [ -f "$CONFIG_PATH" ]; then
echo "✓ 配置文件已创建: $CONFIG_PATH"
restart_display_manager
return 0
else
echo "✗ 配置文件创建失败!"
return 1
fi
}
# 删除虚拟显示器配置
remove_virtual_display() {
echo "正在禁用虚拟显示器配置..."
rm -f "$CONFIG_PATH"
if [ ! -f "$CONFIG_PATH" ]; then
echo "✓ 配置文件已禁用"
restart_display_manager
return 0
else
echo "✗ 配置文件禁用失败!"
return 1
fi
}
# 重启显示管理器
restart_display_manager() {
echo "⏳ 正在重启显示服务..."
# 自动检测当前显示管理器
if systemctl is-active --quiet gdm3; then
systemctl restart gdm3
echo "✓ 已重启 gdm3 服务"
elif systemctl is-active --quiet lightdm; then
systemctl restart lightdm
echo "✓ 已重启 lightdm 服务"
else
systemctl restart display-manager
echo "✓ 已重启 display-manager 服务"
fi
}
# 自动检测并调整显示器配置
auto_adjust_display() {
if has_real_display; then
# 有真实显示器,应禁用虚拟显示器
if [ -f "$CONFIG_PATH" ]; then
echo "检测到真实显示器,禁用虚拟显示器..."
remove_virtual_display
else
echo "检测到真实显示器,无需调整"
fi
else
# 无真实显示器,应启用虚拟显示器
if [ ! -f "$CONFIG_PATH" ]; then
echo "未检测到真实显示器,启用虚拟显示器..."
create_virtual_display
else
echo "未检测到真实显示器,无需调整"
fi
fi
}
# 主函数 - 直接启动自动监听模式
main() {
echo "启动 Ubuntu 虚拟显示器自动控制脚本"
# 初始检测一次
auto_adjust_display
# 然后每10秒检测一次
while true; do
sleep 10
auto_adjust_display
done
}
# 运行主函数
main
2. 保存脚本并设置权限
sudo nano /usr/local/bin/virtual-display-manager.sh
# 粘贴上面的脚本内容
sudo chmod +x /usr/local/bin/virtual-display-manager.sh
系统服务配置
3. 创建系统服务文件
sudo nano /etc/systemd/system/virtual-display-manager.service
添加以下内容:
[Unit]
Description=Virtual Display Manager
After=multi-user.target
[Service]
Type=simple
ExecStart=/usr/local/bin/virtual-display-manager.sh
Restart=always
RestartSec=10
User=root
[Install]
WantedBy=multi-user.target
4. 启用并启动服务
sudo systemctl daemon-reload
sudo systemctl enable virtual-display-manager.service
sudo systemctl start virtual-display-manager.service
重启服务指令:
sudo systemctl restart virtual-display-manager.service
5. 检查服务状态
sudo systemctl status virtual-display-manager.service
服务管理命令
启动服务
sudo systemctl start virtual-display-manager.service
停止服务
sudo systemctl stop virtual-display-manager.service
重启服务
sudo systemctl restart virtual-display-manager.service
禁用开机自启动
sudo systemctl disable virtual-display-manager.service
查看服务日志
sudo journalctl -u virtual-display-manager.service -f
功能说明
这样设置后,脚本将在系统启动时自动运行,并在后台持续监控显示器状态,根据需要启用或禁用虚拟显示器。服务会在意外停止时自动重启(每10秒检查一次),确保始终运行。
注意:切换虚拟显示器配置时会重启显示管理器服务,这将终止当前图形会话和所有运行的图形应用程序。以下是详细说明:
类别 |
会被终止 (❌) |
不会终止 (✅) |
---|---|---|
应用程序 |
所有带有图形界面的程序(浏览器、IDE、办公软件) |
无图形界面的命令行工具(如 |
终端/Shell |
所有图形终端模拟器(GNOME Terminal, Konsole) |
文本控制台(tty1-6)中的 Shell |
进程类型 |
在图形终端中运行的前台进程 |
使用 |
系统服务 |
无 |
所有由 systemd 管理的服务(nginx, docker, sshd) |
用户界面 |
整个桌面环境(GNOME, KDE Plasma, XFCE) |
无 |
因此,在执行此脚本之前(插入或者拔出物理显示器时),务必要保存所有图形应用程序中的重要工作。 对于需要长时间运行的任务,强烈建议在 tmux
或 screen
会话中启动它们,这样即使图形界面重启,任务也会在后台继续运行,之后可以重新连接恢复。