分类 技术向 下的文章

记一次神奇的Manjaro文件丢失修复


事件起因

上次关闭了虚拟机之后, 手贱在Vmware里使用了"压缩磁盘以回收未使用的空间", 然后下次再启动的时候, 启动就报错了...
QQ图片20180808090659.jpg

故障现象

/sbin/init提示找不到libz.so.1文件找不到.
QQ图片20180808090624.png

故障分析

libz.so.1是zlib的库文件, 在系统中肯定是安装了的.

  • 联想到上次关机前, 我滚了一次系统, 首先想到是不是Arch又日常滚挂了, 于是打开了Arch官网...可是没有任何关于此的通知, 相比应该不是滚系统的原因.
  • 联想到我关机之后压缩了一下磁盘, 第二反应是不是文件系统挂了, 于是启动了livecd, 跑起了brtfsck, 然而它告诉我其实什么问题也没有.

恢复过程

于是这就很尴尬了...
既然文件系统本身没问题, 那就只好先恢复系统再说, 于是在livecd里把磁盘挂载, 然后find -name "libz.so.1"...
QQ图片20180808090634.png
诶...怎么只在/usr/lib32/下有libz.so.1, 看来应该是/usr/lib/下的文件丢失了导致的.
嗯 复制livecd的libz.so.1到/usr/lib/, 成功启动.

然后我需要重装一下zlib, 于是pacman -S zlib启动!
QQ图片20180808090641.png
emmmm 我的pacman发生了什么!
看来不仅仅是丢了一个libz.so.1的问题...好像zlib的软件包元数据也丢了Orz
更神奇的是, 我安装其他软件都没问题, 唯独zlib...emmmmm

群里有大佬建议说, 你不如用pacstrap安装一下试试看, 于是...
QQ图片20180808090648.png
emmmmm 还是不行啊Orz

思考了一下, 你不是说desc文件找不到么, 于是我去那个目录看了一下
emmmm 好像只剩下一个mtree文件了, desc和files都丢掉了...
于是我想要不干脆把这个文件夹删掉, 是不是就当作我从来没装过zlib了.
立刻mv /var/lib/pacman/local/zlib-1:1.2.11-3 ~/ && pacman -S zlib
QQ截图20180808093307.png
emmmm 好像是真的 虽然提示文件系统中已存在 这当然是因为我们已经安装过的原因

不过可以这样 pacman -S --dbonly zlib~
QQ截图20180808093429.png
成功! 这个时候再去pacman -S zlib已经一点问题也没有了yeah

总结与后记

  • pacman的软件包数据库真简单啊, 除了mtree是未知格式以外, desc和files都是纯文本文件
  • pacman的单个软件包数据库挂了完全一点都不影响到整个软件包仓库
  • 恢复完之后, 我发现上次关机前我滚过的包, 它又提醒我再滚一遍, 仿佛是一段时间内的磁盘写入完全丢失, 甚至还丢了别的文件
  • 如果真的丢了别的文件, 其实我也看不出来Orz
  • 所以既然用了brtfs, 那么就要常做snapshot啊_(:3」∠)_
  • 所以下次再也不手贱压缩磁盘了!!!

以上


使用Matplotlib画图时如何修改字体及显示汉字


前情提要

Matplotlib是python下一个非常常用的绘图库, 可是如果你用pip install matplotlib默认安装后, 却会发现它会把你输入的中文变成框框.
原因其实很简单, 只是因为默认的Matplotlib安装不带中文字体而已, 所以我们需要将添加中文字体进去.
当然还有可能的原因是你用的是python2, 对于utf-8的中文文本要进行一些别的非常恶心的操作, 当然这个不是本文的讨论范围.
以下文字的操作环境是Windows SubSystem for Linux, 但是原理在各个平台应该是通用的.

如何添加中文字体到Matplotlib中

Matplotlib的字体无论是在Linux还是在Windows中, 都和系统字体是完全独立的, 因此你需要手动将中文复制到其字体路径中去.
具体的路径位置和你当前使用python的site-packages路径有关, 在Linux中这个路径有可能在/usr/lib/python*下也有可能在~/.local/lib/python*下, 而在Windows中这个路径应该在你的python安装路径下.
那么具体的字体文件夹路径在哪里呢?假设$site-packages是你的site-packages路径, 那么字体目录在$site-packages/matplotlib/mpl-data/font下. 当然这个目录下一般会有afm pdfcorefonts ttf三个文件夹, 一般我们添加的都是ttf字体, 因此一般是添加到该目录下. 注意ttc字体放在这个目录下并不能被识别
比较推荐的代码字体有: 更纱黑体, 思源黑体.
更纱黑体是某个在微软工作的大佬正在开发而且不断在维护的一个字体, 效果很棒.
思源黑体是Adode开源的一个字体, 对于汉字和字幕都有着很好的效果.
总体来说, 这两个字体的显示效果差不多, 细节上略有差别, 具体的细节可以戳这里.

清空字体缓存

rm -rf ~/.cache/matplotlib

只有正确清空了字体缓存, 你的字体才会被Matplotlib再次识别. 对于Windows, 这个路径可能在C:\Users\$username\.matplotlib下.

查看已经添加在Matplotlib中的字体名

from matplotlib.font_manager import FontManager

fm = FontManager()
mat_fonts = set(f.name for f in fm.ttflist)
print(mat_fonts)

在Matplotlib中是使用字体名来配置字体的, 而不是字体的文件名, 因此你需要是从这里读到的字体名来进行下面的配置, 同时也可以查看之前的添加字体操作是否成功.

修改Matplotlib的字体配置

修改Matplotlib的字体配置, 有两种方法:
一种是我们可以在代码中修改配置;
另外一种是我们可以去修改Matplotlib的配置文件;

在代码中修改配置

通过plt.rcParams['$config_item']就可以修改Matplotlib的字体配置选项.
Matplotlib中一共有五种类型的字体, 分别是:

plt.rcParams['font.serif']=['Sarasa Mono SC'] # 衬线字体
plt.rcParams['font.sans-serif']=['Sarasa Mono SC'] # 无衬线字体
plt.rcParams['font.cursive']=['Sarasa Mono SC'] # 手写字体
plt.rcParams['font.fantasy']=['Sarasa Mono SC'] # 梦幻字体
plt.rcParams['font.monospace']=['Sarasa Mono SC'] # 等宽字体

直接修改配置文件

通过下面的代码可以读取到matplotlib的配置文件, 当然这个配置文件一般在$site-packages/matplotlib/mpl-data/matplotlibrc下:

import matplotlib

print(matplotlib.matplotlib_fname())

在这个文件搜索font.serif就会看到之前说的五大字体族了, 去掉前面的#号注释, 再在:前加上你的字体名就可以添加字体了的说.

最后的效果如图所示

QQ截图20180511151753.png


在WSL运行32位应用程序的神奇操作


在WSL运行32位应用程序的神奇操作

原理

主要的操作是通过qemu-i386-static模拟来运行x32程序, 然后通过binfmt来指定使用qemu来运行给定x32二进制文件

首先需要开启debian的x32基础支持

dpkg --add-architecture i386
apt-get update
apt-get install libstdc++6:i386

这会在dpkg中添加i386架构, 这样就可以通过apt工具安装i386的包了, 然后安装libstdc++会自动安装libc6/libgcc_s, 这样就可以运行基本的x32程序了.
一般的Linux到这一步就已经可以运行x32的程序了, 但是对于WSL来说还是不行, 使用ldd exec依然会告诉你这不是一个可执行文件, 于是说我们需要安装qemu.

安装qemu

apt-get update
apt-get install qemu-user-static

这样我们就可以通过qemu-i386-static exec来实际的运行我们想要的x32程序了, 但是这样很麻烦, 于是我们可以配置binfmt来自动使用qemu来运行qemu.

配置binfmt

update-binfmts --install i386 /usr/bin/qemu-i386-static --magic '\x7fELF\x01\x01\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x03\x00\x01\x00\x00\x00' --mask '\xff\xff\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xf8\xff\xff\xff\xff\xff\xff\xff'
service binfmt-support start

这样, 我们就可以像在正常Linux里面一样运行x32的程序了. 真是非常神奇的操作_(:3」∠)_

后记

当然每次启动要记得启动一下binfmt服务才行.

service binfmt-support start

Reference: https://github.com/Microsoft/WSL/issues/2468#issuecomment-374904520


Hibernate 5.1.1 + Spring 4.2.9 + Proxool 0.8.3 踩坑记录


起因

折腾的原因完全来自于我不想把DataSource配置到Spring的ApplicationContext中去.
希望Hibernate能够单独用一个配置文件, 这样就可以脱离Spring单独调试数据库部分的代码.

前提

原本在Spring 3.x + Hibernate 2.x的条件下已经成功了, 但是迁移到新版本就产生了各种各样的神奇的坑.

第一个坑

在新版本的Hibernate中, 在不使用org.apache.commons.dbcp.BasicDataSource的情况下, 似乎是不能用内置的默认连接池的.
大概看了下, Proxool似乎性能比较好, 用的比较多于是打算用这货.

抄了下网上常见的配置, 大概是这样的:

        <property name="hibernate.connection.provider_class">org.hibernate.proxool.internal.ProxoolConnectionProvider</property>
        <property name="hibernate.proxool.pool_alias">DBPool</property>
        <property name="hibernate.proxool.properties">test.properties</property>

可是...并不能找到配置文件, 从Trace一层一层网上看, 似乎是不知道传进去的路径是什么类型...
想了想, 加了file://可是依然不行= =
翻了好久源码, 突然看到...这货好像是从classpath开始搜索的...
放在classpath下果然就行了= =

第二个坑

Caused by: org.hibernate.service.UnknownUnwrapTypeException: Cannot unwrap to requested type [javax.sql.DataSource]

因为我把数据源配置在proxool里面, 所以明面上并没有给HibernateTransactionManager显式地传数据源...
可是HibernateTransactionManager在初始化的时候发现没有数据源会非常执着的去拿数据源, 拿不到还会去找ContentProvider要...可是并不能unwrap到数据源于是就报错了...
解决也很简单, HibernateTransactionManager有一个叫做autodetectDataSource的属性, 将其改为false即可.

第三个坑

其实算是我自己作死...
因为为了省事我把MVC和Spring的ApplicationContext写在一起了...
然后proxool会报错说配置文件已经配置...[md不能智能一点么]
想了想之前看的Spring文档, 好像Spring的Application和MVC并不是同一个Context.
又看了下web.xml...好像在ServletContext和Servlet的init-param里面指定了两遍...
于是把sessionFactory单独拿出来放在Application的Context配置里就可以了= =

第四个坑

这个也是很迷...看之前的书, 他告诉我Hibernate的current_session_context_class属性应当设置为thread.
我也就照着做了...可是我在执行任何操作的时候都会和我说Transcation没有ACTIVE???
追踪到TransacationManager里去也发现这里面的Transcation也正常的ACTIVE了.
可是执行的时候却拿不到ACTIVE过的session???
认真看了源码...好像它每次执行数据库操作的时候都是从Factory生成一个Session然后就去执行了...EXECUSE ME???
TransacationManger管理的Session呢???
查了好久发现...这篇文章难怪= =拿不到TransacationManger管理的Session啊_(:_」)_

配置了<property name="current_session_context_class">org.springframework.orm.hibernate5.SpringSessionContext</property>马上就好了(╯‵□′)╯︵┻━┻


如何在Terminal中使用Sock5代理


大部分终端应用, 比如wget, curl都支持http_proxy, https_proxy变量配置HTTP代理.
然而常见的SS使用的则是SOCKS代理, 可以使用privoxy做SOCK->HTTP的转换.
但是相对而言privoxy比较重量级, 因此可以采用polipo做转换.

Mac OSX下可以使用brew安装:

brew install polipo

然后添加代理:

vi /usr/local/opt/polipo/homebrew.mxcl.polipo.plist

在array标签之间添加socksParentProxy选项:

<array>
        <string>/usr/local/opt/polipo/bin/polipo</string>
        <string>socksParentProxy=localhost:1080</string>
</array>

测试并启用代理

#!/bin/sh

export http_proxy=""
export https_proxy=""
curl ip.gs
launchctl unload /usr/local/opt/polipo/homebrew.mxcl.polipo.plist &> /dev/null
launchctl load /usr/local/opt/polipo/homebrew.mxcl.polipo.plist
ping -c 3 127.0.0.1 &> /dev/null
export http_proxy="localhost:8123"
export https_proxy="localhost:8123"
curl ip.gs

保存上述内容到http_proxy.sh文件, 需要代理时source文件既可.

source http_proxy.sh