WSL+Manjaro+Xfce打造完美开发环境

  • 基于WSL,运行具有图形界面的Linux程序
  • 使用Manjaro避开Ubuntu等WSL发行版大版本升级容易产生的问题
  • 使用sshVisual GDB,在Linux环编译境下用Visual Studio开发C++程序——有Linux上编译环境的省心,又可以利用Visual Studio这一宇宙第一IDE进行大型项目开发。

安装的过程主要参考了WSL使用小结:从ArchLinux到Manjaro,但这篇文章还是有一些点没有讲到,这里补充一下。

首先,去控制面板开启WSL,然后去应用商店装个Ubuntu,这都属于常规操作。

应用商店装完Ubuntu后,启动之,这时会释放实际的Ubuntu文件,然后会让你新建用户。此时不要新建,直接Ctrl+C打断。随后从cmd运行bash,就以root权限进入了Linux子系统。

下面做的事比较复杂:

从开始菜单打开 Ubuntu。从[清华的ArchLinux镜像](https://mirrors.tuna.tsinghua.edu.cn/archlinux/iso/latest/) 下载 Arch bootstrap .tar.gz 放在root用户的目录LocalState\rootfs\root下,然后解压【注:解压archlinux-bootstrap时在root目录,外面可能会出问题】:$ tar -zxvf archlinux-bootstrap-2017.11.01-x86_64.tar.gz

注释:必须在Linux里面解压,不能在win中解压完了拖进去,权限会有问题。

在 ~/root.x86_64/etc/pacman.d/mirrorlist 文件中,选择需要的服务器,取消注释。这一步直接换成Manjaro的 清华镜像:Server = https://mirrors.tuna.tsinghua.edu.cn/manjaro/stable/$repo/$arch

注释:我觉得中科大的镜像更快

让 WSL 自动生成 /etc/resolv.conf 【注:或者 直接删除 /etc/resolv.conf文件】:$ echo "# This file was automatically generated by WSL. To stop automatic generation of this file, remove this line." > ~/root.x86_64/etc/resolv.conf退出所有打开的 Bash 命令行窗口。在 Windows 资源管理器中打开 %localappdata%\Packages,并找到 CanonicalGroupLimited.UbuntuonWindows_* (其中, * 表示随机字符串 )。在 %localappdata%\Packages\CanonicalGroupLimited.UbuntuonWindows_*\LocalState\rootfs 中删除 bin, etc, lib, lib64, sbin, usr and var。然后从rootfs\root\root.x86_64移动(不要复制)相同的文件到 rootfs。

至此,之前安装的Ubuntu被替换为一个尚未安装完毕的Arch,且软件源被指向了Manjaro的软件仓库。

此时,“WSL使用小结:从ArchLinux到Manjaro”一文提到需要执行pacman -Syu升级当前软件,但实际上如此执行会报key错误,原因是当前安装的文件都是Arch的,但软件仓库中下载的包都是Manjaro签名的,不是一个系统。为此,首先尝试安装manjaro-keyring软件包:

pacman -S manjaro-keyring

不出意外会报错,并询问你是否要删除已下载的文件。选择否,然后从本地强制安装此包:

pacman -U /pat/to/manjaro-keyring/package

安装过程中应该会自动进行各种key的初始化,之后就可以pacman -Syu,如果还是不行,执行以下命令初始化刚刚安装的key

pacman-key --init
pacman-key --populate archlinux manjaro

出错的话都有提示,仔细阅读按提示执行就好。

Arch Wiki中也有对于在WSL中安装Arch的描述,其中提到需要安装fakeroot-tcpglibc-wsl。目前,glibc-wsl的问题已经被微软官方解决。fakeroot-tcp貌似主要是yaourt在用,不急安装。

一切搞定之后,pacman -Syu更新软件。更新可能覆盖之前的软件源设置,检查一下,否则后面又跑到国外下载软件去了。

原作者提供了一份好几百行的文件,包含了Manjaro官方镜像所具有的包。实际上这些包很多有相互依赖关系,装一个就是全家桶。并且有一些是WSL中明显用不到的,所以我只挑选了一些看起来有用的,其他的用到时再装也不迟。我的初始安装只有下面两个组:

pacman -S base-devel
pacman -S xfce4

pacman会自动把依赖们装上,也有大几百兆,耐心。随后参考原文设置语言环境,设置export DISPLAY=:0等。

一切装完之后,需要首先新建一个常规用户,然后在WSL外面使用ubuntu config --default-user username命令设置新的默认用户。奇怪的是这一命令并不会当场生效,据我观察需要重启才行。这一命令对应的注册表是计算机\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lxss\{4xxxx2-2e4c-4b3b-9b40-1xxxxxx}\DefaultUid,记录默认用户的Linux User ID

图形环境由VcXsrv呈现,这一点网上教程很多,不再详述,先把运行起来把GUI显示出来,后面还要改。

不用原文的MobaXtem原因是,经我测试,目前(2018年8月30日),对于高分屏,仅有VcXsrv可以可靠支持,这还是在修改了VcXsrv可执行文件的高DPI行为之后。其他包括MobaXtemXManager在内都是模糊的,调不过来。

网上教程,包括本文的主参考文献,多是使用export DISPLAY=:0在本地运行图形服务,但我发现使用ssh服务,远程登陆到本地WSL内执行图形任务可能体验更好一些,原因包括:

  • 可以在使用VcXsrv的前提下实现双击打开Linux桌面
  • 既然要用Visual GDB,后台总是要跑一个ssh服务的,空闲时又不占资源
  • ssh服务可以使用VBS脚本做到后台开机自启,很省心

这一阶段任务比较杂,仅写下要点:

  • 安装openssh
  • 最好使用使用/usr/sbin/sshd -D启动ssh服务
  • 新建一个VBS文件丢到启动目录或者新建计划任务,开机执行C:\Windows\System32\bash.exe -c 'sudo /usr/sbin/sshd -D'
  • ssh最好设置成使用私钥登陆
  • 使用sudoer机制实现sudo /usr/sbin/sshd -D的无密码执行。为防止手滑作死,其他命令最好还是要输密码才能执行,具体配置如下:

    root ALL=(ALL) ALL xxxx ALL=(ALL) ALL xxxx ALL=(root) NOPASSWD: /usr/sbin/sshd

至此,应该有了一个开机自启、可以通过私钥登陆的ssh服务。使用VcXsrv的“启动远程程序来启动GUI”功能,可以配置出来一个双击启动即可登陆到ssh并启动startxfce4

启动VcXsrvXlaunch,窗口设置无所谓,建议用无边框最大化窗口,Display number就留着默认自动选择,下一项选择start a program,再然后选择远程程序,用户名密码密钥什么的按需填写,启动的程序写LANG=zh-CN.UTF-8;LC_ALL=zh_CN.UTF-8 /usr/sbin/startxfce4,以保证仍然是中文环境。后面的选项基本无所谓,最后一步选择将配置保存到xlaunch文件。该文件可以用记事本打开编辑。举例如下:

<?xml version="1.0" encoding="UTF-8"?>
<XLaunch WindowMode="Nodecoration" ClientMode="StartProgram" LocalClient="False" Display="-1" LocalProgram="xcalc" RemoteProgram="LANG=zh-CN.UTF-8 LC_ALL=zh_CN.UTF-8 /usr/sbin/startxfce4 1>/dev/null 2>/dev/null" RemotePassword="" PrivateKey="C:\Users\metor\.ssh\PuTTY.ppk" RemoteHost="127.0.0.1" RemoteUser="metorm" XDMCPHost="" XDMCPBroadcast="False" XDMCPIndirect="False" Clipboard="True" ClipboardPrimary="True" ExtraParams="" Wgl="True" DisableAC="False" XDMCPTerminate="False"/>

双击此文件,即可打开一个Xfce工作环境,爽!

使用要点:

  • 要退出时,用Xfce的注销功能,然后关闭VcXsrv窗口
  • 避免同时多个实例启动Xfce界面

记得必须找到预编译的fakeroot-tcp手动安装进去。

使用yaourt安装过了,结论是基于此程序在图形界面响应速度上比原生程序(例如Qt程序)慢了一个数量级,怀疑是Electron底层作怪,无法解决,弃用,也没心情去尝试Atom会不会好一点了——印象中Atom本来就相对慢一些。

基础不牢,地动山摇。

刚装好时,一些依赖Qt的程序安装正常,但可能会无法打开。从命令行运行可以发现,这些程序报错的位置是统一的:

xxx程序xxx: error while loading shared libraries: libQt5Core.so.5: cannot open shared object file: No such file or directory

这个错误出现了原因是WSL中的一个底层实现有问题,详细讨论可以关注下面这个链接:

https://superuser.com/questions/1347723/arch-on-wsl-libqt5core-so-5-not-found-despite-being-installed
https://github.com/Microsoft/WSL/issues/3023

修正则比较简单:

sudo strip --remove-section=.note.ABI-tag /usr/lib64/libQt5Core.so.5

折腾ssh服务,一个很重要的原因(还好不是全部原因)是想用Visual GDB,折腾完了之后我发现,新版的Visual GDB已经专门提供了利用WSL编译的功能……

不过ssh服务对于编程仍然是有意义的——貌似直接用WSL的话,Visual GDB中的程序只能以调试模式运行,不能直接运行.

浏览器这玩意儿相对于编辑器,反应速度更重要。恰好WSL具有一项神奇的能力:在Linux系统下可以直接调用Windows程序,并且可以正常传递命令行和标准输入输出。

WSL(windows subsytem linux)下添加网络浏览器支持一文利用此特性在WSL/Ubuntu下实现了从Linux的jupyter开启Windows下的Chrome浏览器。但Xfce的设置是不同的。

Xfce下,浏览器需要通过gio mime命令或者设置管理器-首选应用程序来设置。同时,这套机制处理不了带空格的路径,加转义符也不行,所以首先需要做一个软连接把Chrome的可执行文件引入到home路径里面来(相当于把空格交给底层去处理):

➜  ~ ln -s /mnt/c/Program\ Files\ \(x86\)/Google/Chrome/Application/chrome.exe winBrowser

然后在设置管理器-首选应用程序,将默认浏览器指向/home/xxx/winBrowser,系统会自动加上一个%s参数。这时再启动jupyter一类的东西,Windows下的Chrome浏览器就会自己弹出来。

搜狗Linux输入法已经支持账户同步了,业界良心!

要安装它,首先需要安装fcitx-im软件组,记住要全部安装。然后从yaourt安装fcitx-sogoupinyin,然后修改上面的XLaunch文件,在远程命令里面多加入几个环境变量:

LANG=zh-CN.UTF-8 LC_ALL=zh_CN.UTF-8 XMODIFIERS=@im=fcitx GTK_IM_MODULE=fcitx QT_IM_MODULE=fcitx /usr/sbin/startxfce4 1

注销再登陆,应该没有问题了。有问题的话运行fcitx-diagnose仔细看报告,常见问题都能找出来。

  • 最后更改: 2022/01/22 14:19