飞蚊话 发布的文章

相关视频:OBSAUR

这个文章只是简要介绍一下使用OBS构建软件包的基本方法,以及AUR与OBS在编写时候的对应关系。编写一个规范且更易维护的软件包要比这里边提到的关注点要多。

一、什么是OBS

开放构建服务Open Build Service)是一个通用的系统,以自动、连贯和可重复的方式从源代码构建和分发软件包。它可以为各种操作系统和硬件架构发布软件。我们用来构建发行版的 OBS 参考服务器目前(2018 年 6 月)已有 53219 个项目,其中包含了 79794 个仓库中的 468316 个软件包,用于众多发行版和架构,并由 53171 个已确认的开发者使用。

资料来源于Portal:构建服务 - openSUSE Wiki

二、什么是AUR

Arch 用户软件仓库(Arch User Repository,AUR)是为用户而建、由用户主导的 Arch 软件仓库。AUR 中的软件包以软件包生成脚本(PKGBUILD))的形式提供,用户自己通过 makepkg) 生成包,再由 pacman) 安装。创建 AUR 的初衷是方便用户维护和分享新软件包,并由官方定期从中挑选软件包进入 community 仓库。许多官方仓库软件包都来自 AUR。通过 AUR,大家相互分享新的软件包生成脚本(PKGBUILD) 和其他相关文件)。用户还可以为软件包投票。如果一个软件包投票足够多、没有协议问题、打包质量好,那么它就很有希望被收录进官方 community 仓库(以后就可以直接通过 pacmanabs 安装了)。

资料来源于Arch User Repository(简体中文)

三、快速通过OBS构建一个软件包

以我打包的electron-wechat为例。

一切的基础,是需要你拥有一个OBS账号并登录。前往OBS官网注册并登录,你就拥有你的工作空间了。

通过Create Package,来创建一个软件包目录,并将源码上传到这个目录中。但要注意的是,OBS构建的服务器是不联网的,所以对于electron-wechat这种nodejs的程序,由于通过npm命令进行构建的时候一定会去往nodejs官网检索相关依赖的最新版本,所以对于这种程序,最简单的办法就是直接上传编译好的文件进行分发。


这里想补充一下:已经在自己的电脑上编译好了,那就已经可以使用了,为啥还要使用OBS打包呢?很简单,因为自己编译出来的东西是零散的,需要手工把文件放到对应的位置上去,而且没有一个统一的卸载方法。通过OBS打包之后,就可以进入到软件源中,直接通过统一的安装/卸载指令来使用一个软件了。


所以对于electron-wechat,我就是在本地编译好了之后,将二进制文件打包成tar.bz2,上传到了打包目录。

之后,编写spec文件。这个文件告诉了OBS到底都需要干什么来完成打包。

在打包目录下新建软件包名.spec,开始填空。(如果使用openSUSE的vi编辑器直接新建的话,会直接生成一个.spec文件的模板,填空即可。)

  • Name: 软件包名
  • Version: 软件包版本
  • Release: 使用默认即可
  • Summary: 一句话介绍
  • License: 许可证类型
  • Group: 软件类别
  • Url: 项目地址
  • Source: 源码地址

    如果有多个源码,可以通过Source0 Source1 依次指定。参考我打包的dingtalk

  • Provides: 提供的内容
  • Obsoletes: 排斥的内容

然后,在%description下写一个比较详细的软件介绍,不主要的部分就写完了。

之后,%prep下写入打包要做的准备工作。比如解压缩源码包。对于以软件包名-版本号.tar.bz2形式的包,默认的%setup -q即可完成解压。其他命名方法的bz2,需要补充 -n 参数。即setup -q -n 包名

如果还有其他要解压之类的工作,一并写在这个下面,可以参考rpm打包的宏,如果不熟悉,也可以使用bash命令代替。

准备工作做好,填写%build编译部分。对于一般的C语言,可以上传源码包,在%build填写编译的指令。而对于nodejs这种无法通过编译的软件,由于上传的就是编译好的二进制文件,所以编译这部分留空。

%install指示了编译出来的所有文件都要放到什么地方。这里相对比较简单理解,就是通过bash命令,把编译出来的文件依次复制到它应该在的位置即可。至于具体应该在什么位置,就要看一看Linux的标准了。如果不确定的话,把所有文件放在/opt/软件名这个文件夹下也未尝不可。这种做法并不标准,但很快。不过即使如此操作,也需要注意desktop桌面入口文件和图标文件一定要放置在它应该在的位置,否则在图形界面一定会找不到启动的按钮,图标显示也会有问题。
%post -p /sbin/ldconfig%postun -p /sbin/ldconfig两句话照抄即可。

之后,在%files下书写这个软件都拥有哪些文件和文件夹。宗旨就是产生了哪些文件,就把绝对路径写在这里。

到此,一个简易的spec文件就写好了。

之后的查错,可以通过OBS编译结果进行排查,根据报错进行修改即可。

四、AUR编写与OBS的异同

AUR与OBS非常类似,区别只在于OBS的spec文件命名是根据软件包名命名的,而AUR的文件叫做PKGBUILD。所以在AUR建立一个软件工程后,直接新建一个PKGBUILD,在里边编写即可。

至于编写的内容,与OBS也很类似,只不过AUR是一个更纯粹的脚本,不能使用OBS里边诸如%prep这种宏来书写。

我的OBS仓库的dingtalk就是借鉴AUR的dingtalk-linux。可以对比着来看一看。

相对来说,AUR的编写更容易上手,但是相对OBS来说,编写出来的PKGBUILD通用性会差一些。不过无论哪种,思路都是类似的。看一看现有的文件写法,自己尝试一下就会了。

前些日子尝试通过电报来实现短信多终端同步的方案,很成功,并且为了实验稳定性开了一天。到了第二天早晨再看,服务是正常的。但新来的短信就是没再往Tg上面发送。

最先想到的就是梯子有问题了,通过尝试也发现确实是梯子的问题。具体表现就是浏览器会报503错误。

现在使用的是v2ray方法,在刚搭建好的时候也遇到过503问题,所以惯性的认为这次出现这个问题也是由于服务器时间与本地时间不一致导致的(服务器商授时比实际时间快了3分钟,不知道什么毛病)。

不过当我查看服务器时间时候,发现问题好像没那么简单了——因为服务器时间很正常,说明并不是时间出错导致的这个问题——一下子就感觉问题严重了起来。

查看服务状态(systemctl status v2ray),是active,一切如常;查看运行日志(/var/log/v2ray/access.log),一大溜的invalid user。这是认证错误;但是我并没有改过我的config文件(/etc/v2ray/config.json)啊,为什么会失效呢?

上网搜索类似的情况,并没有什么有用的解答。不过在网上冲浪的过程中,v2ray的github页面提交issue的模板让我想到了一个可能的原因:

  • 我的安卓机应用是play商店自动更新的
  • 我的iOS应用是商店自动更新的
  • 我的Archlinux是及时跟进版本的
  • 我的openSUSE刚刚做了一次dup,所有存在新版本的软件都升级到了最新

这些都指向了一个可能的原因:版本不同(github上面就写到了如果客户端和服务端版本不同请注明)。我的客户端全部到了最新而服务端已经很久没有更新过了。

所以先尝试把服务端更新到了最新,再次尝试。

仍然503.

这就真让我百思不得其解了。

不过在查看服务状态时,有一行信息引起了我的注意:它提示读取的配置文件路径是/usr/local/etc/v2ray/config.json

咦?跟网上大多数提到的/etc/v2ray/config.json不一样啊。查看了一下usr的配置文件,里边只有一行:

{}

这就很好的解释了为啥认证会失败了。啥配置都没有,能存在有效用户就怪了。

虽然不知道为什么之前的/etc/v2ray/config.json可以生效,但既然它现在貌似读取的是带usr的路径,那给它补上就得了呗。

不过为了延续之前的路径,做一个软连接可能是更恰当的选择。直接ln -s /etc/v2ray/config.json /usr/local/etc/v2ray——当然,提前把usr那个空的config文件删掉。

尝试重启服务systemctl restart v2ray,查看状态……

退出。

不过下面的信息给出了明确的信息:日志文件无法写入。

那就把日志文件的读写权限给上去就得了呗chmod 666 /var/log/v2ray/*

再次启动服务,成功。尝试通过客户端连接,也成功了。


这问题出现的还挺突然的——因为前一天还是可以正常使用的东西,在啥都没手工动过的情况下就不能用了,还是非常没有头绪去解决的。不过好在没有什么特别令人费解的问题(虽然突然间读取的配置文件路径就变了有些令人费解),很快也就解决掉了。但关键在于网上竟然没有一篇文章能适配到这个问题上,所以还是写下来了。

好像很长时间没怎么更新过博客了,就连一些评论也没再回复过。

所以趁着元旦有点时间,简单说说吧。

工作了

去年8月份开始,正式从学生变成了社会人。不好说是否已经完成了身份的改变,但这身份终究是要如此转变的。

我现在就职在某国企的系统集成子公司的总部。不用想,肯定有很多人感觉朝九晚五,工作轻松。

错了。因为它早在3年前就已经进行了混改了,现实的情况是在我去之前,我们组一共4个人,要支撑全国31家分公司和产业互联网公司的业务。你就可以想象一下在总部的这几个人需要拥有多少个分身了。

但现实终究不是西游记,这些人也不可能拥有分身来协助,所以纵使刚刚到岗的我再不熟悉业务,也算是多了一个帮手。什么意思呢?我到岗的第4天就被安排出差去四川了。

从四川回来,是为期一个礼拜的新员工培训——这可能也是我这半年里边最轻松的一个礼拜。

然后便是无止境的工作。对了,我好像还没有介绍公司的上下班时间:早上八点半,晚上五点,不打卡。

但是工作量使得五点这个下班时间没有什么作用,至少从五点半开始,同事才会陆陆续续的离开。

可能即使是这种程度的加班也比一般的互联网公司下班时间早。但是要知道,公司是不打卡的,不打卡就意味着人力或者领导并不知道你到底是几点离岗的,也就意味着加班是没有加班工资的。

退一万步讲,即使我可以做到正点下班,我的单位在二环里,每天我都要往返于六环外和二环里。而这就使得我一天要上两个班:单位一个班,坐车一个班。

说几个数据你可以体会一下:为了保证八点半到岗,我需要赶六点四十五的车上班;五点半出公司的话,我最早可以在八点二十下车到家。

插空做的视频

所以即使正点出公司,我也没有时间在工作日做视频。所以从工作开始,所有的视频都是在礼拜六日抽空录制的。这也是为什么我不再提供字幕了。没时间打轴维护,也懒得在休息日做这么多工作了。

如果你是从b站关注过来的,你应该还记得我在去年八月份时候发过一条动态,就是更新频率从周更调整至四周三更。这是有计算的。因为我知道不管我去到什么样的公司,我家的位置也就保证了我在工作日是没有时间做额外的事情的——有时间也只是在坐车途中看看书。所以所有额外的工作都要堆到周末完成。而一个月有四个礼拜,四周三更就意味着每个月能空出来一个星期。我又没指定四周三更是哪三周更,所以这一个礼拜有着很大的价值:

  • 如果这个月没什么出差也没什么事,那么空出来的这个礼拜可以录一个视频做备用。
  • 如果有出差,那么出差占用的那个礼拜末正好就是四周三更中不更新的那一周,或者直接使用备用视频发布。

事实上也是这样。在这半年里,我已经使用过几个备用视频了,你可以通过结尾来判断。

很少更新的博客

这半年里边,我视频内容更多的是在进行看板主题的解答。这一部分的内容我个人感觉还真不值得写一篇文章来保存,所以也就没有跟随视频的更新而更新。

即使是自己产出的内容,就现在的情况来看也不是很有时间把视频落到文字上面。

不过之后可能就会有所变化了。为什么呢?因为我想变一变我的流程了——文字不是记录,而是草稿。

也就是说,在确定了视频主题后,先落实到文字,再做成视频。相对于现在临场发挥的录制法,这样兴许还会节省不少剪辑衔接的时间。

啊不说了,明天又该上班了。就祝这里的各位新年(公历)大吉吧。

视频点此

这个不是我想到的方法,因为这种笔记本想做到直通太麻烦了。不过机缘巧合,我在这个博客中看到了方法,尝试之后也成功了,遂来记录一下。

上面的博客有着非常详细的操作步骤及一些基本原理介绍,有兴趣可以阅读一下。不过在我尝试的过程中发现文章漏掉了一些步骤,再加上我的电脑与文章的博客不同,获取vBIOS的过程有些许出入,所以这里只记录一下操作过程,每一步的解释及更多扩展请看原博客。

我的电脑:HP暗影精灵一代,i7-6700hq+950M独显

事前准备:KVM虚拟机拥有一个UEFI启动的Win10,含有QXL显卡、实体机启动的win10、Linux宿主在使用英特尔核显,独显驱动禁用或驱动被卸载

一、隔离独显

  1. lspci -nn | grep NVIDIA,获得类似输出:

    01:00.0 3D controller [0302]: NVIDIA Corporation GP107M [GeForce GTX 1050 Mobile] [10de:1c8d] (rev a1)

    记录中括号[10de:1c8d]中的ID

  2. 编辑或创建/etc/modprobe.d/vfio.conf,内容书写 options vfio-pci ids=刚刚记录的ID
  3. 修改/etc/mkinitcpio.conf,在MODULES里增加vfio_pci vfio vfio_iommu_type1 vfio_virqfd
  4. mkinitcpio -P更新initramfs

二、增加英特尔虚拟核显

  1. 编辑/etc/default/grub,在GRUB_CMDLINE_LINUX中增加i915.enable_gvt=1 kvm.ignore_msrs=1 intel_iommu=on
  2. 编辑或创建/etc/modules-load.d/lantian.conf,增加三行

    kvmgt
    vfio-iommu-type1
    vfio-mdev
  3. grub-mkconfig -o /boot/grub/grub.cfg重新生成grub
  4. 重启
  5. lspci | grep "HD Graphics"记录最开始的PCI地址,如00:02.0
  6. 创建显卡

    sudo su
    echo "af5972fb-5530-41a7-0000-fd836204445b" > "/sys/devices/pci0000:00/0000:刚刚记录的PCI地址/mdev_supported_types/i915-GVTg_V5_4/create"

前面两部的成功性验证:

二.4重启之后,使用lspci -nnk查找英伟达,如果kernel in usevfio,则表明隔离NVIDIA成功;二.6第二行命令可以成功执行,则表明创建虚拟核显成功。

三、增加虚拟显卡进虚拟机

virsh edit 虚拟机名,在</device>前增加

<hostdev mode='subsystem' type='mdev' managed='no' model='vfio-pci' display='off'>
  <source>
    <address uuid='af5972fb-5530-41a7-0000-fd836204445b'/>
  </source>
</hostdev>

保存后启动虚拟机,如果在设备管理器中多了一个Microsoft 基本显示适配器,则说明增加成功,耐心等待驱动安装成功,便会显示出Intel核显名称了。

一旦驱动安装完成,关闭虚拟机,再次编辑配置。

  • 刚刚增加的hostdev标签,将display='off'更改为display='on'
  • 删除<graphics><video>两块,用如下内容替换

    <graphics type='spice'>
      <listen type='none'/>
      <image compression='off'/>
      <gl enable='yes'/>
    </graphics>
    <video>
      <model type='none'/>
    </video>
  • </domain>前增加

    <qemu:commandline>
        <qemu:arg value='-set'/>
        <qemu:arg value='device.hostdev0.ramfb=on'/>
        <qemu:arg value='-set'/>
        <qemu:arg value='device.hostdev0.driver=vfio-pci-nohotplug'/>
        <qemu:arg value='-set'/>
        <qemu:arg value='device.hostdev0.x-igd-opregion=on'/>
        <qemu:arg value='-set'/>
        <qemu:arg value='device.hostdev0.xres=1920'/>
        <qemu:arg value='-set'/>
        <qemu:arg value='device.hostdev0.yres=1080'/>
        <qemu:arg value='-set'/>
        <qemu:arg value='device.hostdev0.romfile=/vbios_gvt_uefi.rom'/>
        <qemu:env name='MESA_LOADER_DRIVER_OVERRIDE' value='i965'/>
    </qemu:commandline>

    其中,vbios_gvt_uefi.rom从这里下载,并对应修改上面的文件路径。

  • <domain type='kvm'>更改为<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>

启动虚拟机,如果图像正常显示且设备管理器中只有英特尔核显,则说明截至目前,操作都是成功的。

四、获取显卡vBIOS

这部分在实体Windows下进行。

  1. 前往惠普支持官网,下载适合自己的惠普BIOS更新程序
  2. 百度下载MaxwellBiosTweaker备用
  3. 启动更新程序,选择第三项Copy
  4. 解压缩导出的所有bin文件(已知7z可成功解压)
  5. 进入解压出来的文件夹,打开到有.rom文件的文件夹
  6. 打开MaxwellBiosTweaker,依次将.rom拖入文件,如果程序成功显示各种内容,则这个文件是一个显卡BIOS文件
  7. 对于是显卡BIOS的文件, 对照显示的内容,找到是自己显卡的rom文件,复制出来备用

五、编译虚拟机UEFI固件

这部分回到Linux下进行。

# 根据 GitHub 上用户反馈,UEFI 固件编译完成后不能移动位置
# 所以要先找好存放的地方
cd /opt
# 使用root用户进行,避免sudo前缀
sudo su
git clone https://github.com/tianocore/edk2.git
# 安装编译过程中需要的依赖
pacman -S git python2 iasl nasm subversion perl-libwww vim dos2unix
yaourt -S gcc5
# 假设你导出的显卡 BIOS 存放在 /vbios.rom
cd edk2/OvmfPkg/AcpiPlatformDxe
xxd -i /vbios.rom vrom.h
# 编辑 vrom.h,把 unsigned char 数组(在第一行)的名字修改成 VROM_BIN
# 把文件末尾的长度变量(在最后一行)改名为 VROM_BIN_LEN,并记录下长度值,我的是 167936
wget https://github.com/jscinoz/optimus-vfio-docs/files/1842788/ssdt.txt -O ssdt.asl
# 编辑 ssdt.asl,修改第 37 行为 VROM_BIN_LEN 的值
# 然后执行下面这行命令,会报错但是没关系,只要 Ssdt.aml 有了就行
iasl -f ssdt.asl
xxd -c1 Ssdt.aml | tail -n +37 | cut -f2 -d' ' | paste -sd' ' | sed 's/ //g' | xxd -r -p > vrom_table.aml
xxd -i vrom_table.aml | sed 's/vrom_table_aml/vrom_table/g' > vrom_table.h
# 返回 edk2 的目录下打补丁
cd ../..
wget https://gist.github.com/jscinoz/c43a81882929ceaf7ec90afd820cd470/raw/139799c87fc806a966250e5686e15a28676fc84e/nvidia-hack.diff
dos2unix nvidia-hack.diff
dos2unix OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c
patch -p1 < nvidia-hack.diff
# 开始编译 OVMF
make -C BaseTools
source edksetup.sh
# 修改 Conf/target.txt 中如下变量的值:
# - ACTIVE_PLATFORM       = OvmfPkg/OvmfPkgX64.dsc
# - TARGET_ARCH           = X64
# - TOOL_CHAIN_TAG        = GCC5
build
# 等待编译完成,确认 Build/OvmfX64/DEBUG_GCC5/FV 文件夹下有这两个文件:
# - OVMF_CODE.fd
# - OVMF_VARS.fd
# 然后替换你的虚拟机的 UEFI 参数,注意修改虚拟机名
cp Build/OvmfX64/DEBUG_GCC5/FV/OVMF_VARS.fd /var/lib/libvirt/qemu/nvram/虚拟机名_VARS.fd

六、增加独显进虚拟机

visrh edit 虚拟机名称,做如下配置

<!-- 把 os 一段改成这样,注意对应你的 OVMF_CODE.fd 路径 -->
<os>
  <type arch='x86_64' machine='pc-q35-4.2'>hvm</type>
  <loader readonly='yes' type='pflash'>/opt/edk2/Build/OvmfX64/DEBUG_GCC5/FV/OVMF_CODE.fd</loader>
  <nvram>最后复制的那个路径</nvram>
</os>
<!-- 把 features 一段改成这样,就是让 QEMU 隐藏虚拟机的特征 -->
<features>
  <acpi/>
  <apic/>
  <hyperv>
    <relaxed state='on'/>
    <vapic state='on'/>
    <spinlocks state='on' retries='8191'/>
    <vendor_id state='on' value='GenuineIntel'/>
  </hyperv>
  <kvm>
    <hidden state='on'/>
  </kvm>
  <vmport state='off'/>
</features>
<!-- 添加显卡直通的 PCIe 设备,必须放在核显 hostdev 的后面 -->
<hostdev mode='subsystem' type='pci' managed='yes'>
  <source>
    <address domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
  </source>
  <rom bar='off'/>
  <!-- 注意这里的 PCIe 总线地址必须是 01:00.0,一点都不能差 -->
  <!-- 如果保存时提示 PCIe 总线地址冲突,就把其它设备的 <address> 全部删掉 -->
  <!-- 这样 Libvirt 会重新分配一遍 PCIe 地址 -->
  <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0' multifunction='on'/>
</hostdev>
<!-- 在 </qemu:commandline> 之前添加这些参数 -->
<qemu:arg value='-set'/>
<!-- 下面的两个id为 lspci -nn中的那两个id -->
<qemu:arg value='device.hostdev1.x-pci-vendor-id=0x10de'/>
<qemu:arg value='-set'/>
<qemu:arg value='device.hostdev1.x-pci-device-id=0x1c8d'/>
<qemu:arg value='-set'/>
<!-- 下面的两个id为 lspci -nnk中,subsystem显示的id那两个 -->
<qemu:arg value='device.hostdev1.x-pci-sub-vendor-id=0x17aa'/>
<qemu:arg value='-set'/>
<qemu:arg value='device.hostdev1.x-pci-sub-device-id=0x39d1'/>
<qemu:arg value='-acpitable'/>
<qemu:arg value='file=/ssdt1.dat'/>

最后一行的ssdt1.dat从这里下载,并将路径对应修改。

启动虚拟机,等Win10自动安装驱动。

如果不出意外的话,直通就完成了。

视频点此

VNC,Virtual Network Console的缩写。说白了,VNC是从类Unix系统出来的,横跨全平台的图形远程桌面,有别于纯文本的ssh,功能强大。所以,来看看再Linux下要如何部署VNC服务。

只是使用的话,不必研究它的原理,只需要知道Linux下面是通过软件包tigervnc来实现vnc服务的即可。

这里以Arch为例。

  • 安装tigervnc:pacman -S tigervnc
  • 启动vnc服务:vncserver

    • 要求一个密码,输入后回车
    • 确认刚刚输入的密码,输入后回车
    • 是否需要一个仅查看的密码,需要则输入y回车,否则输入n回车完成设置
    • 若输入y,则继续输入新的密码两遍,完成配置
  • 编辑~/.vnc/xstartup,只保留最前面unset开头的两行,之后的全部删除,并增加一行exec dbus-launch startplasma-x11(这是kde桌面增加的行,其他的请去往wiki查看),保存
  • 注销再登录,重新启动vnc服务,设置完成

到此,就可以从其他电脑上通过vnc相关软件连接了。其中,vnc使用的端口在输入vncserver之后输出的内容中有所体现。规律为5900+冒号后的数字。如输出为:1,则端口号为5901

更多资料

更详细更高级的vnc使用方法,参考TigerVNC (简体中文) - ArchWikiVNC - openSUSE Wiki

视频点此

我曾经说过如何在Windows下屏蔽笔记本键盘的教程。现在,来看看Linux下面如何实现屏蔽笔记本键盘。

Linux屏蔽需要安装一个工具xinput。arch系的包名为xorg-xinput,debian系的包名为xinput

之后,通过命令xinput找到自带键盘设备的ID号。这个设备的名字为AT Translated Set 2 Keyboard。找到以这个名字开头的一行,记录后面id=字段的数字。我这里是11.

最后,通过命令xinput set-prop ID 'Device Enabled' 0来完成设备的仅用。其中,ID区域替换为前面找到的数字。

如果想恢复使用,将结尾的0更改为1即可。