作者: meathill

  • 重置 MariaDB root 密码

    重置 MariaDB root 密码

    以我最常用的 Ubuntu 为例,记录如何重置 MariaDB root 密码。MariaDB 是 MySQL 原作者在 MySQL 闭源之后的再起之作,基本能完全兼容 MySQL。在我的 Ubuntu 上,它的大部分命名都沿用 MySQL。

    1. 停掉 mysql 服务

    $ service mysql stop

    2. 以特殊方式启动 mysql

    使用 --skip-grant-tables 可以跳过用户权限检查,让你没有密码也能连接。此时为了避免安全问题,可以加上 --skip-networking,防止有人此时通过网络连接你的数据库。在本地环境下差别不大。

    $ sudo mysqld_safe --skip-grant-tables --skip-networking &

    这一步可能会启动失败,导致下一步连接时报错:ERROR 2002 (HY000): Can’t connect to local MySQL server through socket ’/var/run/mysqld/mysqld.sock’ (2),此时,可以这样修正:

    $ sudo mkdir /var/run/mysqld
    $ sudo chown mysql /var/run/mysqld

    3. 连接数据库

    $ mysql -u root

    正常情况下就连上了。

    4. 重置密码

    mysql> FLUSH PRIVILEGES;
    mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'new_password';

    5. 重启 mysql

    按照参考文档里介绍的做法,需要

    $ sudo kill `cat /var/run/mysqld/mysqld.pid`
    # 或
    $ sudo kill `/var/run/mariadb/mariadb.pid`

    不过我实际操作的时候只要把(2)开启的进程关掉就好了。然后重启 mysql 服务:

    $ service mysql restart

    6. 完成

    尝试一下连接,应该可以成功了:

    $ mysql -uroot -p

    7. Ghost 连接

    虽然命令行连接成功,但是 ghost start 仍然报错,经查,是 Ghost 的数据库连接方式有点问题,修改 config.production.json,加入一行配置即可,大体如下:

    {
      "client": "mysql",
      "connection": {
        ....
        "socketPath": "/var/run/mysqld/mysqld.sock",
      }
    }
    (更多…)
  • 突发招聘: Zine 诚聘 Web 前端开发工程师 全职远程

    突发招聘: Zine 诚聘 Web 前端开发工程师 全职远程

    早上刷推,看到一家全职远程公司招聘 Web 前端开发工程师,叫 Zine,做编辑器产品。心想正好可以水一篇更新,就转载一下吧。

    我跟这家公司并不熟,不过经常在 V2 上看到他们家的消息,应该还是可以的,有自己的产品,有五险一金。感兴趣、并且有定力的同学可以试一试。

    投了再说:

    hr@auramarker.com

    关于投简历的建议:

    1. 开篇写一段100~150字的自我描述,让招聘方对你有一个概括的了解。同时你会更像一个人,而不是某个数字。
    2. 针对对方的 JD 强调自己的优势,比如类似的技术背景、产品开发经验、或者深度用户
    3. 对职业经历的描述要体现自己的价值,哪怕只是参与者,不要写“负责完成领导交付的任务”

    完整的 JD 在这里:

    【全职远程】 Zine 诚聘 Web 前端开发工程师

    V2上的帖子:

    「全职远程」 Zine 诚聘 Web 前端 开发者

  • GitHub 开放自定义 Profile 功能

    GitHub 开放自定义 Profile 功能

    GitHub 有一个个人简介(Profile)页面,比如我,我的用户名是 meathill,我的个人简介就是 https://github.com/meathill。这个页面和 GitHub Pages 有所不同,后者是完全自定义的,想放啥都可以;Profile 页面只体现我们在 GitHub 上的状态。

    不过很多同学并不满足 GitHub Pages,还想定义这个页面;现在 GitHub 闲钱也比较多,可以改进这些痒点;于是乎,自定义 profile 就诞生了。

    使用方法:

    1. 创建一个与用户名相同的仓库,比如我,就是 meathill 仓库
    2. 创建时,你就能看到小提示了:(因为我已经创建过仓库,所以有错误提示,正常没有)
    3. 如提示所写,你只需要编辑这个仓库里的 README 文件,就会自动更新页面上的内容
    4. 更新后的效果如下:

    感觉还不错,近期找工作的同学赶紧用起来吧,是个不错的加分项。

  • Ubuntu 20.04 科学上网

    Ubuntu 20.04 科学上网

    闲言少叙,直奔主题。

    0. 服务器

    首先,你得先准备个服务器。本文不讨论如何制备科学上网服务器。

    如果你用 Mac 或者 iPhone,想玩 Clubhouse,可以考虑买个现成,比如链接里这个(其实只要你有 AnyConnect,任何系统都可以用)。

    1. 客户端

    接下来,下载客户端。

    我用的是 shadowsocks-qt5,先在 https://github.com/shadowsocks/shadowsocks-qt5/releases 这个页面下载打包好的 AppImage 文件。

    右键点击文件,在“权限”选项卡里勾选“允许文件作为程序执行”,然后双击运行,配置服务器信息。配置完成,点击“连接”,顺利的话,就会显示连接成功。

    在命令行里输入 gnome-session-properties,会启动如下图所示的“启动应用程序首选项”,把刚才下载的 AppImage 路径添加进来,这样每次启动 ss 客户端都会自动启动了。

    启动应用程序首选项

    2. 生成 pac

    安装genpac

    pip install genpac

    Ubuntu 20.04 默认 python版本是 3,所以可以使用 pip3 替代上面的 pip。

    使用在线的 gfwlist

    genpac --pac-proxy "SOCKS5 127.0.0.1:1080" --gfwlist-proxy="SOCKS5 127.0.0.1:1080" --gfwlist-url=https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt --output="autoproxy.pac"

    使用离线的 gfwlist

    如果你的机器没有完成配置,暂时无法访问到 gfwlist,也可以先想办法下载到这个文件,然后离线生成。

    genpac --pac-proxy "SOCKS5 127.0.0.1:1080" --gfwlist-proxy="SOCKS5 127.0.0.1:1080" --gfwlist-local=你的路径/gfwlist.txt --output="autoproxy.pac"

    3. 配置服务器

    Ubuntu 安装时就集成了 Apache2,并且默认也会启动它,所以直接把刚才生成的 pac 文件放在 /var/www/html/ 目录下,就能通过 http://localhost/autoproxy.pac 访问到。

    不过我不喜欢用 apache,一般都会用 nginx 或者 openresty 取代之。好在默认情况下,nginx 的 web 服务目录也是 /var/www/html,所以只要卸载 apache 然后重新安装 nginx 即可。另外因为这个服务只为使用 pac 文件,所以可以不用换源。

    sudo apt remove apache2
    sudo apt update
    # 安装 openresty 需要的系统依赖
    sudo apt-get -y install --no-install-recommends wget gnupg ca-certificates
    # 添加 key
    wget -O - https://openresty.org/package/pubkey.gpg | sudo apt-key add -
    # 添加 openresty 官方源
    echo "deb http://openresty.org/package/ubuntu $(lsb_release -sc) main" 
        | sudo tee /etc/apt/sources.list.d/openresty.list
    # 在更新一次,然后安装
    sudo apt update
    sudo apt install openresty
    sudo service openresty start

    然后访问 http://localhost/autoproxy.pac,如果能打开,就说明配置成功。

    4. 启动全局配置

    如果,打开“设置”,找到“网络”,打开“网络代理”,选择“自动”,然后填入上面说的 pac 地址即可。

    5. 在其它应用里完成配置

    比如,打开 Firefox,在“首选项”里找到“网络设置”,然后选择“使用系统代理设置”即可。

    (更多…)
  • Ubuntu 20.04 配置 TP-WDN5200H 无线网卡

    Ubuntu 20.04 配置 TP-WDN5200H 无线网卡

    前情提要:朋友赞助了 AMD 2950x + 技嘉 x399 MEG Creation,我配上其它组件,装了台新电脑。接下来把老电脑收拾一下,装上 Ubuntu 20.04,打算补齐 x86 64 Linux 平台。

    结果卡在无线网卡配置上,Ubuntu 无法识别和使用。我的无线网卡是 TP-Link 的 WDN5200H 免驱 USB 网卡,我直接用型号搜索,很容易就找到介绍安装教程

    原来这个网卡同时集成了一块小 U 盘,里面是驱动程序,方便没有网络的人安装。但是在 Ubuntu 下,会优先把它识别成 U 盘(但是我也没找到盘符),所以无线网络不工作。解决方案就是先安装驱动,然后用 usb_modeswitch 切换工作模式,然后系统就会把它识别成无线网卡,然后就可以了。

    但在我这里,这套操作行不通,切换设备的时候,上面都一样,但最后会报错:

    Use interface number 0
     with class 255
    Error: can't use storage command in MessageContent with interface 0; interface class is 255, expected 8. Abort.

    我用上面的错误信息作为关键词搜索,只能找到各种关于 huawei modem 的讨论,解决不了问题。折腾很久,我突然注意到,我的网卡 ID 似乎和教程里不太一样,我的是 obda:c811,而教程里是 obda:1a2b(分号前是设备id,分号后是产品id),是不是这个原因呢?我以 0bda:c811 作为关键词,很快找到这个答案

    原来核心原因在于原先的驱动是基于 4.x 内核的,从 19.04 开始,Ubuntu 内核已经升级到 5.x,所以要用新驱动。所以我按照帖子里的指示,安装了新驱动。一番折腾之后,还是不行……

    眼看周末过去,没时间继续折腾了,我只有到京东下单了一款 m2 接口的 Intel AX200 无线网卡(含蓝牙)——据说 Intel 网卡都是免驱的,而且 m2 接口肯定没有集成 U 盘这种幺蛾子。

    周一,拿到新网卡,插上。果然,Intel 网卡就是免驱,工作正常;但是,我没买天线,而这个鬼网卡没有天线是绝对不能工作的(客服告诉我可以试试,不行再买天线,我……),于是我只好再下单了一套天线。然后我无意打开 Wi-Fi 一看,WTF,这是啥,Rtl8821CU?不就是我的 TP-WDN5200H 么?原来我昨天其实就弄好了,只是没有重启,没有生效……

    至此,问题解决。

    (更多…)
  • Jetpack 的流量统计好像被墙了

    Jetpack 的流量统计好像被墙了

    从5月23日开始,从 WP 后台的 Jetpack 统计看起来,我的博客访问量大跌。

    一开始我以为是 CDN 的问题,拉着同事研究了半天,没有找到证据。然后检查了 DNS 解析统计,似乎也正常。最后想起来看 GA。从 GA 的数据来看,似乎访问量并没有什么变化。那么只好猜测是 Jetpack 的统计出问题,很多访问没有统计到。

    不过我觉得多半是误伤,毕竟 Jetpack 作为 WordPress 的产品,很容易被“误伤”,而且在国内也没多少人用,不必像 GA 这样还要留点余地。可惜以后我没法很容易的看到统计数据了。

  • 使用 GitHub Registry 托管私有 NPM 源

    使用 GitHub Registry 托管私有 NPM 源

    我厂有不少私有仓库,都是日常开发中提炼出来的,在几个项目中共享,比如 UI、Vuex、网络请求(axios 封装)等。以前的主要形式是使用 npm 安装 GitHub 仓库,即

    npm i openresty/some-repo

    这样 npm 会自动去 GitHub 查找对应的仓库,然后 clone 下来完成安装。项目中的 .npmignore 文件也会正常生效,安装后的目录会忽略不需要的文件。这样做的好处就是简单,只要仓库存在,安装依赖的系统有足够的权限(比如 ssh key),就能顺利安装。在过去的三年时间里,我们一直都这样做。

    但是这样会有一些问题:

    1. package-lock.json 里记录的是 commit hash,只看这个值无法判断版本,npm 也没法使用版本号解决依赖冲突的问题。换言之,比如 A 仓库需要 C 仓库的 1 版本,B 仓库需要 C 仓库的 2 版本,那么就只能同时安装两个版本,因为 npm 无法判断两个版本是否兼容。
    2. 安装的时候要走 git clone,下载量很大,速度很慢,经常被同事吐槽。也会影响 CI 的效率。
    3. git 仓库里要提交编译后的代码,一方面浪费时间和空间,另一方面大量编译后的代码也影响 code review

    所以,考虑之后决定改用 GitHub Registry。GitHub Registry 是 GitHub 提供的私有源,感兴趣的同学可以访问这个页面了解详情。这个服务需要收费,不过我厂本来就是 Team 用户,额度比较富裕,所以并没有阻力。

    经过一段时间的摸索,终于搞成了,下面简单说一下做法。

    对依赖项目

    修改 package.json,把项目名称改成 @openresty/some-repo,即“@公司名/仓库名”。然后增加 publishConfig 字段,设置源为 GitHub registry:

    {
      "publishConfig": {
        "registry": "https://npm.pkg.github.com/"
      },
    }

    接下来,正常使用 npm publish 发布依赖即可。不过在发布之前,最好使用 .npmignore 忽略掉开发时的源文件和配置文件,一方面这些文件对于其它项目的开发没有价值,另一方面无论是存储还是下载消耗流量,都要收费,能省则省嘛。

    对业务项目

    因为这些依赖仓库都是私有项目,所以我们先得解决身份认证的问题。GitHub 提供了 Personal access tokens 方式,生成 token 后,添加到 ~/.npmrc 文件即可:

    //npm.pkg.github.com/:_authToken=<TOKEN>

    接下来,在业务项目中,添加 .npmrc 文件,指名依赖源:

    registry=https://registry.npmjs.org/
    @openresty:registry=https://npm.pkg.github.com

    这段配置分两部分:其它域的依赖,直接从 npm 的源下载;@openresty 域下的依赖,从 GitHub Registry 下载。

    最后,正常使用 npm i @openresty/some-repo 安装依赖即可。


    最后的最后附上修改前后的效果对比,可以看出,改造后效果明显:

    国内修改前real 0m39.543s
    user 0m17.768s
    sys 0m3.944s
    阿里云
    修改后real 0m16.450s
    user 0m15.204s
    sys 0m3.380s
    阿里云
    国外修改前real 0m49.350s
    user 0m22.352s
    sys 0m4.144s
    阿里云
    修改后real 0m30.807s
    user 0m15.780s
    sys 0m3.936s
    阿里云
  • 一些近况

    一些近况

    4月28日晚上,我在家跳 Just Dance,大概跳了 4 首歌,结果第二天早上起床,左脚踝肿了。我猜测是扭伤,因为前几天光脚跳舞,感觉很粘,做动作比较困难,所以28日特地穿了袜子,光滑了很多。我左脚本就有伤,怀疑旧伤复发。

    但是我没有特别在意,觉得似乎不太影响行动,有点大学时候崴了一下那种感觉。于是该遛狗遛狗,该出门出门。晚上伤势突然加重,甚至把我疼醒了。次日起床,脚踝肿得更加严重。我开始怀疑是痛风,因为我尿酸一直偏高。

    经过冰敷+云南白药,两日后渐渐消肿,不太影响行动。但是没高兴多久,肩膀又痛起来,也是夜里突发,又把我疼醒了。这次觉得惨了,多半是痛风。

    然后赶紧去医院诊治,测了尿酸,好像并不太高。但是血糖因为前阵子的疏忽,百达杨停药,我自己麻痹大意,空腹高到12.5,糖化8.7,已经明显进入发病状态。骨科大夫说,糖尿病人多半会有肩周炎,关节莫名其妙的疼痛也很常见,所以怀疑我并不是痛风,也不是扭伤,而是血糖控制不好导致多发关节炎。

    所以,没办法,赶紧控糖吧。首先请内分泌大夫调整药物剂量,我也重新定时定起来,保证按时吃药;其次百达杨性价比太低不再用,但是类似的药还是用起来,这次换上诺合力,在我身上效果明显,食量大减,我本身血糖也高,并不会觉得不舒服;再次,小区里的健身房办张卡,尽量每天都锻炼一下子。

    经过一个月努力,现在空腹能维持在 6.1 附近,偶尔能正常;餐后如果体育锻炼,能降到 7.8 以下,不锻炼8附近,算基本控制住。接下来就是坚持,顺便把体重减一减。等到放了暑假,有空去住下院,好好检查一番,希望到时候能都正常。

    哎,这身体真是一刻都不能大意啊……


    诺合力在我身上表现不错,且已入医保,需要减肥又控制不住嘴巴的同学可以去医院咨询一下专业医师。(此段文字不构成用药建议)

  • webpack 入口是 vue 文件时,无法合并 CSS

    webpack 入口是 vue 文件时,无法合并 CSS

    在多页网站中合并 CSS 是很常见的优化手法。一般来说,CSS 体积不会太大,使用同一份 CSS,改进用户点击链接后的加载速度,大部分收益都大于多加载几 K CSS 带来的损耗。

    对于 UI 库来说也是如此,用统一的样式库,减少 import 时的心智负担,也是性价比很高的做法。

    最开始我在 UI 库的入口文件里 export 所有组件,然后在其它仓库里用 import {component} from 'my-components' 使用组件。后来通过分析得知,这样做无法 tree-shaking,而且会导致组件库的重复引用,即 A import B,B import C,那么无论 A 里有没有用到 C(比如用到 B 的一个小功能 b1,它不依赖 C),都会把 C 的代码打包进去。

    通过研读 Webpack 的 tree-shaking 文档,我得知也没有什么好办法可以规避这个问题,毕竟 JS 很灵活,你也不知道哪个开发者会搞个 eval('const myRequire = require'),如果要识别解析分辨所有情况太复杂,所以选择最保守的策略:认不出来具体功能的代码都给你带上。(早年我写 NerveNet 的时候,就是想不通这里怎么搞,最后坑掉了。早知道大家都选择绕开,说不定我的 NerveNet 也能如愿写出来了……)

    总之,目前 lodash 的做法比较常见且能解决问题,即增加多入口,为每个可能用到的函数都打包独立的函数。这样需要引用那个就引用哪个,不用担心把整个 lodash 都打包进去。

    于是我就立项开始重构我厂的几个前端库。然后很快就卡在 UI 库上面:无法生成合并过的 CSS 文件。Google 许久没有结果,吃饭前我灵机一动:vue-loader 必须搭配 VueLoaderPlugin 才能正确打包,会不会这个过程有 bug,导致如果我的入口都是 Vue 单文件组件,就会没法正确合并 CSS 文件。

    然后我就测试了一下,代码大约如下:

    // a.js
    import './a.styl'
    
    // b.js
    import './b.styl'

    可以生成合并过的 CSS 文件。与之相较,这样的 Vue 单文件组件就不行:

    // a.vue
    <style lang="stylus">
    body
      font-size 16px
    </style>
    
    // b.vue
    <style lang="stylus">
    body
      color red
    </style>

    但是,同样是 vue 单文件组件,样式使用 import 的方式导入,就没问题:

    // a.vue
    <script>
    import './a.styl';
    </script>
    
    // b.vue
    <script>
    import './b.styl';
    </script>

    现在可以确定是 vue-loader 或者 VueLoaderPlugin 有问题。不过最近身体欠佳,每天要花很多时间锻炼,另外还欠下不少坑要填,所以暂时没空去翻 issue 或者提 issue。哪位同学看见了,愿意帮忙的,可以搞一下,也算参与 开源社区建设了,功德无量。

  • Font Awesome 发布 Duotone 字体,支持双颜色

    Font Awesome 发布 Duotone 字体,支持双颜色

    无意中看到 Font Awesome 发布了 Duotone 双色字体,感觉很神奇,我还不知道 WebFont 竟然支持多种颜色,于是赶紧看了看。

    首先,这是旧闻,实际上,去年,也就是2019年7月30日,Font Awesome 就发布了 Duotone。

    关于 Duotone 的介绍,大家可以看这篇官方博客:Introducing Duotone。借张图直观地展现 Duotone 的效果:

    然后我就很好奇它们是怎么实现的,据我所知 WebFont 不支持多颜色。研究了半天,发现原来是这样:

    2019年5月30日,Font Awesome 发布了 Font Awesome Kits(工具包)。Kits 是一个 JS,用来取代之前直接使用 CSS 引用字体的方式。这样做有几个好处:

    1. 根据字体使用情况按需加载
    2. 可以在客户端管理缓存,避免重复下载图标
    3. 可以自动更新图标,跟 Font Awesome 发布同步
    4. 可以帮助开发者处理可用性问题(关于这一点,GitHub 曾经发布过一篇博客,解释他们为什么要从 Icon Font 切换回 图标:https://github.blog/2016-02-22-delivering-octicons-with-svg/
    5. 可以更快应用新技术,比如 HTTP2,SRI 等

    上面几个好处都是 Font Awesome 官博《Introducing Font Awesome Kits》中列出来的,还有一个好处它们没说:可以修改 DOM。Duofont 正是藉此实现双色的。打开开发者工具,我们可以看到,所有图标 <i class="fad fa-*"></i> 都被替换成了 inline <svg>,包含两个图层,自然可以通过 CSS 控制颜色等样式。

    这个思路很有意思,布局也一步一步规划的很好,虽然不知道最终效果如何,但还是学到不少东西。

    Font Awesome 提供免费版,我一直在用。付费版一年 $99,我觉得还是贵了点,所以一直没用,有需求的同学应该试一下。