如何在多屏幕运行自定义编译的xmobar?现存问题求解
双屏Xmobar方案问题解析与修复建议
核心结论
单进程运行多个Xmobar实例理论可行,但Xmobar的插件和核心组件设计未考虑多实例场景,会引发全局状态冲突、资源竞争等问题,调试成本极高。更高效的方案是回到多进程模式,为自定义编译的Xmobar实现-x参数,复用你原本的工作流。
现有单进程方案的bug分析与修复尝试
1. 内存监控显示Updating...
这确实是依赖缺失导致的。Xmobar的系统监控插件(如Memory)依赖系统级库:
- Debian/Ubuntu系:需安装
libgtop-dev - Fedora/RPM系:需安装
libgtop2-devel
重新安装依赖后,用Stack重新编译自定义Xmobar即可解决。
2. 仅第一个屏幕的插件定期更新
Xmobar的内置插件(如Clock、Memory)依赖全局定时器或共享状态,单进程多实例下会出现状态抢占,只有第一个实例的定时器能正常触发。
修复尝试:为每个实例创建完全独立的配置对象,包括插件的更新间隔,避免共享任何全局状态。但这种修改需要深入Xmobar内部代码,复杂度很高,且无法保证所有插件都能兼容。
3. UnsafeStdinReader仅单栏更新
一个进程只有一个标准输入(stdin),两个Xmobar实例在同一进程内会争抢这个输入流,导致数据读取混乱。
修复尝试:需修改Xmobar的UnsafeStdinReader实现,支持指定自定义输入源(如命名管道),但这涉及核心代码修改,成本远高于切换到多进程方案。
推荐方案:多进程+自定义-x参数
这个方案和你原本的工作流一致,仅需为自定义Xmobar添加命令行参数解析,实现-x <screen-id>功能:
步骤1:修改自定义Xmobar的App/xmobar/Main.hs
import System.Environment (getArgs) import Text.Read (readMaybe) import XMonad.Theme.XMobar (configFromTheme) import XMonad.Theme.XResources (loadXResources) import Xmobar main :: IO () main = do args <- getArgs -- 解析-x参数,获取屏幕ID let screenId = case args of ["-x", sid] -> readMaybe sid _ -> Nothing -- 加载主题配置 config <- fmap configFromTheme <$> loadXResources case config of Nothing -> putStrLn "Failed to load Xmobar config from theme" Just cfg -> xmobar $ case screenId of -- 设置对应屏幕的位置 Just sid -> cfg { position = OnScreen sid (position cfg) } Nothing -> cfg
步骤2:恢复Xmonad的多进程启动代码
修改app/xmonad/Main.hs回到原本的多进程启动方式:
main :: IO () main = do bars <- traverse (spawnPipe . mappend "~/.xmonad/xmobar -x ") ["0", "1"] xmonad . plugins $ def { manageHook = myManageHook, layoutHook = myLayout, logHook = for_ bars myLogHook, }
方案优势
- 每个Xmobar都是独立进程,无全局状态冲突,插件、stdin各自独立运行,彻底解决所有现有bug
- 完全复用你原本的工作流,学习和修改成本极低
- 后续维护简单,无需担心Xmobar版本更新带来的兼容性问题
内容的提问来源于stack exchange,提问作者cheezsteak
相关产品推荐
相关产品推荐

