Recent Posts

h404bi's avatar

总结下博客最近的调整

Old Days

我建博客始于 2013 年,时间也不长。那会儿也不过是一个从 WordPress 加免费空间入坑的新手,免费空间关了就买了个域名和虚拟空间继续折腾。啊对,也改成了 Typecho 一段时间,仿过几个主题。之后便是在流行之下,一个 commit 换成了静态博客 Hexo。于是开始在这个“自留地/实验室”里摆弄各种新玩意,做做小试验。没写过几篇文章,却也一直延续至今。

Changes

A. 核心系统

将使用了近 4 年的 Hexo 换下是博客最近最大的改变,换上的是基于 Vue、Webpack 等当前主流技术的 Saber 静态博客系统。

以 React、Vue、Webpack 等当代主流前端技术为基础的静态网站生成器系统持续出现并开始崭露头角,Gatsby、Nuxt、VuePress[1],势必会抢占 Jekyll、Hexo 等以字符串模版为主的“更加静态[2]”的旧式静态博客系统,我相信这也是这个社群中的趋势。

在最初规划迭代的时候,预期是更换至 Gatsby 这个基于 React 技术栈的系统,其中的原因是受到 Daniel Eden(知名 CSS 动画框架 animate.css[3] 的作者)的博客改版影响。他在稍早的一段时间将他的博客 —— daneden.me 从 Jekyll 换成了 Gatsby。我的博客受其影响很大,即使到目前为止,在我博客中你仍然能够找到一些来源于他的博客的设计元素。最明显的是在文章图文排版上的借鉴,在大屏幕下,你可以在如《推特背后的 Notch 之道》等文章中看到左右溢出的插图。这个我非常喜欢的排版设计,便源于:「Design Elitism」,我博客的整个排版系统很大程度上受他影响,只是彼此经过多次迭代,已不太能找出相似点了。

Gatsby

没有选择 Gatsby 是因为在我对 React 生态的还不了解,头疼一连串硬啃 React、GraphQL 等技术的时候,VuePress 出世了,我还是更倾向于相对比较熟悉的 Vue。

VuePress

然而,在我尝试 VuePress 后,其更加面向于项目文档的设计,让我感觉从 Hexo 迁移显得力不从心。对比 Gatsby 这或许是因为还是刚起步阶段,生态还不完善吧,截至目前其博客方面的支持还在陆续开发中[4]

于是我便在等待/寻找一款能让我更加平滑地进行迁移的系统。然后 Peco 出现了,并在后来被现在的 Saber 所替代。我不想在此大谈如何迁移至 Saber 的,真要这样或许会另起一篇文章写这个。只想说,非常感谢 EGOIST 的开源工作,让大家能够用上前沿的技术。

B. 主题外观

得益于 Saber 的系统设计,将我的原有 Hexo 自用主题迁移至新系统并没有感觉到费力。迁移后整体上我还是使用此前的主题,只是在原有的基础上完成了一些更加细致的迭代,使其更符合我的现存观感。除了调整了列表的布局变得紧凑些、完善响应式文字排版设计外,最大的一点是从以前一直使用的 CSS 预处理器 Stylus 切换成了 SASS,并用上了原版 Bulma 框架。在生态上,果然还是 SASS 更胜一筹。

Bulma.io

期间学会了几个以前不了解、不常用的 CSS 属性,并应用到了主题中。

  • text-align: justify; —— 文字两端对齐,在单栏布局中排版差异尤为明显[5]
  • font-display: swap; —— 修改 Web 字体加载显示逻辑,可避免字体下载过程中闪白[6]

不过整个主题目前还是有缺陷,只能后续随着时间推移再慢慢优化。

C. 部署架构

在我刚开始使用 Hexo 或者说刚入坑静态博客系统的时候,我就已经在使用持续集成工具来帮助我进行构建和部署工作,一直在使用 Travis CI 的社区版。静态博客系统通过使用持续集成做自动构建部署,真的能省下不少重复劳动。

旧部署架构

旧架构如此的原因是以前部署到 GitHub Pages 上觉得速度不行,同时又不支持自定义域名使用 HTTPS,我也有一台闲置的香港 VPS,于是就通过 Webhook 触发 VPS 同步 GitHub Pages 的内容,然后在 VPS 上使用 Nginx 提供服务,这样能解决前述的两个问题。后来因为域名的 SSL 证书过期(那时还没用 Let's Encrypt)和 VPS 不稳定的原因,就加了层 CloudFlare。然后就没管了,一直这样。

新部署架构

调整后实际上就是将提供服务的后端从 VPS 迁移到了 Netlify。其一是图方便,Netlify 自动申请 Let's Encrypt 不用自己麻烦在 VPS 上设置,其二是 Netlify 自带 CDN,速度还不错,最后是因为我需要调整整个博客各页面的固定链接,同时希望旧有的链接能重定向到新的固定链接上,保留可用性。而刚好 Netlify 原生支持重定向服务 —— Netlify Redirect,这样就不用因为 CloudFlare 免费版只有 3 个 Page Rules 而显得拘谨。

构建文件依然推送到 GitHub Pages 分支上后再同步到 Netlify 的原因是,我希望保留能够在 GitHub 仓库中查看构建后的文件的功能,构建后直接推送到 Netlify 上我就看不到构建文件和历史变更了。

Wappalyzer 检查

故意加了个假的 Hexo Generator 的 Meta 标签,所以被检测出用 Hexo(大雾)。关于这个扩展程序,可以看我之前写的文章《我都在用些什么 Chrome 扩展程序》里有介绍。

D. 其它变化

整个核心架构变化,于是现在托管仓库的项目架构也有所调整,改成了 Monorepo 并用 Lerna 进行管理[7]

修改了内容授权协议,具体可见 About 页面。因为细想了一下,真有人取走内容的话大概也不会在意你的协议,于是干脆放飞自我。

RSS Feed 调整,增加 JSON Feed 的支持,路径 /feed/index.json,同时原有的 Atom Feed 的路径会从 /blog/atom.xml 调整为 /feed/atom.xml,原有路径会重定向至新路径。因为这个是一个 Breaking Change,于是我着重了一下。希望有订阅我博客的朋友看到这篇文章后能知道这个变化。

完整的迁移记录可见仓库 Commit Log


  1. https://www.staticgen.com/ ↩︎

  2. https://vuepress.vuejs.org/zh/guide/#hexo ↩︎

  3. https://daneden.github.io/animate.css/ ↩︎

  4. https://github.com/vuejs/vuepress/issues/36 ↩︎

  5. https://developer.mozilla.org/zh-CN/docs/Web/CSS/text-align#Justify ↩︎

  6. https://developer.mozilla.org/zh-CN/docs/Web/CSS/@font-face/font-display ↩︎

  7. https://github.com/h404bi/www.h404bi.com/tree/592c99120e8452a816d51fbec6fb7eabf3f15448 ↩︎

's avatar

upld 修改版

基于 lfiore/upld 修改而来,目前项目托管于 GitHub: JixunMoe/upld


主要修改:

  • 多图片(支持拖拽)上传
  • 多 url 批量上传
  • 允许禁止用户注册。
  • 举报并不会实际发送出来,因为懒得改发邮件的代码

改过的部分很挫,主要是自己用。 所以基本上都是在原版的基础上缝缝补补来实现我要的那堆功能, 也因为个人化太多了,所以就没提交到上游了。

欢迎代码审计。


测试图片,由 CloudFlare 提供云加速,图片为 Chris LawtonUnsplash 上传的照片:

依云's avatar

T470p 使用N卡运行 Xorg

本文来自依云's Blog,转载请注明。

AlisterTT's avatar

春天好

Processed with VSCO with c2 preset
h404bi's avatar

推特背后的 Notch 之道

自 Notch 出售了 Minecraft,出售了 Mojang 公司后,他在 Minecraft 方面的消息也随着 Minecraft 逐年下降的热度而减少。因此也有人跟我说,微软收购 Minecraft 的那一刻是 Minecraft 的巅峰,Notch 退出得很及时。卖掉 Minecraft 之后的 Notch 经历了怎样的一段过渡期;为何在《Minecraft: The Story of Mojang》纪录片[1]中还是在 Minecon 与粉丝见面时给人的感觉都是平易近人的他,在推特上却常常出言惊人;Notch 是否还有在做些什么游戏;以及他平时有喜欢玩什么游戏。也许你也会与我一样有一些这样的疑惑。
IceHoney Blog's avatar

前端中的e2e测试

对于单页面应用,我们需要由前端来控制每个页面的路由。但是在开发过程中,我们经常要对路由进行调整。每次调整都要手动检查所有页面是否正常显示。这个过程实在是太浪费生命了, 所以我们需要选择一个测试框架来自动完成这个过程,结合CI系统,在每次PR的时候都自动测试一遍,只有通过测试才会进行下一步的review。

Nightwatch

Nightwatch是基于W3C WebDriver API。WebDrive主要是为了满足浏览器的自动化测试需求,把最终的接口统一成HTTP协议。 所以可以统一不同浏览器的自动化测试接口。我们只要安装每个浏览器的WebDriver实现,就可以同一套代码在不同的浏览器中进行测试。老版本的NightWatch需要使用Selenium来管理各个浏览器,但是从1.0版本开始便不需要也不推荐。所以我现在的项目中并没有安装Selenium。

依赖

由于不需要安装Selenium,所以并不需要安装Java依赖。我使用Chrome浏览器来进行自动化测试,所以需要测试环境安装Chrome,注意安装的必须是Chrome,Chromium不可以。 在Travis CI中可以很方便的添加Chrome。还需要安装ChromeDriver依赖来驱动Chrome完成自动化测试。

配置

在Linux测试环境下,基本上都是没有图形化界面的,所以我们在配置Chrome的启动参数中需要加入--headless选项,这样就可以不启动UI。当我们以root权限启动的时候还需要添加--no-sandbox选项,这两个选项基本上是必须的。在我的实际情况下,需要测试不同UA下的展示效果,所以还需要添加--user-agent=Mozilla/5.0 (Macintosh; Test自定义的UA。 下面给出一个配置的例子供大家参考:

// http://nightwatchjs.org/gettingstarted#settings-file

module.exports = {
  output_folder: "tests/e2e/reports",
  custom_assertions_path: ["tests/e2e/custom-assertions"],
  globals_path: "globalsModule.js",
  src_folders: ["tests/e2e/specs/web"]

  webdriver: {
    start_process: true,
    server_path: require("chromedriver").path,
    cli_args: ["--verbose"],
    port: 9515
  },

  test_settings: {
    default: {
      desiredCapabilities: {
        browserName: "chrome",
        javascriptEnabled: true,
        chromeOptions: {
          args: ["--headless", "--no-sandbox"]
        },
        acceptSslCerts: true
      }
    }
  }
};

每个参数的详细含义可以参考官方的说明文档。

总结

在集成Nightwatch的时候,我是卡在了安装浏览器上。在Mac系统上可以正常执行,在CentOS的docker里面却不行。找了半天发现是自己用了Chromium,之前对Chromium能代替Chrome深信不疑。。。 在遇到问题的时候,还是多怀疑,多找找可能性比较好。

Felix Yan's avatar

nspawn.org:简单的 systemd 发行版容器

如果你想要运行一个发行版容器,而又不想被 docker 一类的重量级方案打扰,现在有一个新的简单方案了。

nspawn.org 目前提供了 Arch、CentOS、Debian、Fedora、Ubuntu 的各版本镜像,并可以直接用 systemd-nspawn 的验证机制进行签名验证。

推荐的用法是使用其提供的 “nspawn” 工具。下面以创建一个 Fedora 30 容器为例:

1、获取工具:

$ wget https://raw.githubusercontent.com/nspawn/nspawn/master/nspawn
$ chmod +x nspawn

2、获取 Fedora 30 镜像:

$ sudo ./nspawn init fedora/30/tar

3、启动容器并获取 shell:

$ sudo machinectl start fedora-30-tar
$ sudo machinectl shell fedora-30-tar
Connected to machine fedora-30-tar. Press ^] three times within 1s to exit session.
[root@fedora30 ~]#

一些背景:容器默认的存储路径在 /var/lib/machines/。nspawn.org 的创建者是 shibumi,目前是 Arch Linux Trusted User。所有的镜像使用 mkosi 制作,定义文件均在 GitHub 上。除了 nspawn 容器镜像,这个站点还提供可引导的 GPT-UEFI 镜像。

依云's avatar

系统在解析哪些域名呢?

本文来自依云's Blog,转载请注明。

最近用 Rust 写了个叫 capture-dns 的小程序,实时显示 DNS 查询结果的。配合 ipmarkup 的效果是这样的:

>>> sudo capture-dns lo | ipmarkup
[sudo] lilydjwg 的密码:
github.com -> 52.74.223.119(新加坡Amazon数据中心)
github.com -> 13.229.188.59(新加坡Amazon数据中心)
github.com -> 13.250.177.223(新加坡Amazon数据中心)
live.github.com -> 192.30.253.125(美国弗吉尼亚州阿什本GitHub)
live.github.com -> 192.30.253.124(美国弗吉尼亚州阿什本GitHub)
collector.githubapp.com -> 34.193.248.191(美国弗吉尼亚州阿什本Amazon数据中心)
collector.githubapp.com -> 52.20.29.9(美国弗吉尼亚州阿什本Amazon数据中心)
collector.githubapp.com -> 34.197.57.23(美国弗吉尼亚州阿什本Amazon数据中心)
api.github.com -> 13.250.94.254(美国Amazon数据中心)
api.github.com -> 13.250.168.23(美国Amazon数据中心)
api.github.com -> 54.169.195.247(新加坡Amazon数据中心)
ocsp.digicert.com -> 117.18.237.29(澳大利亚美国MCI通信服务有限公司(韦里孙商业Verizon Business)EdgeCast亚太网络CDN节点)

可以看到本地的软件们都在查询哪些域名,得到的 IP 又是什么。抓取的是应答,所以没得到 IP 结果的不会显示。我抓取的是 lo 网络接口,因为我本地有用 dnsmasq 做缓存。

其实这个程序一开始不是这样子的。群里有人想抓取系统上进行的 DNS 查询的域名。一开始是用 tshark 抓取的,然而它太占用内存了。我粗略看了一下 Python 的 scapy 工具,也用掉了大几十M内存。那么,用 Rust 写一个好了,也顺便练习一下 Rust。

这个程序运行时只有几M的内存占用,CPU 占用也是非常低的。不过它并没有做完全的协议分析,而是假设抓得的包是以太网帧封装的 IPv4 报文封装的 UDP 数据包里包着 DNS 应答报文。所以如果你是在 eth0 上跑 PPPoE 的话,抓 eth0 上的包就不行了,得抓 ppp0 这种了。当然你要是 IPv6 啊 DoH、DoT 啥的就更抓不到了。

后来我用 bcc 的 tcpretrans 脚本查看我这里到哪些地方的 TCP 连接不太通畅,然而经常会看到一些我猜不到是干嘛的 IP。所以就把这个程序改了一下,把域名对应的解析结果显示出来了。

Rust 不仅节省资源,而且开发的体验真的很棒呢,编译成功之后就能按我预期的运行了。也不用担心什么时候遇到个有问题的报文导致程序崩掉,因为写的时候就已经处理好了出错的情况。不像 Python 写的脚本,刚写好,一跑就抛个异常出来,提示我哪里不小心写错了。好不容易调试好了,跑着跑着,遇到意外情况就挂掉了……

依云's avatar

正确的隐藏挂载点的方法

本文来自依云's Blog,转载请注明。

脚本需要挂载文件系统,但是不希望外部看到。正确的做法是:

mount --make-rprivate /

然后该干嘛干嘛。当然如果你不知道在执行之前先调用 unshare 或者等价的系统调用,说明这篇文章不适合你阅读。

错误的做法是在挂载的时候加 --make-private 或者把 / --make-private。这个标志(MS_PRIVATE)的意思是挂载/卸载事件在这里停止传播,而不是这个挂载点的事件是否传播出去。至于为什么需要使用 --make-rprivate(增加了 MS_REC 标志),暂时我还不理解。

这个用法是从 unshare 工具的 strace 结果里挖掘出来的。因为我的目的跟 unshare -m 一样嘛,当然首先想到的是看看它是怎么干的了。你问我为什么不用 unshare -m?你自己写脚本的时候试试看啰?

依云's avatar

迁移系统到 SSD

本文来自依云's Blog,转载请注明。

最近一段时间,不知道是磁盘、缓存相关算法的更新,还是我开的服务太多,又或者是新软件占用内存太高,我的系统越来越卡了,尤其是更新系统的时候(备份系统时也特别卡,然后我用限制内存占用的办法解决了)。我当然知道最主要的原因是因为机械硬盘的处理能力就那么多,于是经过一些了解和计划之后,还是决定换 SSD 了。

刚才查看了一下历史数据。从去年七八月份起,平均内存使用量从2G多升高到了3G多。大概是火狐更占内存了吧。我都尽量减少内容进程数量了……也可能是 PHP / MediaWiki 的锅,因为使用 SQLite 存储时,经常发生错误也是这段时间的事情。不过也可以理解为由于磁盘负载重导致的。算了不管了。

准备工作

当然首先要去买块 SSD 啦。我买的是 LITEON T11 Plus 512,512GB,800块。实际操作系统得到的空间是 477GiB,因为硬盘产业还在沿用1000进制的单位词头。它比我预期的要小不少呢,不过拿在手里感觉比一般同样大小的电路板要重。

拆开我的 T470p,把空闲接口旁边的螺丝下下来,然后 SSD 标签朝外插进去。我也不清楚这个接口叫什么。插进去之后它是翘起来的,难怪要用螺丝固定。然后用下下来的螺丝固定好,再把机器装好,就好了。启动系统,可以看到 /dev/nvme0n1 设备在了~GNOME 磁盘软件不能读取到 SMART 信息,用 smartctl -a /dev/nvme0n1 命令就好了。

设备没问题了,接下来当然是备份系统啦。

开始迁移

备份妥当之后,我就开始格式化 SSD。计划是 EFI 分区 512M,400G 给我的 Arch Linux,然后剩下 76G 左右的空间预留给我的 Win10。

然后这 400G,首先上一层 LUKS 加密,然后格式化为 btrfs 文件系统。其实我想要 btrfs 很久了,快照、去重、压缩都挺棒的。但是听说它的性能比较差,而我已经在受磁盘 I/O 能力不足的苦了,所以到现在有了 SSD,是时候换 btrfs 了!

其实之前 zfs(zfsonlinux)也是候选项,并且已经在工作本上使用过了。然而最近我的 zfs 备份两度出现问题(磁盘掉线之后 zfs 元数据损坏,导致一整个 zfs 文件系统一写就卡住;近期莫名其妙 rsync 跑着跑着就卡在那里不动了,磁盘也没有什么活动),再加上之前遇到的各种大小问题(ARC 被算进内存使用量中;挂载期间一旦磁盘离线就卡死;克隆出来的文件系统无法摆脱原文件系统;不支持 overlayfs;因为是树外模块所以需要专门准备的支持 zfs 的系统来执行安装),以及 TRIM 支持刚刚才加入,我已经停用 zfs 并将其排除考虑范围了。

然后就是规划子卷。参考了 openSUSE 的方案,最终决定分为这么几个子卷:/, /var/cache, /var/tmp, /var/log, /var/lib/lxc/lxc-debian/rootfs, /var/lib/lxc/lxc-centos6/rootfs, /home/lilydjwg, /home/lilydjwg/.cache。主要考虑的是快照。另外我给 /var/log/journal 和 /var/lib/postgres chattr +C 禁用了 CoW。这样也会禁用压缩,不过本来它们基本上就没什么可压缩的。需要排除的有:我的公开第三方源码和各类大文件用的 /ldata 还是放在机械硬盘上、/var/cache/pacman/pkg 缓存不要、/var/lib/pacman.fs 不用单独放连续的文件里了、/home/lilydjwg/.cache 缓存不要、/home/lilydjwg/.debug 这个 perf top 用的目录会有 libc 的硬链接,rsync 时会失败所以就不要了。

最终的同步命令如下:

sudo systemd-run -p MemoryMax=64M --scope \
  rsync -aviHAXKhPS --inplace --delete --exclude='*~' --one-file-system \
  / /mnt/root --exclude=/var/cache/pacman/pkg --exclude=/home/lilydjwg/.cache \
  --exclude=/var/lib/pacman.fs --exclude=/ldata --exclude=/home/lilydjwg/.debug

同步好之后,重启进入 live 系统再同步一次以保证最新数据也同步好了。然后把部分被排除的目录再同步一下:~/.cache/winetricks 这个以后不一定能够下到、~/.cache/sxiv 都是有效缓存(我有清理)而且生成耗 CPU、/var/lib/pacman 这个是被 --one-file-system 排除掉的。

然后是在 /etc/default/grub 里更新内核命令行 cryptdevice=/dev/disk/by-partlabel/ssd:ssd:allow-discards。这个 allow-discards 会轻微地降低安全性,不过在中国没什么用的。更新 /etc/fstab。

然后还有 /boot 要处理。其实就是把内核和 initrd 复制过去,然后重新安装 grub、生成 grub 配置。位于机械硬盘上的旧文件之后再删掉即可。

重启,使用 fallback 版 initrd 进入系统,开始修复各种问题。

首先是更新默认的 initrd。不过在更新它之前,我要修改一下我自己的 hook。之前这个 hook 里只有 partprobe 我解密之后的机械硬盘分区,因为我在它上边又分了 xfs 和 swap 两个区。现在因为 encrypt hook 解密的是 SSD 上的分区,所以这个机械硬盘上的加密分区的解密也要自己做。其实也很简单,给这个加密分区添加一下文件密钥,然后

cryptsetup open --type=luks --key-file=/etc/keys/hdd.luks /dev/disk/by-partlabel/main main

就可以了。不需要输入两次密码。

/ldata 使用 automount 延迟挂载,所以需要写 ldata.mount 和 ldata.automount 两个文件,然后 enable ldata.automount 那个。不知道写在 /etc/fstab 里是不是也行。然后把机械硬盘里的目录结构调整一下,把原来 /ldata 下的东西上移一级,旧的 / 里的其它东西都放到隐藏的 .oldroot 里去好了。

swap 本来我是保留着的,不过发现这样子我会时不时听到机械硬盘启动了。而且因为机械硬盘启动比较费时,所以系统会卡好一会儿(大概有一两秒)……所以我默认就不开 swap 了,但是 resume hook 还是保留,需要的时候打开 swap 就可以休眠了。这个 resume hook 也是我需要在启动的时候就解密机械硬盘上的加密分区的原因。

加了一个每周运行的 fstrim -v / cron 任务。没有使用 fstrim.timer 是因为它会 trim 所有设备。而我可不希望它去 trim 我挂载的机械硬盘上的 loop 设备,会造成大量碎片的。

还有一些小问题要处理。chattr +i /etc/resolv.conf 以避免 DNS 服务器被不知不觉修改了。我有用 dnsmasq 的所以这个文件不用动。我有一个 MediaWiki 实例的文件是使用 overlayfs 的,它现在挂载提示「failed to verify upper root origin」。后来才发现相关目录上有同步到几个 trusted. 开头的、overlayfs 使用的扩展属性。是它还挂载的时候被同步到的,不知道为什么最后一次同步时没有被清除掉。手动使用 setxattr 删除掉就好了。

rsync 还出了另外几个莫名其妙的问题。我在 /usr/local/sbin 下有个最近新加的文件的执行权限消失了,造成使用它的 systemd 服务失败。另外有个最近被删除的配置文件竟然还在。我不是有指定 --delete 选项吗?火狐缓存的网站图标也都没有了,需要访问之后才会重新出现。~/.cache 下有很多 root 所有的空目录,也许是我哪次忘记 --exclude 它然后又中断才加上?

Wine 有几个文件有几十 KiB 大的 user.wine.sd 扩展属性。太大了以至于 btrfs 里放不下,报「No space left on device」错误。我刚看到时还吓一跳,以为是我的 SSD 满了,仔细一看才发现只是扩展属性写不下而已。

我于是又带 --dry-run 参数同步了一次,确定再没有什么需要的东西被落下。这次 rsync 出现这些问题很是奇怪,不过我没有留日志,加上操作的时候其实是有不少修修改改的,所以就不深究了吧。

修好所有发现的问题,再次重启之后,systemctl status 和 systemctl --user status 没有失败项了~撒花 O(∩_∩)O~

后记

现在我的系统超快的!比如启动时间:

>>> systemd-analyze
Startup finished in 9.257s (firmware) + 1.466s (loader) + 15.110s (kernel) + 6.945s (userspace) = 32.780s 
graphical.target reached after 6.945s in userspace

firmware 和 loader 咱管不了。kernel 那儿包含了我输入密码解密,以及解密和探索机械硬盘上的分区,所以花了些时间。userspace 那里你别看花了好几秒,其实大部分时间都是花在联网上了。不依赖网络的服务在差不多一秒的时间内就全部启动好了。

之后我还要更新备份脚本,因为我用了 --one-file-system 而现在它们在不同的子卷上。再写一下每日快照的脚本,就不用一不小心删错文件啥的都要去备份里找了。

关于写入量,smartctl -a /dev/nvme0n1; sleep 300; smartctl -a /dev/nvme0n1 统计了一下,因为我开了 collectd 收集一些系统数据,每分钟大概会写入 60MiB 的数据。算下来,一年要写 20T 左右。这块 SSD 标称的是 280TBW,也就是可以写 280TB 的数据。这么算起来能用十年,所以就这样吧,不用再优化了。顺便说一下,SMART 信息里的「Data Units Written」数据,乘以 512000 之后是字节数。

就这样啦。最后还要说一句:SSD 超快的!

17windy's avatar

[七日杀原创MOD] 17windy的卡通幻想风格武器包 Ver1.2 0416

emmmm 最近七日杀服务器比较荒凉 为了避免美羽姐姐的服务器空转 研究了下七日杀的MOD开发 所以有了这个武器包 嗯嗯…

应该会适合比较喜欢这类卡通风格道具的玩家们:) 毕竟废土太阴暗啦!

内含5把双手剑 3把双手斧 6把单手武器 4枚投掷玩具

武器参数和性能经过了平衡 各有所长 例如某把武器割肉相当厉害的!

只能通过搜刮获得(因为毕竟属性还是比原版的要强力)这又到了看脸的时候了……

更新日志

Ver 1.05 武器特效
为几把武器增加了特效
部分武器的细微平衡

Ver 1.1 新武器和特性
增加了三把新武器和两把挖矿镐
部分武器性能平衡
部分武器增加了特殊的隐藏效果

Ver 1.2 新的地刺方块和远程武器
增加了四种地刺方块
增加了三把远程武器
部分武器性能平衡

下载地址:

N网 https://www.nexusmods.com/7daystodie/mods/301/

Git https://github.com/17windy/17windy-s-cartoon-fantasy-weapon-pack

希望大家用的开心!

后续有时间会继续更新的!

RecursiveG's avatar

Haskell 简易指南

Haskell 简易指南
HY's avatar

Horror game

最近玩了生化2重制版,有点感想就随便写点东西_(:3」∠)_ 生化2全程给我的精神压力都不大,大多被吓到的场景 […]
h404bi's avatar

彻底搞懂 Windows 控制台的设置

Windows Console Host(即 conhost.exe,下称“ConHost”[1])中的设置可能有点难以理解,主要是因为在过去几十年中这个设置系统不断发展。根据 ConHost 如何被调用,这些设置项会存储在不同的位置。

控制台设置

设置加载的层级

决定一个控制台设置的加载与存储是基于以下层级进行的:

  1. 写死在 conhostv2.dll 里面的设置
  2. 用户定义的控制台默认设置,存储在注册表 HKCU\Console
  3. 每个控制台应用程序[2]单独的设置,存储在注册表 HKCU\Console\<sub-key> 中,其中 sub-key 使用以下两种值中的一种:
    • 控制台应用程序的文件路径(其中的 \ 会替换成 _
    • 控制台应用程序的标题
  4. Windows 快捷方式(.lnk)中的设置
注册表中的控制台设置键值

当一个控制台应用程序被启动后,ConHost 会依据加载情况决定使用哪些设置,同时会按照前述的层级先后对一些进行覆盖。每一个设置项将取其最后加载的值,也就是说在第 4 级(Windows 快捷方式)中的值会覆盖掉第 2 级(用户定义的默认设置)中的值。

这样一个层级设计解释了为什么在每个控制台实例窗口的标题菜单中,都会有一个“默认值” 选项以及一个“属性”选项。

控制台窗口标题菜单

修改“默认值”时,改动会存储到注册表 HKCU\Console 中,写入用户定义默认设置(即前述层级中的第 2 级)。

修改“属性”时,改动会存储到注册表中的控制台应用程序单独设置或者 Windows 快捷方式中:

  • 如果这个控制台应用程序是被直接(比如是从 Win+R,Windows 运行对话中)启动的,则改动会存储到前述的控制台应用程序单独存储位置(层级中的第 3 级)中。
  • 如果这个控制台应用程序是通过 Windows 快捷方式被启动的,则改动会直接存储到这个快捷方式 .lnk 文件中(层级中的第 4 级)。你可以右键这个控制台应用程序的快捷方式,选择“属性”查看其设置。
快捷方式中的设置

当一个控制台应用程序被启动后,ConHost 会根据前述的层级,从第 1 级写死的默认设置开始覆盖设置,最后确定使用哪些设置。这意味着在 Windows 快捷方式中的设置会覆盖掉注册表中的控制台应用程序单独设置以及默认设置。

值得注意的是在注册表中的设置是“稀疏”的,意味着如果某个设置项为空,则不会修改正在使用的值。这允许用户在所有控制台应用程序之间共享部分设置项的同时指定其它一些特定设置项。

而快捷方式文件则会将每个设置项都存储其中,不管是否有默认设置。这些设置会以不透明的数据块存储在快捷方式中。

下面是 Windows 控制台的设置列表,包含了简短的描述以介绍其作用。

设置项名字 类型 描述
FontSize Coordinate (REG_DWORD) 字体像素大小
FontFamily REG_DWORD GDI 字体族
ScreenBufferSize Coordinate (REG_DWORD) 屏幕缓冲区大小,宽x高个字符
CursorSize REG_DWORD 光标大小
WindowSize Coordinate (REG_DWORD) 窗口大小,宽x高个字符
WindowPosition Coordinate (REG_DWORD) 窗口位置,宽x高个像素(如果没有设置则进行自动定位)
WindowAlpha REG_DWORD 窗口透明度(取值范围:0x4D-0xFF)
ScreenColors REG_DWORD 前景色与背景色
PopupColors REG_DWORD 显示弹窗(CMD.exe 按 F2)时的前景色与背景色
QuickEdit REG_DWORD 快速编辑模式是否开启
FaceName REG_SZ 字体名字 (默认使用 __DefaultTTFont__,根据你的代码页 CodePage 选择最合适的字体)
FontWeight REG_DWORD GDI 字重
InsertMode REG_DWORD 插入模式是否开启
HistoryBufferSize REG_DWORD 命令记录缓冲区大小
NumberOfHistoryBuffers REG_DWORD 命令记录缓冲区数量
HistoryNoDup REG_DWORD 是否丢弃旧的副本
ColorTable%% REG_DWORD 16 色的调色盘中每个颜色的 RGB 值
ExtendedEditKey REG_DWORD 是否启用扩展的文本选择键
WordDelimiters REG_SZ 分词符列表(例:' .-/\=|,()[]{}'
TrimLeadingZeros REG_DWORD 选取复制文字时是否删除首部零宽字符(使用 00000001 表示 1
EnableColorSelection REG_DWORD 选择时是否同时复制颜色
ScrollScale REG_DWORD 使用滚轮滚动时一次滚动多少行
CodePage REG_DWORD 代码页 CodePage
ForceV2 REG_DWORD 是否使用新版控制台
LineSelection* REG_DWORD 是否启用对选定内容自动换行
FilterOnPaste* REG_DWORD 是否在粘贴时筛选剪贴板内容(如:将弯引号替换为直引号)
LineWrap REG_DWORD 是否在调整窗口大小时对输出的文本换行
CtrlKeyShortcutsDisabled REG_DWORD 是否启用 Ctrl 键快捷方式
AllowAltF4Close REG_DWORD 是否禁用 Alt-F4 热键
VirtualTerminalLevel REG_DWORD 控制台 VT 支持级别

*仅在新版控制台中有效

已知问题

与大多数复杂的事物一样,有一些问题需要注意:

系统更新会导致设置被重置

每当你升级到新版本的 Windows 时,系统级的快捷方式以及“「开始」菜单”中的设置会被重置为默认值。这意味着如果你升级了系统,你自定义的字体、颜色等设置将会全部重置为 Windows 的默认值。

后记

我一直在使用 concfg 作为我管理我的 Windows 控制台设置的工具,近期成为了该项目的协作者进行项目维护,便开始稍微深入地了解 Windows 控制台相关知识。本文是微软官方 Windows Console & WSL 团队的一篇博文的译文,原文见 Understanding Windows Console Host Settings,有些许删改。


  1. 在 Wikipedia 上也称 Win32 控制台 ↩︎

  2. 注意“控制台”与“控制台应用程序”的区别,前者指 ConHost 宿主程序,后者是运行在 ConHost 下的应用,如 cmd.exe/powershell.exe ↩︎

Roy Binux's avatar

Zerotier Nat 网关出口 和 iptables 调试

每当看到各类教程中的 iptables 指令,在格式参数组合之下可以实现从防火墙,封禁 IP 端口到 NAT 的各种操作,就如同魔法一般,看不明白,却又感到无比强大。想学,但又好像不得要领,稍微不慎可能就再也连不上了。最近配置 Zerotier 的 Nat 网关的时候,看着

Roy Binux's avatar

少女前线拖尸脚本 和 生成它的可视化工具

最近在玩少女前线,这是一个手机游戏,over。不是,就真的没有什么好讲的嘛,了解的人早有耳闻,不了解的就只要知道这是个手机游戏就好了,嗯。

然后,我会好好地,正常地,氪金地去玩这个游戏吗?不可能的,玩游戏哪有破解它有意思呢。当年破解 Ingress 是因为它用的 HTTPS 通信的,算是本行。百万亚瑟王是因为别人已经逆向好了,我只是写了一些 bot。现在这么办,玩不了了吗?作为一个不会安卓,不会逆向,不会汇编的菜鸡,那我只好上按键精灵了啊。于是乎,我找到了这个: AnkuLua

AnkuLua 是一個專注在自動化的Android App
基本自動化動作有:

  • 抓取螢幕並找尋指定圖案
  • 對找圖結果採取使用者要的動作(例如點擊、抓放(drag and drop)、打字…等等)

最重要的是,它能运行 lua 脚本!虽然我是一个不会安卓,不会逆向,不会汇编的菜鸡,但是我会 lua 啊。

ankulua-vision

不过,在使用过程中发现,找寻指定图案,需要不断截图/裁剪,这样太麻烦了。于是我又用 electron 做了一个可视化的截图资源管理器 ankulua-vision,像这样的:

基本思路就是,一般游戏是由众多 UI 界面组成的,点击某个按钮能跳转到某个界面上去。那么通过截图,标注识别区域,那么程序就能知道游戏现在所处的界面。通过标注按钮区域,那么只需要 goto('battle'),程序就能自动规划从当前界面到 battle 的可行路径,然后点啊点啊就完成需要的操作了。这样一方面不需要自己去裁剪图片了,另一方面通过框架代码,在运行过程中能够有更多的错误检查,自动应对可能出现的各种异常。

理论上,对于点啊点的游戏,是能实现无代码的。即使不能,对于复杂的动作,也可以通过 lua 拓展。

源码在这里:https://github.com/binux/ankulua-vision

你依旧需要在安卓手机或者模拟器中安装 ankulua,然后加载生成的 start.lua 脚本。默认自带了一个简单的循环逻辑,运行后可以直接图形化界面配置运行。当然你也可以通过 lua 脚本拓展,除了 ankulua 本身的 API 可用之外,你也可以使用 stateMachine 这套界面跳转逻辑 API,重用简化步骤。stateMachine 的 API 在 README 中有简略的文档说明。

源码使用 GPLv3 或 MIT 许可证,取决于第一个有效 PR(例如 fix typo 不算),如果第一个 PR 之前有商业化需求或者 PR 作者要求,则 MIT。

少女前线拖尸脚本

WARNING: 任何使用脚本的行为都是官方禁止的,我不对下文所述任何内容以及其后果负责

于是,这里就是 少女前线的拖尸脚本:

https://github.com/binux/binux_github_com/releases/download/gf/shojo.zip

同时它也是一个 ankulua-vision 的项目,你可以通过 ankulua-vision 打开这个项目目录,调整截屏或者按钮位置。

脚本实现的功能

  • 43e, 02, 52n 拖尸
  • 自动重启后勤
  • 自动强化或者分解人形
  • 自动修理

使用方法

  1. 根据 [填坑结束?][失了智]萌新向拖尸教学帖[更新8-1N相关] 一文准备好打手和阵型,一队练级队,二队补给队,52n 还需要 3 队狗粮队。
  2. 解压拷贝脚本到手机中,在 ankulua 中加载 start.lua。
  3. 在启动界面中选择你的两个打手(每轮结束后,两个打手会交换),选择拖尸任务,如果仅自动后勤,选择 null 就好了。

其中 52n 会在战斗中撤退 5, 8 号位 (见 NGA 文 “43e的说明” 展开部分),02 在选择 m4a1 时会撤退 1, 7 号位。

然后开始吧!

WARNING: 任何使用脚本的行为都是官方禁止的,我不对上文所述任何内容以及其后果负责

over

依云's avatar

使用 cgroups net_cls 来让 docker 走代理

本文来自依云's Blog,转载请注明。

我这里 docker hub 连不上或者连上了访问很慢,根本没法用。本来我常规代理的办法,要么是 proxychains,要么是用 iptables 代理特定的 IP 段。至于 docker 嘛,亚马逊的 IP 段那么多,它用到的域名我也不是很清楚,一点点加好麻烦。作为系统服务,用 proxychains 不仅得修改 systemd 服务配置,而且不知道会不会出什么幺蛾子。最近刚好在某个地方看到这一手,就试试啰。

其实用法很简单的。去 /sys/fs/cgroup/net_cls 下建立个目录,往 net_cls.classid 里写一个整数(支持十六进制的 0x 表示法),然后把 dockerd 的 pid 写到 cgroup.procs 里去。最后用 iptables 代理这部分流量即可。现在都用 443 端口啦,所以只要代理它便好,也避免影响了别的东西:

iptables -t nat -A OUTPUT -p tcp --dport 443 -m cgroup --cgroup 0x110001 -j REDIRECT --to-ports XXX

XXX 是 ss-redir 的端口啦。

注意不要把进程的 pid 往 tasks 文件里写。那里得写的是 task 的 id 而不是 process 的 id,也就是说(用内核的术语来说)是线程的 pid 而不是进程的 tgid(thread group id)。所以非要写 tasks 文件的话,得把 docker 所有的线程的 pid 都写进去才行。真是混乱呢……画个表格好了:

用户态 内核 相关系统调用
pid tgid getpid, kill
tid pid gettid, tgkill
process task group fork, clone without CLONE_THREAD
thread task clone with CLONE_THREAD

另外如果更新过内核的话,那句 iptables 有可能会找不到模块的。(所以更新内核之后还是重启一下以避免尴尬吧。)

依云's avatar

使用 cgroups 限制指定进程的内存使用

本文来自依云's Blog,转载请注明。

最近我的系统有这么个问题:在备份或者系统更新等高 I/O 负载的时候,系统整体性能下降严重,界面经常卡到动不了。经过分析发现此时比平常多了许多磁盘读操作。平常的时候磁盘读操作是很少的,会有大量的缓存命中,反倒是写操作一直都有(因为我本地搭了个监控系统)。啊对,分析用到的磁盘性能数据就是来自于这个监控系统。

所以原因很清楚了:备份和系统更新不仅造成了大量缓存未命中,还占用了本来存放着热数据的缓存,导致常规使用的缓存命中率也急速下降,结果我的机械硬盘就忙不过来了。

那么,要是能够限制这些操作占用的缓存,性能不就能好一点吗?那些新读进来的数据反正是短期内再也用不到了,缓存起来也只是浪费有限的内存空间啊。

研究了一下 /sys/fs/cgroup/memory/memory.stat,看起来 cgroups 内存限制是包含缓存部分的,于是就试试呗。正好 systemd 直接就能设置了:

$ sudo systemd-run -p MemoryMax=512M --scope pacman -Syu

本来我是设置的 256M 限制,结果发现 dkms 编译内核模块的时候超级慢,还用掉了不少 swap……于是分了 512M。效果还是不错的,常规操作偶尔还是卡一卡(毕竟还是有一些 I/O 操作),但比起不限制的时候要少很多。

要注意一点的是,不使用 cgroups v2 的话(Arch Linux 默认),这个命令不能加 --user 以在用户级的 systemd 下跑的。而使用 cgroups v2 的话,lxc 和 docker 都跑不了……

备份也是类似的,而且因为 rsync 自己用不到多少内存,这个效果更好:

$ systemd-run -p MemoryMax=256M --scope ./backup-my-system

终于又一次在半小时内完成了备份 QAQ 之前动不动就一两小时的。

我也不知道为什么这个问题近期才出现,总之现在是缓解了。(接下来有空继续计划换 SSD 硬盘的事情~

IceHoney Blog's avatar

localStorage互斥锁的使用

JavaScript是单线程语言,所以我们在写代码的时候根本不会遇到互斥锁的问题。但是当用户打开多个Tab页面的时候,这些页面却是共享同一个localStorage的。当我们试图修改localStorage的时候就会遇到竞争问题,如果两个页面同时修改了localStorage,程序的可靠性就无法保证。

多Tab互斥

这个问题查了不少时间,目前有的解决方案:Shared Web Workersfast mutex。由于想尽可能的支持更多浏览器,所以我们选择了后者。

实现localStorage互斥

fast mutex的源码也不是很多,所以读起来也没有很复杂。当执行lock函数的时候,会为一个key存储 _MUTEX_LOCK_X_KEY_MUTEX_LOCK_Y_KEY。以下简称X和Y。 首先存X,然后读Y。如果Y存在说明别人已经拿到互斥锁了,所以重新执行函数。直到获取到互斥锁。如果Y不存在,说明没有人竞争锁。所以往下继续执行存储Y。 但是我们不能保证这段时间没有别的tab来存储X或者Y。所以继续读取X,如果X没有发生变化,说明没有人来竞争锁。我们就可以resolve传入的回调函数了。 如果X发生了变化,说明有人来竞争互斥锁,这时候的函数设置了一个50ms的延迟执行,就是保证检测的足够晚。竞争的tab能够执行完自己的lock函数。50ms之后再去读取Y,如果发现Y没有发生变化,则自己还拥有这个互斥锁,可以顺利执行resolve。否则自己丢失了互斥锁,重新执行lock函数。

总结

fast mutex的实现确实很巧妙,通过添加两个localStorage值和setTimeout完成互斥锁的实现。看到这个项目之前,一直以为想做到localStorage的互斥是不现实的事情。

SgDylan's avatar

音频互联笔记兼 VB-Audio 使用小结

farseerfc's avatar

東方歌詞翻譯遷移至 sak.uy

最近幾個月在這個博客發了不少歌詞翻譯 似乎有要轉型成音樂博主的趨勢 ,前段時間買了個新域名 sak.uy ,準備專門用來放這些東方歌曲的歌詞翻譯,於是分設了單獨的博客「 Sakuya的音樂盒 」。主博客這邊右側邊欄會有到音樂盒的鏈接。

曾經在這邊的那些歌儘量保持 URL 跳轉過去,新的歌詞翻譯會發到那邊去,還想繼續聽歌的話請繼續訂閱那邊的 RSS 呀。

主博客這邊還是像往常一樣保持記錄生活點滴和技術經驗好了。說道介紹技術, 有人問過我那些日語歌詞上給漢字標註的假名都是我一個個手輸的麼? 一開始是手輸的,後來發現了不錯的自動化方案,於是這裏介紹一下。

首先是 python-furigana

這是個 python 寫的小程序(嚴格說是庫),可以把一段日文轉換成標準的 HTML 形式的 <ruby> 標籤的振假名( 振(ふ) り 仮名(かな) )。 它本身只是個方便的格式化庫,實際工作是用 python-mecab 這個 binding 去查詢 mecab 這個著名的日語語料分析庫。要用它還得配合一些開源的 mecab 詞典,這些在 [archlinuxcn] 都有打好的包了,直接安裝:

$ sudo pacman -Syu python-furigana mecab-git python-mecab mecab-ipadic

裝好之後用法也很直接,甚至沒有 binary 直接調用 python 的 module 就可以:

$ python -m furigana.furigana "振り仮名の例"
<ruby><rb>振</rb><rt>ふ</rt></ruby>り<ruby><rb>仮名</rb><rt>かめい</rt></ruby>の<ruby><rb>例</rb><rt>れい</rt></ruby>

就是提供日語作爲輸入,然後輸出 HTML 形式的 <ruby> 標籤而已。 像上面的例子中出現的錯誤(「振り仮名」完整的一個詞中「仮名」意思是「平仮名」應該發音「がな」而非意爲「假的人名」的「かめい」) 可以看出其實標註的準確率還是有些問題的。嘛日語作爲一個非常依賴上下文判斷的語言, 經常日本人都會搞錯某些漢字的發音,這些也不能強求機械化的算法能 100% 正確實現。 好在單純的詞典匹配也能滿足大部分標註的需要了,用這個標註總體來說 95% 以上的情況都是正確的(歌詞的話正確率低一些,畢竟歌詞中古語啦当て字啦訓読み這些情況很常見)。

把輸出插入我的博客

然後我的博客用 reStructuredText 語法寫,不能直接用 HTML 標籤(雖然我加了 :html: 這個 行內角色(inline role) 但是大量用也不方便)。這個博客一開始用 Pelican 重寫主題的時候 我就實現了個自己的 :ruby: 行內角色(inline role) 用來標發音,於是一段 sed 就能把 python-furigana 的輸出轉換成我用的 rst 語法:

$ which clipboard Co Ci Ct
clipboard: aliased to xclip -selection clipboard
Co: aliased to clipboard -o
Ci: aliased to clipboard -i
Ct () {
    t=$(mktemp /tmp/furigana-XXXX)
    python -m furigana.furigana $(Co) | sed 's@<ruby><rb>@ :ruby:`@g;s@</rb><rt>@|@g;s@</rt></ruby>@` @g' | sponge $t
    cat $t | tee /dev/tty | perl -pe 'chomp if eof' | Ci
}

上面這些 alias 在我的 .bashrc 中。有了這些之後, 我只要把需要標註的日語文本放入剪切版,執行 Ct ,再粘帖結果就好了。

$ echo "振り仮名の例" | Ci
$ Ct
:ruby:`振|ふ` り :ruby:`仮名|かめい` の :ruby:`例|れい`

然後所有那些歌詞上標註的假名都是這樣一句一句標註好之後,再手動校對修改的。

's avatar

《还愿》很棒,可是为什么要乳滑,为什么啊?

前几天,台湾游戏制作团队「赤烛」发布了它们的第二部作品《还愿》。本身是很正常的恐怖游戏,有许多人觉得它非常恐怖,也有许多游戏主播不畏恐惧地在给害怕自己玩的人直播。这是对于一个非常恐怖的恐怖游戏来说,再正常不过的现象了。只是里面有一个彩蛋,引起了不和谐的风波:

「习近平小熊维尼」,用篆体写在了一张贴图上。

明明是这么优秀的游戏,为什么偏偏要乳滑啊?为什么啊?这实在太可惜了——我看到许多人这样想。如果是曾经的我,大概也会这样觉得。但是现在如果你有这样想法的话,我写出了这篇文章,希望可以缓解一下你的心情。

「明明是非常棒的作品,可为什么偏要加入这样侮辱的东西啊?」我也经常有这样的感受。自己喜欢的东西,却不得不和自己非常讨厌的东西纠缠着,对于这两者的结合,要是讨厌它也太浪费了,可要是喜欢它的话,对于自己讨厌的部分却无法释怀。这毫无疑问是一件令人难受的事情。可是,在这次事件中,这个令人讨厌的部分,自己真的有必要那样讨厌吗?

简单地说,我觉得这没有什么大不了的。游戏彩蛋拿国家领导人开玩笑,并不是一个需要非常反感的事情。

拿一个人开玩笑再正常不过了。当然,要除了当这个玩笑是对着自己开,而我们觉得这个玩笑开得很不恰当的时候;或者当这个玩笑会冒犯到我们喜欢的人的时候(是广义上的喜欢,包括朋友、家人,还有偶尔遇见的路人)。而习近平,需要被我们当作是喜欢的人吗?他当然是国家领导人,可这也并没有使他在这个方面变得有多么特殊,事实上作为政治人物,被骂是再正常不过的事情了。在世界的大部分地方,开政治人物的玩笑也是很平常的事情。我们说奥巴马长得像跳跳虎,安倍长得像驴,川普在各种演讲上的发言以及推文上的错别字实在是太搞笑了。这些都没有问题,那么说习近平小熊维尼,为什么就不可以了呢?游戏彩蛋没有针对对我们玩家中的任何一个人,而只是针对习近平开玩笑。为了这样一个遥远的人被开玩笑而生气,实在是太没有必要了。我们可能觉得这个玩笑一点也不好笑,但也不必因此反感它嘛。而且作为一国之主,习近平显然不会被这么一个小游戏团队的一句话冒犯到。

台湾独立一直是个敏感的话题,你可能会因为这个游戏宣扬了支持台湾独立的观念而讨厌它。但值得思考的是,为什么在许多观点不同的时候,我们都可以相对和平地相处,而只要涉及一点政治,就不得不暴跳如雷呢?我们在游戏中遇到一个不喜欢的东西,通常都会继续玩下去,如果令我们不喜欢的东西有很多,也最多是批评这个游戏并告诉其它人不要去玩,并希望开发者能在以后改进。遇到自己不支持的政治观点时也是一样,我们只需要表达自己的不认同就足够了,而不需要像 Steam 上的许多评论评论中一样辱骂开发者,诅咒他们早点解散。当然,你可能还是会觉得一个游戏加入了自己讨厌的政治观点是无可救药的——可是如果我们回来看,《还愿》的这只彩蛋里面,也并没有说任何支持台湾独立的话啊。

不管你是觉得台湾独立是非常坏的主意,或者是需要双手赞成的提案,还是觉得都无所谓,都和这个游戏没有关系。《还愿》又不是一个政治游戏,它只是一个包含了「习近平小熊维尼」这句彩蛋的恐怖游戏罢了。赤烛的成员的确可能抱着支持台湾独立的想法,其实大部分台湾人都这样想,但要是仅仅因为作者抱有了和我们不同的观点就要抵制他们的所有作品的话,那世界上有这么多怀有不同观点的作者,岂不是许多作品都需要抵制了?至少基本上所有台湾出产的文学、艺术作品,还有游戏,都会变成需要抵制的对象了,这怎么想都太夸张了嘛。

实际上,即使是面对表达了支持台湾独立的游戏,也没有必要看到就直接拒绝。你也许觉得台湾独立是一件很坏的事情,是分裂国家、挑起战争、对生活影响巨大的事情,但从另一方面想,这有比杀人放火,炸掉政府大楼,宣扬恐怖主义这样的政治理念更加可怕吗?没有吧?但实际上,从电子游戏这方面看来,扮演杀人狂魔和恐怖分子的游戏却备受欢迎。而台湾独立不但远没有这么可怕,也和恐怖主义不同,它在世界上还有非常多的人支持。我们也许认为它是不应该被支持的,但这只是我们的观点,从客观的事实上来说,应该怎样还不知道呢。

当然啦,这篇文章也不是一篇我表达政治观点的文章,我只是希望能够为大家减少一些气愤。真的,一个游戏彩蛋而已,有必要上纲上线吗?如果你也在看完了这篇文章之后,觉得没有必要,那么谢谢你让我的文章变得有用,也祝愿你能够享受游戏,在其它的地方能够少遇见令自己不愉快的事情。如果你完全不同意我的说法,那么也感谢你至少没有马上关掉文章拉黑我,而是耐心的把它读完了。不管怎样,大家怎样做都是大家的自由,对吧?


除特殊说明外,本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。转载时请注明来自 FiveYellowMice's Blog ,以及原文链接

虽然 RSS 是一种很好的新闻获取方式,但是不同的 RSS 阅读器所显示的内容可能会有很大差距,有些甚至无法显示所有内容。所以为了能够获取到完整的内容,最好还是点开网页链接看。
之所以还是保留了 RSS 的全文输出,是因为摘要输出会被很多人讨厌……

cuihao's avatar

留言板备份

null
's avatar

与萌狼的笔谈

是一个平常的夜晚,萌狼少见地发来一条消息,说想要和友情链接里的各位来一次笔谈。然后黄鼠很荣幸地,成为了第一位。正好,黄鼠也经常发愁博文没灵感写、博客日渐荒废呢,要做笔谈的话,不但是个介绍自己和了解别人的机会,也顺便能够给博客补充一点活力。于是就开心的答应了(虽然咕咕咕了 3 天才写有出来)。

所以「笔谈」这样东西是什么呢?

一开始萌狼提起的时候,黄鼠也有些疑惑,可又感觉似乎在其他地方有听说过这样的东西。记得是跟歌手和主播之间互相客串类似的做法, 互相向对方提一些问题,然后各写一篇文章来回答 ——至少萌狼觉得黄鼠这样理解是没有问题的呢。

但黄鼠还是好奇的查询了一下,笔谈具体是什么,然后维基百科说……

笔谈,是指人们在面对面的情况下不使用口头语言而是通过互相书面书写或键盘输入文字的方式,来传达彼此意思的沟通行为。

……是汉字文化圈地域内不同母语的文人相互交流的方法之一。主要使用汉字以及文言文(汉文)的交流方式。

唔唔,诶?原来是东亚国家之间的人以前因为用的文字一样,所以用来勉强交流的方式嘛……好像差距有点大诶。嘛,不管了,总之就当作互相提问的意思好了。

下面就是萌狼提出的问题了

Q1. 除了博客的「关于」页面以外,还愿意再向咱介绍一下自己嘛?

这样的打算,其实很早之前就有呢。看到许多人都有专门的个人主页,做得很漂亮,黄鼠也打算过效仿着做一个。这也是黄鼠购买 fym.moe 域名的原因。结果嘛……点开那个链接的话就显而易见了,个人主页一直处在咕咕的状态,大概已经快要有两年的时间处在这样的状态了。所以要让黄鼠现在做出一些个人介绍的话,也不知道要从哪里讲起呢……

——每次都是这样,自从有了那个个人主页予定的域名之后,黄鼠在每次遇到简略介绍自己的机会的时候,都会这样想:唔啊……这里要怎样说呐……还是等到以后写好个人主页上那篇完整、系统的自我介绍之后,再放一个链接过去好了,在这里写简略的介绍,果然还是太浪费脑筋了。就是因为每次都这样想,而个人主页又一直咕咕咕,所以最后落得黄鼠不管是长的自我介绍还是短的自我介绍,都没有写出来过。

话说,既然说到博客的「关于」页面,那个似乎也需要不小的更新了呢……不过既然黄鼠有决定之后写一篇完整的自我介绍,还是等到那里写好之后再链接过去吧,单独写一下果然还是太废脑筋了。

萌狼是想要黄鼠在这里做出一些自我介绍嘛?可是黄鼠已经有打算在个人主页上面写一篇完整的介绍了,觉得还是等到黄鼠写好的时候,直接去那里看会比较好呢。

(咕咕咕)

Q2. 这个名字是怎么想到的呢?

这其实是自己真的还在中二的时候,做出的一些饱含中二成分的决定啦……唔,实际上也不只是中二呢。要说出来的话,还是太羞耻了。

总之总之,大家先这样看。

首先, Five ,是一个很吉利的数字,对吧?一个正常人就是有五根手指,所以这就是 Five 的来源。至于一个人有一只手还是两只手,那种事情就先不管啦。

然后 Yellow ,是因为,呃,那个,柠檬的颜色,对吧?柠檬吃起来很甜,一点都不酸,对吧?黄鼠可以一口气吃下 5 个,所以这就是 Yellow 的原因。

最后呢,这个, Mice ,怎么说呢,就是就是,唔,要怎样解释大家才会相信呢。就是这个……老鼠!老鼠……呃,老鼠很厉害对吧?可以吃掉猫咪,所以这就是 Mice 的来源,嗯。

以上的解释都是真实的 FiveYellowMice 的名字的来源,而且没有一点点事实错误哦。(光速逃)

Q3. 是怎么喜欢上视觉小说的呢?

剧透警告:这里会有对《守护甜心》第二季的开始,对藤咲的介绍的小剧透喔。虽然不算是很重要的内容,但失去这个惊喜还是很可惜的。

其实主要的原因很简单呢,说是令人大跌眼镜也不为过,当时自己可以使用到的电脑,性能非常差劲,连 Ubuntu 的 Unity 桌面都会让显卡吃力无比。主流的游戏都没有办法运行,于是就只好推视觉小说了 _(:3)<)_ 。

一开始接触视觉小说,是因为看到《守护甜心》里面的藤咲凪彦,觉得很厉害,所以就到百度百科上面看了看,就发现,原来这样类型的角色不但有专门的名称,而且还有很多诶!兴奋的黄鼠又看到里面说这样类型的角色的始祖是一个被称作《少女爱上姐姐》的视觉小说,于是黄鼠就找来玩了玩,便把新世界的大门打开了(双重意义上的)。

说到现在黄鼠依然喜欢视觉小说的原因的话,就要复杂一些了。黄鼠对 RPG 的剧情很感兴趣,但是又很讨厌维护各种属性值,也不愿意跑来跑去,只想看剧情对话。视觉小说刚刚好就是和去掉游戏成分、只剩下剧情的 RPG 一样,所以在听说了有这样类型的游戏的时候,黄鼠觉得简直就是像找到了知己一样的感觉呢。而且和其它类型的游戏不一样,视觉小说一点难度都没有,对于手残的黄鼠来说再合适不过了。

不过其实黄鼠觉得,把视觉小说和「游戏」比较不是一个很合适的分类。名字都叫做视觉「小说」,内容也是和小说一样,一直往下读就可以了,仅仅是有偶尔出现的选项,能够带来的游戏性和真正的游戏比还是相差太多了。而和真正的小说比较的话,视觉小说不但有多出了背景和立绘,还会经常有很棒的 BGM ,再加上偶尔会有的语音的话,还有一半的动画的感觉,而有了这些附加的东西以后,主要的故事表现手段还是文字。黄鼠觉得文字是一种能够有深度和艺术性的很棒的媒介,漫画和动画都很难避免会失去一些这样的东西,而视觉小说却能够在不破坏小说的优点的情况下,依靠图像和声音弥补了很多的缺点。这就是黄鼠认为视觉小说最棒的地方呢。

Q4. 对咱的印象怎么样?

萌狼嘛……因为第一次认识的时候,萌狼的设定还没有出现,所以一开始的印象是那种很厉害,做事情又有行动力又有坚定想法的大佬。只是后来嘛……才渐渐熟悉起来,意识到其实萌狼是和大家都一样的人(狼?),拥有自己的喜怒哀乐,也有失落的时候。

然后就是萌狼的设定,除了支仓冻砂带来的「狼」的设定以外,萌狼带给黄鼠的印象,就是很喜欢发送「😂」,遇见很多东西的时候都会用「😂」来作为回应。在很多时候向群里面发送一些东西,会一点回应都收不到,黄鼠就会觉得自己发出的内容非常无趣,直到有看到萌狼的「😂」的时候,才欣慰感受到,还是有人觉得黄鼠发送的东西是有趣的呢。是萌狼的「😂」在这些时候给了黄鼠继续下去的动力。

再接下来的话,就是音游的方面了。黄鼠也忘记了是在什么时候知道的萌狼喜欢音游,在意识到以前,音游狼的印象就已经刻印在脑中了。萌狼的音游水平,在黄鼠感觉是那种很厉害,但也不是遥不可及的那种,就像是漫画里的「前辈」一样,让黄鼠把音游渐渐熟悉了。

最后一点,是黄鼠不喜欢萌狼的一点。萌狼喜欢说讽刺的话,或者是叫做风凉话。像是在有新人被推荐东西的时候说「不要用。反正都是被大佬鄙视的」这样的话,以及在完全没有提起萌狼如何的时候说「您您您,咱就是弱鸡」这样的话。萌狼说这是在音游圈子里面的普遍现象,可是黄鼠觉得,音游圈里面会崇拜水平高的玩家,对其他人卖弱,但没有必要说讽刺的话嘛。

Q5. 还记得第一次接触 GNU 是什么时候嘛?

如果是说第一次用到 GPL 的软件的话,那应该是很久以前了。也许 Firefox 是黄鼠第一个在自己家的设备上使用过的 GPL 软件,但也不能确定有没有更早的呢。

如果是说第一次知道 GNU 这个理念的话,大概是在 2015 年,黄鼠使用 Ubuntu 的时候了。觉得 GNU 非常厉害,能够使开源的东西也这样好用呢。黄鼠也很认同利用自己的开源软件,使别人在使用了黄鼠的开源软件的时候也不得不开源的做法。开源作为一个大家共有的东西,索取了再返还,也是合理的事情。然后黄鼠就成为了 RMS 的粉丝,开始传教……(逃)不过大概没有萌狼厉害啦。

Q6. 现在有在做什么嘛?

自从高中毕业了之后,黄鼠就越来越颓废了。以前本来是计划了好久,雄心勃勃的计划,都越来越缺少动力去做了。两年前有着想写一个评论系统的计划,到了现在一直也没有见到里程碑。再之前打算写的可以自定义项目的追番列表 sedosipE ,即使有了想要看许多列表里面都没有记录的冷门漫画的需求,也还是随着各种其它的事情渐渐淡化了。

现实方面的,去年有试过健身,但果然体育方面的事情还是没有办法让黄鼠有动力去做呢。脱离了教练的监督以后,就一直颓废下去了。另外也担心健身效果太好的话,女装的计划就得抛弃了,黄鼠觉得这样是很大的损失。

不过女装最近倒是有开始尝试了。之前放假的时候心血来潮,在超市里面买了一盒脱毛膏,又痛苦又耗时地把两条腿处理完毕了。不过那个时候,黄鼠还没有打算马上开始女装,是在同一天,一位群友的说「既然已经脱毛了,不如就开始女装吧,要不然之后还得来一次」,使黄鼠提早产生了女装的动力。现在有到下半身的程度,但是上半身的挑战看起来更加严峻呢……要化妆什么的更是听起来就令人望而却步,于是就连这也开始停滞了。

也是在假期的时候,觉得自己越来越滞后的黄鼠,感到自己一定要继续学习才行,于是就把放置了很久的《Head First C》拿出来看了。里面有一章是有写用 Arduino 做出东西,黄鼠想「诶, Arduino ,是听说过很多次的名字诶,大家好多人也都有玩过的样子」,于是在新年回到中国的时候,依靠淘宝进入了这个大坑。这次黄鼠再次雄心壮志地立下了自己要做出一个带有 16x16 LED 屏幕的东西,但是组件比想象中地多了很多,黄鼠又因为面基 Eq彼得,还有过年回老家探访亲戚什么的,错过了春节快递停运之前的时间,只好等到回到澳洲之后才能梳理需要的组件。但是这样子的话,成本就噌噌地上涨了呢。时间也是大概要等到一个月之后,材料到达之后才能开始了……希望到达的时候,黄鼠的热情没有消减才好呢。

还有还有最后一点,就是想要恋爱 ( > ∀ <) /!虽然在这样的方面,黄鼠看起来也没有什么可以 take initiative 的事情就是啦。

Q7. 有什么话要对咱说嘛?

平常都有说话的机会,所以硬要黄鼠说下什么的话,也不是一件容易的事情呐。总之……萌狼好吃!

萌狼好吃!
萌狼好食!
萌狼好吔!

(在被追到之前赶紧逃)

笔谈还有另一边喔!

上面是黄鼠对萌狼提出的问题的回答,那么既然是交换提问回答的笔谈,黄鼠也向萌狼提出了一些问题,让萌狼在萌狼的博客上面回答呢。如果还没有看过的话,可以走向这里喔。

🍎😋


除特殊说明外,本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。转载时请注明来自 FiveYellowMice's Blog ,以及原文链接

虽然 RSS 是一种很好的新闻获取方式,但是不同的 RSS 阅读器所显示的内容可能会有很大差距,有些甚至无法显示所有内容。所以为了能够获取到完整的内容,最好还是点开网页链接看。
之所以还是保留了 RSS 的全文输出,是因为摘要输出会被很多人讨厌……

HY's avatar

TwitterImg Downloader

想必不少朋友也和我一样关注了很多画师,定期收图。 Pixiv的图片文件名可以直接反推出图源,直接保存就可以,但 […]
's avatar

FLAC / MP3 / WAV 批量转 aac

自动检查 ffmpeg 是否有启用 fdkacc-lib,如果没有则使用 native_aac 编码器。

关于编译带有 fdk 支援的 ffmpeg 请参见官方文档;因为 GPL 病毒的原因,就不放出编译版了。

#!/usr/bin/env node
/**
 * FLAC/MP3 to aac script
 * MIT License
 * (C) 2019 Jixun.Moe
 */

/* configuration */
const srcExt = ['flac', 'mp3', 'wav'];
const maxThreads = 4;

/*
 * override with command line options
 * node to_acc.js ./rip ./aac
 */
const srcDir  = process.argv[2] || './rip';
const destDir = process.argv[3] || './aac';

/* import modules */
const fs = require('fs');
const util = require('util');
const readdir = util.promisify(fs.readdir);
const copyFile = util.promisify(fs.copyFile);
const exec = util.promisify(require('child_process').execFile);

/* global variables */
let threads = [];
let files = [];
let aacCodec = 'aac';

function getExt(name) {
    const m = name.toLowerCase().match(/\.(\w+)$/);
    if (m) return m[1];
    return '';
}

async function scanDir(dir, outDir) {
    const scanResult = (await readdir(dir)).filter(d => d[0] != '.');
    for (let i = 0; i < scanResult.length; i++) {
        const inPath = dir + '/' + scanResult[i];
        let outPath = outDir + '/' + scanResult[i];

        const stat = fs.statSync(inPath);

        // sync directory structure.
        if (stat.isDirectory()) {
            // create subdirectory
            try {
                fs.statSync(outPath);
            } catch {
                fs.mkdirSync(outPath);
            }
            await scanDir(inPath, outPath);
            continue;
        }

        const inExt = getExt(inPath);

        // Music file to convert
        if (srcExt.indexOf(inExt) != -1) {
            outPath = outPath.slice(0, -inExt.length) + 'aac';

            try {
                fs.statSync(outPath);

                // file exists, skip...
                continue;
            } catch {}

            files.push([inPath, outPath]);
            continue;
        }
        
        // other file type
        console.info('copy %s...', inPath);
        await copyFile(inPath, outPath);
    }
}

async function doWork(thread) {
    while (true) {
        let work = files.shift();
        if (!work) break;

        const [input, output] = work;
        console.info('[T%d] converting %s...', thread, input);
        await exec('ffmpeg', ['-i', input, '-c:a', aacCodec, '-vbr', '3', output]);
    }

    console.info('thread T%d complete.', thread);
}

async function detectFdk() {
    const {stdout, stderr} = await exec('ffmpeg', ['-codecs']);

    // test for libfdk
    const useFdk = /encoders:[\w\s]* libfdk_aac/.test(stdout);
    console.info('libfdk: %s', useFdk);

    aacCodec = useFdk ? 'libfdk_aac' : 'aac';
}

async function main() {
    // let detect and scan run at the same time.
    const detect = detectFdk();
    await scanDir(srcDir, destDir);
    await detect;

    console.info('to process: %d files.', files.length);

    // create threads
    for(let i = 1; i <= maxThreads; i++) {
        threads.push(doWork(i));
    }

    // wait for thread complete
    // 感谢 orzFly
    await Promise.all(threads);
    
    console.info('done');
}

main();
依云's avatar

在 Linux 下整理磁盘碎片

本文来自依云's Blog,转载请注明。

磁盘碎片其实有两种:文件碎了,和空闲空间碎了。使用 FIEMAP 命令可以获取到文件在磁盘(的逻辑地址上)的分布情况。也是 filefrag -v 命令输出的东西。比如我的 pacman.log 就很碎:

Filesystem type is: 58465342
File size of /var/log/pacman.log is 11052443 (2699 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..    2015:  170210423.. 170212438:   2016:
   1:     2016..    2017:  170567879.. 170567880:      2:  170212439:
   2:     2018..    2027:  170569969.. 170569978:     10:  170567881:
   3:     2028..    2030:  170574582.. 170574584:      3:  170569979:
   4:     2031..    2031:  170574631.. 170574631:      1:  170574585:
   5:     2032..    2033:  170592662.. 170592663:      2:  170574632:
....
 123:     2683..    2687:   56903805..  56903809:      5:   56906403:
 124:     2688..    2698:   56903011..  56903021:     11:   56903810: last,eof
/var/log/pacman.log: 125 extents found

整理的办法也很简单,复制一下,基本上就好了。只要剩余空间足够,小文件会变成一整块,大文件也是少数几块。如果非要弄一整块大的,比如我存放 pacman 数据库的那个小文件系统,可以用 fallocate -l 200M pacman.fs2 这样子的命令分配空间,然后把数据 dd 进去(cp 不行,因为它会先截断文件再写入,之前分配的空间就释放掉了)。

介绍完毕,重点来了:怎么找到那些被写得很碎很碎的文件呢?

对每个文件调用 filefrag 肯定太慢了,所以我写了个库和工具 fiemap-rs 直接调用 FIEMAP。它提供两个工具。一个是 fraghist,统计碎片数量分布直方图,用来了解一下某群文件有多碎。另一个是 fragmorethan,用来寻找碎到一定程度的文件。运行起来是这样子的:

/var/log:
# Number of samples = 712
# Min = 1
# Max = 297
#
# Mean = 11.338483146067423
# Standard deviation = 40.138129228003045
# Variance = 1611.0694179238724
#
# Each ∎ is a count of 13
#
  1 ..  31 [ 658 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
 31 ..  61 [  11 ]:
 61 ..  91 [   9 ]:
 91 .. 121 [  10 ]:
121 .. 151 [   6 ]:
151 .. 181 [   5 ]:
181 .. 211 [   3 ]:
211 .. 241 [   2 ]:
241 .. 271 [   3 ]:
271 .. 301 [   5 ]:
/var/log/journal/00000000000000000000000000000000/system@xxx.journal: 271
/var/log/journal/00000000000000000000000000000000/system@xxx.journal: 277
/var/log/journal/00000000000000000000000000000000/system.journal: 274
/var/log/journal/00000000000000000000000000000000/system@xxx.journal: 297
/var/log/journal/00000000000000000000000000000000/system@xxx.journal: 274

我系统上最碎的两群文件是 journal 日志和 python2-carbon 的数据文件。carbon 优化做得挺不好的,明明是预分配的固定大小文件啊,不知道怎么的就弄得很碎了。部分程序的日志(如 pacman、getmail)和火狐的 SQLite 数据库也挺碎的。后边这些我已经处理掉了所以示例输出只好用 journal 的啦。

找到想要整理的过碎的文件之后,复制一下就好啦:

for f in $(<list); do sudo cp -a $f $f.new; sudo mv $f.new $f; done

啊对了,工具的编译方法是,获取源码并安装 Rust 之后,在项目根目录里 cargo build --release 然后就可以在 target/release 下找到新鲜的可执行文件了~顺便说一下,这东西是支持 Android 的哦。

brainbush's avatar

OpenWrt 编译安装 Nginx rtmp module

参考 https://wonpn.com/2018-03-15-compile-nginx-with-ssl.html

1. 下载 OpenWrt SDK

这里我使用的是斐讯K3,所以下载 bcm53xx 的。

wget https://downloads.openwrt.org/releases/18.06.2/targets/bcm53xx/generic/openwrt-sdk-18.06.2-bcm53xx_gcc-7.3.0_musl_eabi.Linux-x86_64.tar.xz
tar xf openwrt-sdk-18.06.2-bcm53xx_gcc-7.3.0_musl_eabi.Linux-x86_64.tar.xz

2. 下载 Nginx rtmp module

wget https://github.com/arut/nginx-rtmp-module/archive/v1.2.1.zip
unzip v1.2.1.zip

3. 下载nginx并添加设置选项

./scripts/feeds update
./scripts/feeds search nginx
./scripts/feeds install nginx

修改 package/feeds/packages/nginx/Congif.in 添加:

config NGINX_RTMP
         bool
         prompt "Enable RTMP module"
         help
                 Enable RTMP module
         default n

修改 package/feeds/packages/nginx/Makefile ,在213行附近(TARGET_CFLAGS前)添加:

ifeq ($(CONFIG_NGINX_RTMP),y)
  ADDITIONAL_MODULES += --add-module=/path/to/nginx-rtmp-module
endif

4. 修改和编译

make menuconfig
# 在network->Web Servers/Proxies->Nginx->Configuration->开启 Enable SSL module 和 Enable RTMP module 
# (如没有RTMP module请检查是否在Config.in重添加)
make -j4

5. 抱走 Nginx 包

cp bin/packages/arm_cortex-a9/packages/nginx_1.12.2-1_arm_cortex-a9.ipk /where/you/want
摸完了
's avatar

空白的 2018

总而言之,Benpigchu 的整个 2018 年几乎什么像样的事情都没有做。如果是有心观察 Benpigchu 的人的话,大概已经发现这一点了吧。

现在看来过去的这一年和接下来的几个月会是人生中比较困难的一段时间了。

发生了什么

这个……我也不是很清楚,只能大概描述一下。下面的文字会比较混乱。

其实一直以来 Benpigchu 对于自己的未来一直处于迷茫,或者说是,逃避的态度,以至于没有为未来做任何的准备,所以也没有科研经验和实习经历。

而在 2017 年的后半,也就是大三下学期,迎来了 THU 计算机系的五大金刚课程(编译原理、网络原理、计算机组成结构、软件工程、信号处理原理)。这个学期可以说是榨干了我的行动力,虽然挺过来了,但是似乎也产生了一些不好的后果。

我们 THU 计算机系的保研安排是在大四下学期,在这之前我的家长因为看我犹豫不决,所以建议我争取保研,但是……总之我没有动力为这个目标去努力。到了暑假的后半,母上甚至来协助……或是强制我准备申请。这份好意我是理解的,但是在我的抗拒之下理所当然地失败了。

再之后就是这一年的后半,大四上学期。按理说我应该在此时通过秋季校园招聘找到一份工作,但是由于履历的缺失、简历投递少,我并没有获得一份 offer。然后就到了现在了。

过去的一年大概上就是这样的情况吧。

可是为什么不行动起来啊

你说得对,错的是我。

可是为什么我会是错的呢?我其实也不太清楚,但是似乎有一些线索在……确实感觉自己有些地方不太对。

一个……应该是比较低的自我评价。毕竟一方面自己没有什么建树,另一方面 THU 计算机系真是人才辈出,无论是什么方面都能找到能碾压你的人,自然就无法自信起来。更可怕的是这种思维一旦建立起来,就很难从外界改变,别人的赞美会被当做是恭维,而就算真的做到了什么也只会有“这不是大家都能搞定的事情么”而没有什么成就感。这种自我评价甚至还会自我应验,因为怀疑自己所以不敢尝试,因为没有尝试所以把事情搞砸。可以说算是一个蛮严重的问题的。

还有一个就是害怕和逃避未来吧。确实大学这几年来并没有思考过将来的打算,或者说是在害怕这种不确定性而不去做这种思考。事实上我能确定的比较大的计划仅仅是不去做某件事情而已。我不知道我的前路该如何走,我也不去考虑,所以我只能这样子混日子混下去。

于是我就成为了一个没有行动力的人。没有目的就没有推力,害怕结果就会产生阻力,最后当然什么也做不到。

于是,我的困境

现在的我是一个没有毕业去向的人。工作肯定是要找的,但是就算我是 THU 计算机系的,没有个像样经历,GPA 又低于半数同学,我能得到一个还可以的 offer 么?

由此引发而来的是来自家庭的压力。我既然是 THU 计算机系的,那肯定能有不错的前程。就算这句话以一种鼓励的语气说出来,也会被理解成一种过高的期许,甚至是一种嘲讽。我不知道我该如何回应这种鼓励,更不用说批评和鼓励了。

更重要的是我要如何修复这种糟糕的心态,毕竟长此以往就算有偶尔的成就,也于事无补的。

我要如何重回正轨?

我不知道。

也许我应该行动起来,但是我要如何行动起来,或者说有什么能让我行动起来?

我真的不知道要如何回答这个难题。

也许我写下这段文字就能帮助我解决一些问题,但是也许不会有什么实质性的效果。

总之祝我好运吧。也祝你们好运。

依云's avatar

docker 里几个基本概念的简单类比

本文来自依云's Blog,转载请注明。

首先说明一下,这是一位 docker 新手对于 docker 的粗浅理解。如有不对还请谅解。我很早之前就尝试过使用 docker,然而由于术语的差异,导致我每次运行东西时都傻乎乎地创建了一个新的容器……现在感觉用法终于是弄对了,所以整理一下,将其类比到 Linux 上的普通软件的概念上。

image 相当于软件分发中的软件(安装)包。 Dockerfile 跟 PKGBUILD 类似,是用于制作一个 image 的打包脚本。用 docker build -t name:tag . 就可以制作。 container(容器) 一个容器就像是一个安装好了的软件包。该软件已经准备好,随时可以运行了。 docker run 「安装」指定的 image。也就是从 image 制作出容器来,顺带着进行首次运行。如果反复使用,会把同一个软件给安装多次。 docker start 就像是「运行」一个已经安装好的软件,容器跑起来了。之前容器的状态(文件的修改)也会生效。 docker ps 列出运行中或者已安装(带 -a 参数)的软件们。前者和 UNIX 命令 ps 类似,后者则没什么相似之处了。 docker exec 在正在运行的软件的环境内执行命令。有点类似于 ssh。 repository 跟 Linux 的包含众多软件的软件源并不一样。这个东西跟软件名类似,用于标识为特定功能的 image 集。发布出来的 repository 名的格式通常是 `owner/name`,跟 GitHub 差不多的。 tag 软件的版本,跟什么 lite、pro、beta 之类区分类似。它并不是用于分类的标签,也不是 git 中对于指定版本的不变的称呼。它更像是 git 的分支在某些情况下的作用,比如 latest tag 就跟 git 仓库的 master 分支一样,总是指向最新的版本。

我经过以上这样的映射之后,docker 理解起来就容易多了,行为也更符合预期。

farseerfc's avatar

用 usbip 轉發 raspberry pi 的 USB 鍵盤鼠標給 Arch Linux 的 PC

惠狐 megumifox 寫了篇 用PulseAudio將電腦的聲音用手機放出來 ,文末提到想知道我怎麼用樹莓派轉發 USB 的,於是寫篇文章記錄一下。

起因

家裏有個裝了 Arch Linux ARM 的樹莓派3B 閒置着,裝了 Arch Linux ARM 偶爾上電更新一下, 不過因爲性能實在不適合做別的事情於是一直在吃灰。某日 給老婆安利幻想萬華鏡和老婆看片 的時候, 老婆不吃安利於是遷怒鍵盤鼠標鍵盤鼠標被長長的 USB 線扯着感覺很難受 ,於是偶發奇想,能不能利用一下樹莓派的多達 4 個 USB 2.0 端口接鼠標鍵盤呢, 這樣鼠標鍵盤就可以跟着樹莓派來回走,不用拖着長長的 USB 線了。

上網搜了一下, Linux 環境有個 usbip 工具正好能做到這個。原理也很直觀, usbip 能把 USB …

's avatar

莉兹与女装变态杀人魔的选择

有人提醒我 SSL 证书过期,于是我想起来,我还有一个博客。

或许是因为 acme.sh 更新,或是什么变化,总之就是挂了,十分遗憾。但挂在 GitHub pages 上的主页大多数情况下都不会挂,所以可以去那里看一看。

回不来的时间

新年的冬风,今年也是格外的刺骨。虽然没有新闻里芝加哥那么冷,但至少晚间在回去的路上,不穿上厚外衣,戴上手套,捂紧帽子,是免不了要瑟瑟发抖一番的。

农夫冻得手脚冰凉,在与蛇的战斗中,两手僵硬,有劲无处使,落得一个被蛇咬的下场。

元月27日或许是一切混乱的起点。

这一天,弄到了一个卖手机亏损的公司生产的家用主机。于是 Jirga Para Lhao 被拯救了。但 30 个小时就这样过去了。

青鸟不会做杀人的梦

我有时候会思考应该如何写一篇感想。

客观性是我试图避免的:我想写一些主观的、个人的感受,而不是所有人都会感受到、都可以表达出来的东西。我想写的是我个人的感想,而不是所有人的感想。之前的尝试在这一方面都不算是令人满意——大多时刻只是事实的罗列,或者是单纯的侃侃而谈。

聊天倒是也不坏。蔡康永的情商书(为什么我会看这么大众的书,不过转念一想,倒也有种别样的趣味)里就有“分身”这一说法。人每时每刻都需要和他人交流,但往往会忽视与自己的交流。与自己的交流听起来好像很奇怪。尝试培养另外一个不同的自己,跟这个自己对话。这可以说是一种审视自己的方式,也可以是一种批判性思考的方式。从这一个方向用尽九牛二虎之力也推不开的门,说不定换个方向就能轻松打开。

回到侃侃而谈。可能变成侃侃而谈也能从侧面说明,想从心灵这个湖里,捞出感想的鱼,不是件容易的事情,把捞上来的鱼卖给他人,也不是件容易的事情。不过鱼还没有捞上来,就想着销路,算是有点眼高手低了。

不过鱼有大的鱼和小的鱼,就像苹果有甜的苹果和不甜的苹果。大的鱼属于那种容易发现的。比如看完《活着》,感受到悲伤、无奈、沉重。不过转念一想,悲伤和喜悦都只是游在表面上的鱼,而在深水里的,是那种达观、顽强、活下去的力量,是这股力量支撑着人走下去。活着才有酸甜苦辣,活着才有风雨彩虹。

结果又变成万人都能说出的感想了。我大概不适合这差事。

同学聚会

参加了高中的同学聚会。令我惊奇的是,我没那么快活。

用一句大俗话来说,就是感觉少了点什么。

我曾经不止一次梦到过和高中同学搞事——建车站、开组会,无所不为。这或许这是我高中过于安分的反作用。搞事的时候我是快乐的,虽然在梦里的事都说不清楚,但大概的确是这样。

所以一个很大的可能就是,因为没怎么搞事。

灰姑娘是不是因为穿上了水晶鞋,所以不能自由奔跑了呢?

我翻遍了卡拉 OK 的歌单,翻遍了火锅的锅底,但都没有找到答案。

冬天来了,冬天还会远吗

在严寒中,在风雪里,食堂一个接着一个地关门了。有的等春暖花开之际会像燕子一般归来,有的则永远也不会回来了。

可我仍然没有吃到藤椒口味的浇汁饭。

Cee's avatar

Oh My 2018

Summary

変わる世界、 変わらない私。

Moments

2 第一次在国外过年,跨年的时候正好在面 Tumblr

3 和郑老板的自由女神像之旅

3 HackNYU First Prize

3 Frank 走了

4 和腾壕、岛娘的日本 LongHash Hackathon

5 买了吉他

5 西海岸旅行

6 开始在 Tumblr 写 iOS

7 Miku Expo 2018

8 搬家

9 换了纽约州驾照

9 秋招开始

10 第一封 Offer,来自 GrubHub

11 Chara Expo USA

11 决定当一名 Googler 了

12 决战 C95(三日)

Input & Output

+ Sony RX100 VI

- iPhone 7 Plus (Jet Black)

+ iPad Pro 12.9-inch (Space Gray)

- iPad Pro 10.5-inch (Silver)

+ Sony WH-1000XM3 (Gray Silver)

- Sony MDR-1000X (Gray Silver)

Numbers

  • 9,567 photos
  • 0 posts (?)
  • 2,853 twitter followers
  • 760 instagram followers
  • 11 books
  • 245 contributions (only on GitHub)

Hall of Fame

The Next

  • 写完 One Clock!
  • 努力找到另一半😘(真丢人,退群吧)

PS:拖这么晚才发的原因是升级了系统 Ruby 挂了…没法生成静态网页

IceHoney Blog's avatar

亚马逊S3服务简单介绍

最近在做后端的开发,需要一些二进制数据保存在服务器云端。团队决定调查AWS的S3服务是否满足需求,所以就做了一些调查工作。不过也遇到很多坑的地方。所以记录下来,防止以后再遇到。

基本需求

需要云服务有稳定性保证,并且可以批量上传文件。可以设置上传和下载链接的有效期。

AWS试用

AWS提供免费试用,但是注册的时候需要填写信用卡信息。确实有点不安,万一不小心被收费了就不好了。

生成上传凭证

我使用的是AWS的 JavaScript SDK。使用createPresignedPost API可以创建用于上传的凭证。这个凭证是根据用户的AccessId,AccessKey和Policy策略等计算生成的,并没有和AWS服务器直接进行交互。所以不用担心这个接口和AWS直接的流量费用问题。

var params = {
  Bucket: 'bucket',
  Conditions: [
    ['starts-with', '$key', 'path/to/uploads/']
  ]
};
s3.createPresignedPost(params, function(err, data) {
  if (err) {
    console.error('Presigning post data encountered an error', err);
  } else {
    data.Fields.key = 'path/to/uploads/${filename}';
    console.log('The post data is', data);
  }
});

官方提供的例子中,可以使用starts-with的方式来指定上传文件的key必须是以什么开头的,这样就可以指定上传的文件夹。很多文件也可以使用这一个上传凭证来完成上传。

上传Policy构造

AWS提供了一个详细文档说明如何构造合法的Policy:Creating a POST Policy。例如常见的需求就是在上传的时候添加meta信息声明文件的格式或者MD5值。 Policy的Conditions数组里面可以添加["starts-with", "$x-amz-meta-md5checksum", ""]。最后一个参数为空字符串代表可以上传任何数值。

构造POST表单

AWS也有文档说明了如何构造一个上传的表单。这个表单中最重要的是一句注释:The elements after this will be ignored。在file字段之后的所有信息都会被忽略掉,我测试的时候一直把x-amz-meta-md5checksum字段放在file字段之后导致上传一直报错。直到Stack Overflow上面有人解释了才恍然大悟。

构造下载链接

我们使用getSignedUrl API来生成下载链接,下载链接也是根据自己的AccessId和AccessKey生成链接的凭证,也没有和AWS服务器直接进行交互。当请求文件的时候,AWS再计算凭证是否有效。所以后端无需和AWS交互就可以返回客户端有效的AWS下载链接。针对需要返回实际文件的API接口,可以采用返回302的跳转链接来完成需求。示例代码如下:

var params = {Bucket: 'bucket', Key: 'key'};
var url = s3.getSignedUrl('getObject', params);
console.log('The URL is', url);

可能有人会问,这个API也可以用来上传啊。但是这个API接口必须指定key值,这样我们就需要为每个文件来生成一个独立的上传URL。这样太麻烦了。

总结

我们使用pre-sign的方式来生成URL主要是为了对客户端透明。虽然我们可以设置最小权限的IAM User给客户端,但是客户端很容易被逆向拿到敏感数据。这样难免会有风险,所以生成一个单纯的URL供客户端使用一定程度上保证了安全性也减少了客户端的复杂性。毕竟我也不想引入一个AWS的SDK进来。

's avatar

Transmission WebUI 批量添加磁链

抓到一堆磁链,手动加入下载很麻烦… 于是做了个简单的脚本。

(() => {

async function request (object) {
  return new Promise((resolve, reject) => {
    transmission.remote.sendRequest(object, resolve);
  });
}

async function addMagnets(urls) {
  for(let i = 0; i < urls.length; i++) {
    const url = urls[i];

    console.info('add %d/%d: %O', i + 1, urls.length, await request({
      method: 'torrent-add',
      arguments: {
        'paused': false,
        'download-dir': $("#download-dir").val(),
        'filename': url
      }
    }));
  }
}

addMagnets(`
此处填入地址,一行一个 (填入时删除此行)
`.split('\n').map(n => n.trim()).filter(n => n));

})()
's avatar

从 HMV 英国站导出 CD 音轨信息

买了张 EAC 读不出自动填写信息的音乐光盘(freedb 服务),只好自己去网上抓一下音轨的信息。

HMV 英国 找到了整理好的表格,用脚本提取所有信息然后通过 mp3tag 批量导入。

导出脚本如下:

// HVM UK Track Info Dump Script for mp3tag by Jixun<https://jixun.moe>
// MIT License, use at your own risk.

document.body.querySelectorAll('.table--track-listing').forEach((disc, i) => {
  const pad = (n) =>  `0${n}`.slice(-2)
  const tracks = ([].map.call(disc.querySelectorAll('tr>td:first-child'), (x, i) => ({
    track: i + 1,
    name: x.nextElementSibling.textContent.trim(),
    artist: x.nextElementSibling.nextElementSibling.textContent.trim(),
  })))

  console.info('Disc %d\n%s', i + 1, tracks.map(track => `${track.artist} / ${track.name}`).join('\n'))
})

将每张光盘的导出数据另存为文本文档,然后在软件选中光盘文件,然后在菜单选择「Convert」→「Text File - Tag」,填入文本文件,以及格式填入 %artist% / %title%

点击「Preview」检查数据是否与光盘后面的曲目相对应,如果对的话就回到这个界面点击「OK」即可。

h404bi's avatar

历经数月,GitHub 章鱼猫寄来的 T 恤竟然……

Get Your Pull-Request Merged!

竟然寄到了,而且还有小惊喜。


起因是参加了由 GitHub 和 DigitalOcean 联合举办的 Hacktoberfest 2018 活动。据说已经是第五届了,活动目的就是鼓励更多的人对开源社区做出贡献,支持开源项目。在活动期间内在 GitHub 上发出并且被合并 5 次 Pull-Request,就能登记领取文化 T 恤。挺好的。

Hacktoberfest 2018

当时觉得 5 个 Pull-Request 被合并其实不难。倒是在想,这文化 T 到底能不能顺利漂洋过海来到手中。毕竟,我还有 2018 年中从宝岛台湾寄给自己的明信片到现在还是了无音讯的(悲伤)。抱着一丝希望,完成了任务填写了信息。之后就当作没有这回事不管了。

数个月后,突然收到邮政打电话过来询问是不是“茶某某”,说有份国际快件让我去自提。彼时我在上班砍需求中,一时没想起来,就纳闷我名字里没茶这个字啊,这时对面已经挂线了。缓过神来才想起可能是 Hacktoberfest 的 T 恤,就只好等下班去邮政仓库转一圈。

邮政晚上 9 点下班关门,赶着时间提前溜去了目的地拿到了包裹。

打码打码打码...

居然是从 Germany 德国寄过来的,我还以为是你大 USA 呢(图中的邮票是打码加上去的,谁会寄快件贴邮票哈哈哈),贴的满满的邮寄信息贴纸。这里有个小插曲要说下。去自提其实没有很顺利,到场后说是外国包裹,被告知要出示身份证并且不能代领。我不是代领,但是还是遇到了问题,在仓库现场根据我的身份证信息找不到包裹。我想到前面打电话叫我 “茶(Cha)某某”,才醒悟到当时填邮寄信息时,我心大填了英文名而不是姓名拼音。后面拿笔纸写了英文名才找到。被告知国家实行实名制,快件要写实名,不能只凭电话收取云云。还好最后拍了快件照片,让我签收了。工作人员要回收签收贴纸,但由于贴纸贴了太多不好撕,就让我现场剪开了包裹拿走了物品,留下了袋子。在剪开之前拍了上面那张照片。

经过这次后,觉得涉及实物相关的特别是跨国的东西,邮寄信息等资料最好还是写拼音。心大写英文还是不太行,有时候会造成麻烦。


接下来算是“开箱”。

除了 T 恤之外还有……

小惊喜就是包裹里除了一件 T 恤外,还有几张 Stickers。现场拆包裹时邮政的工作人员心细帮我拿了出来,不然我可能拿了件衣服就跑了。

整件衣服就是稍微浅色一点的酒红色。挑了最小号的,感觉刚刚好。正面一个大号 Hacktoberfest LOGO,右侧衣袖印了活动主办方的产品 LOGO,这样你穿出去就是“移动广告”啦。

DigitalOcean、GitHub 以及不认识的 Twilio。

Hacktoberfest 2018 LOGO 整件衣服所有能找到的图案 District - VERY IMPORTANT TEE

哈哈哈,我看得这个“VERY IMPORTANT TEE”的时候真的笑了。这衣服牌子起的名字真有意思。

面料产地

一半棉一半涤纶……倒是摸得出来棉量一般。产地 Honduras 洪都拉斯,拉丁美洲国家…… 所以这件衣服有飞了快一圈地球了吗?

Hacktoberfest 2018 LOGO 细节 Hacktoberfest 2018 LOGO 细节 Hacktoberfest 2018 LOGO 细节

其实可以很明显地看出来,衣服的 LOGO 印花做得是相当直接粗暴的,也有些“粗糙”吧。这种衣服,放洗衣机里拉扯几次,估计印花就烂的差不多了。所以这些文化广告 T 呢,很多情况下要么穿的话就手洗,要么就……不愿做移动广告,供起来做收藏咯哈哈哈……

Stickers

四张贴纸,分别对应 GitHub 章鱼猫、DigitalOcean 鲨鱼、Hacktoberfest LOGO 以及不认识的 Twilio。剩下那个大概是马克杯垫。贴纸是真的小惊喜了,章鱼猫挺好的。

Stickers

有 DigitalOcean 的新用户广告,还有让你收到衣服后穿上然后去 Twitter 上的 #Hacktoberfest 发推分享 2333。我在推上搜索看到有不少分享了,并且才知道除了这一款 DigitalOcean 联名的酒红色 T 恤外,还有微软款等其它款的!我觉得还更好看,有点羡慕……

来自推特用户 @tanhengyeow

看到大眼睛的回形针了吧!好赞啊。不过不管怎样,能收到还是很高兴,于是就记录下来了。有下一届的话,我应该还会参加的,嘿嘿。

Felix Yan's avatar

用脏办法解决 BLE 鼠标重连后指针不动的问题

我的蓝牙鼠标(雷柏 MT750)使用 BLE(Bluetooth Low Energy) 连接笔记本时,时常遇到自动重连后电脑这边认为已连接,而鼠标那边灯自动灭掉,鼠标指针无反应的问题。在网上反复搜索 bluez 相关问题找到了许多类似问题,鼠标类型也集中在罗技、ThinkPad 等 BLE 鼠标上。

偶然间发现每次重连后,如果手动用 bluetoothctl 发一个 “pair” 指令(会超时失败),就能令鼠标正常连接。给 bluez 报了一个 bug 后,我写了下面的简单脚本先绕过问题:

#!/usr/bin/python

import dbus
import dbus.mainloop.glib
from gi.repository import GLib

adapter = "hci0"
device = "xx:xx:xx:xx:xx:xx"
device_path = '/org/bluez/' + adapter + "/dev_" + device.replace(":", "_")

dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
system_bus = dbus.SystemBus()
device_object = system_bus.get_object('org.bluez', device_path)
device_interface = dbus.Interface(device_object, 'org.bluez.Device1')

def device_info(_arg0, event, _arg2):
    if event.get("Connected"):
        print("Mouse connected, attempt to pair...")
        try:
            device_interface.Pair()
        except dbus.exceptions.DBusException:
            pass

system_bus.add_signal_receiver(
    device_info,
    dbus_interface='org.freedesktop.DBus.Properties',
    signal_name="PropertiesChanged",
    arg0='org.bluez.Device1')

GLib.MainLoop().run()

保持在后台运行即可。我自己测试了一段时间,效果非常好。

PS: bluez 上游 bugzilla 堆满了各种没有回答的错误报告,目测不是那么好修的……

AlisterTT's avatar

2019开年的不高兴

2018年末的时候,一个朋友和我聊起去台湾玩的事,我想着挺好呗,干脆计划19年一起出去一波吧,今天和去过的同事仔细咨询了一下,把情况告诉我朋友,结果他丫的前些天已经去过了。

没办法只能另找人组队,问了一个基友倒是很乐意去,他们那边能去两对4个人,问题是我就处于一个电灯泡的状态了,他很随意的告诉我“你找个妹子不就行了”,真想抽他一大嘴巴子,感觉就像我傻呵呵的开了个团,结果因为自己单身的原因被踢出来了,头一次体会到了单身狗的绝望,比那种一个人去吃自助餐还凄惨,真不是开玩笑的,当时简直丧到极点。

现在的情况是,今年要想出去玩,还得先找个独立的队友才行,一个人出远门肯定会有诸多不方便,想想就头大呀,谁来教教我怎么办…

依云's avatar

解析 zxinc IPv6 数据库

本文来自依云's Blog,转载请注明。

很久以前,我就开始使用纯真 IP 数据库来进行简单的 IP 归属查询。离线数据库的好处在于快速、可依赖,我可以使用 ipmarkup 程序来快速地给文本中的所有 IP 地址注解。

然后随着 IPv6 的普及,我越来越多地需要查询 IPv6 地址了。每次 whois 或者找 ipip.net 实在是太没效率了,还暴露隐私。于是看到这个IP地址查询网站提供离线数据库下载之后,就也做了一个和 LinuxToy 介绍的这个程序类似的工具。

数据格式部分参考《纯真IP数据库格式详解》以及该网站自带的简略说明。

ipdb 程序库(带命令行)使用截图:

用于在文本中标注 IP 的 ipmarkup 工具链接开头给了。另外有一个 cip 可以根据情况调用 ipdb 或者 QQWry。

ipdb 解析部分只依赖 Python 3.5+,下载及更新部分会依赖我同一仓库中的 myutils 库。

顺便我也优化了一下 QQWry 模块:一是没必要保留一个低效率的版本,二是既然用 mmap 了,就去掉了所有的 seek 操作,目前大概是线程安全的了。这种跳转来跳转去的二进制格式,就算不用 mmap,也可以用 pread 来操作,免得要维护个当前文件位置,还线程不安全。

lwl12's avatar

Bye 2018, Hi 2019

L2019, runway 18R, clear for take off.


SgDylan's avatar

2018 年终总结

还有三天,2018 就要从指缝流走了。
是时候总结一下了。


's avatar

以此纪念逝去的圣诞节

纵使有千言万语欲与诉说,坐到电脑面前便一个字也不想打。

放一个 Ujico*/Snail’s House 前几天的曲子吧。Magical Holiday。因为暂时上不了 SoundCloud,就放 Youtube 上的视频吧,也很漂亮。

另外,在点 Profile 的时候请戴上耳机。

别的留给新年再说吧。

依云's avatar

Ant Design 彩蛋事件之我见

本文来自依云's Blog,转载请注明。

事情是这样的:一个叫「Ant Design」的大概有挺多人用的前端框架加入了一个彩蛋,在12月25日这天会更改按钮样式并修改提示文字为无意义的消息。

由于使用广泛,此事搞得比较严重,听说有程序员因此被开除,还有不少老板在跟甲方解释。事发之后,作者发布了道歉,并称「这完全是我个人的一意孤行且愚蠢的决定」。

确实很愚蠢,因为当事人似乎还没有意识到自己为什么「愚蠢」。在程序库中加入未预期的行为,是十分不负责任的表现。

库应当提供机制而非策略,并且具有良好定义的行为。软件中彩蛋这种东西由来已久,为什么这次影响这么大呢?其根本原因不在于它是开源软件,也不在于使用广泛,而是在于——它是库。库能不能提供彩蛋呢?是可以的,只要它是以 opt-in 的形式提供的,并且有文档明确其行为,使用方需要显式启用就没有任何问题。库的作者不需要知道圣诞节还可能在1月,也不需要知道代码是运行在哪个国家,他的职责应当是提供清晰明确的行为,而不是某天给你耍个花招。只有最终面向用户的应用才知道什么样的彩蛋对于它的用户是合适的,所以决定权在于应用。

至于那些在 issue 下边滥骂的人,真是给中国人丢脸唉。

PS: 关于「洋节」,shell909090 有篇文章《关于抵制洋节》。关于阿里巴巴,shell909090 还有篇《最近的阿里月饼事件》。

PPS: 每当国外发生这种令程序员们关注的事件的时候,Internet ArchiveArchive.is 上都有会很多的存档来保留历史,而国内发生这种事件,却并没有多少人去存档。大概有保存意思的人们也只是自私地本地截图保存了吧。

SgDylan's avatar

简易 FM 电台搭建

发霉派发射 FM 最简单的方法是从 GitHub 找个相关的 repo 然后装上。
但是那样音质太菜了,所以有了本文。

farseerfc's avatar

【聽譯】君さえいなけりゃよかった

君さえいなけりゃよかった 如果你從未出現過該多好
降り出した雨の中で 君に出会った時から 下起雨的那一刻 從遇到你那時起
君がいないということが 当たり前じゃなくなった 身邊沒有你的情況 就已經不再是平常
ああ こんなはずじゃない 啊 不應該是這樣的
ずっと自分勝手にさ 過ごせたはずなのに 明明一直是散漫地過着自己的日子
まるで僕じゃないような僕が さらけ出されてくよ 就像是帶出了不是我的另一面的我

君さえいなけりゃよかった こんな気持ちは知らないから 如果你從未出現過該多好 就不會知道這種心情
やらなくちゃいけないことが 手つかずのまま積もってく 一堆不得不做的事情 堆在手頭越積越多
僕じゃなくてもいいのなら こっちを見て笑わないでよ 如果不是我也可以的話 就別看着我這邊笑啊
大袈裟じゃなくてそれだけで 忘れられなくなるの 甚至那些不重要的事情 都變得難以忘記了

君の適当な話も 全部心に刺さります 你無意間隨口說的話 全都刺在心頭
気にしなけりゃいいのにな 残らずかき集めちゃうの 雖說只要不在意就可以了 卻一句不剩全收集了起來
ああ こんなはずじゃない こんなはずじゃない 啊 不應該是這樣的 不應該是這樣的

君に出会わなきゃよかった こんなに寂しくなるのなら 如果沒遇到過你該多好 就不會變得如此寂寞
君じゃなくてもいいことが もう見つからないの 已經找不到 和你無關也可以的情況了
忘れられないから 君じゃなかったら 無法忘記了 要不是你的話

いっそ見損なってしまうような そんなひとだったらなあ 乾脆變成根本看不起的人 如果是那種人的話
でもそれでも どうせ無理そう 嫌いになれないや 但是即使如此 大概反正也不可能 無法變得討厭

僕がいなくてもいいなら いっそ不幸になってしまえ 如果不是我也可以的話 乾脆變得不幸吧
最後にまた僕の元に 泣きついてくればいい 最後還是會回到我身邊 哭着湊過來的話就可以
君さえいなけりゃよかった こんな気持ちは知らないから 如果沒有你該多好 就不會知道這種心情
やらなくちゃいけないことが 手つかずのまま積もってく 一堆不得不做的事情 堆在手頭越積越多
僕じゃなくてもいいのなら こっちを見て笑わないでよ 如果不是我也可以的話 就別看着我這邊笑啊
大袈裟じゃなくてそれだけで 甚至那些不重要的事情
君のこと 間違いなく 對你 毫無疑問
苦しいほど 好きになっちゃうよ 刻骨銘心地 變得喜歡上了啊

忘れられないから 君じゃなかったら 因爲無法忘記 如果不是你的話
君に出会わなきゃ 僕じゃなかったら 要是沒遇到過你 如果不是我的話
君さえいなけりゃよかった 如果你從未出現過該多好
h404bi's avatar

我都在用些什么 Chrome 扩展程序

想不到在 Microsoft Edge 正式发布后的第三年,微软官方宣布了 Edge 将放弃自家的内核引擎,转而去拥抱在当前浏览器生态中占据统治地位的 Google Chromium。继 Opera 之后,“Chromium 家族”又将迎来新的成员。这无疑是一个重磅消息,对于用户而言,对于微软自己而言,带来的影响都是巨大的。
Phoenix Nemo's avatar

制作 Arch Linux 内存系统启动盘

之前尝试过 Arch Linux in RAM 完全运行在内存中的轻量业务系统,最近在维护一些物理服务器看到没有安装系统的服务器不断重启,想到了可以制作类似的内存系统启动盘,以高效完成系统测试、安装、远程维护等任务。

这时候就要祭出 mkarchiso 大法了。这是自动化制作最新版 Arch Live 镜像的工具集,当然也可用于制作定制化的 Arch 镜像。

准备

首先安装 archiso

1
~> sudo pacman -Syy archiso

它提供了两种配置方案,一种是只包含基本系统的 baseline,一种是可以制作定制 ISO 的 releng。要制作维护用 ISO,当然是复制 releng 配置啦。

1
2
~> cp -r /usr/share/archiso/configs/releng/ archlive
~> cd archlive

定制

整个过程不要太简单。先来了解下各个文件的用途:

  • build.sh - 用于制作镜像的自动化脚本,可以在这里修改一些名称变量或制作过程的逻辑。
  • packages.x86_64 - 一份要安装的包列表,一行一个。
  • pacman.conf - pacman 的配置文件,不用多说了吧。
  • airootfs - Live 系统的 rootfs,除了安装的包之外,其他的定制(以及启动执行脚本等)都在这里。遵循 rootfs 的目录规则。
  • efiboot / syslinux / isolinux 用于设置 BIOS / EFI 启动的配置。

[archlinuxcn] 仓库加入 pacman.conf

1
2
[archlinuxcn]
Server = https://cdn.repo.archlinuxcn.org/$arch

然后修改 packages.x86_64,加入 archlinuxcn-keyring 和其他需要预安装的包:

1
2
3
4
5
archlinuxcn-keyring
htop
iftop
iotop
ipmitool

按需修改即可啦。

要启动为内存系统,需要加启动参数 copytoram

修改文件 syslinux/archiso_pxe.cfgsyslinux/archiso_sys.cfg 文件,在启动参数后加 copytoram,像这样:

1
2
3
4
5
6
7
8
9
10
11
INCLUDE boot/syslinux/archiso_head.cfg

LABEL arch64
TEXT HELP
Boot the Arch Linux (x86_64) live medium.
It allows you to install Arch Linux or perform system maintenance.
ENDTEXT
MENU LABEL Boot Arch Linux (x86_64)
LINUX boot/x86_64/vmlinuz
INITRD boot/intel_ucode.img,boot/amd_ucode.img,boot/x86_64/archiso.img
APPEND archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL% copytoram

启动时即可将整个 SquashFS 文件复制到内存。如果内存比较小,也可以指定 copytoram_size 来限制 tmpfs 占用内存的最大数量。

同样,也需要修改 efiboot/loader/entries/archiso-x86_64-usb.conf 的启动参数。在 options 行添加

1
options archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL% copytoram

制作

创建工作目录和输出目录

1
mkdir -p work out

最后一步,只需要以 root 权限执行 ./build.sh 就可以啦。

要看具体执行过程的话,加 -v-h 看所有参数。

完成后,即可在 out 目录得到准备好的 ISO 文件。将其 dd 到 USB 闪存盘,大功告成(‘・ω・’)

Ref:

  1. https://wiki.archlinux.org/index.php/Archiso
  2. https://git.archlinux.org/archiso.git/tree/docs/README.bootparams#n53
's avatar

感到烦躁?先休息一会吧

Stuck? Switch to “Play Mode” 有感。

摘抄:

... Instead of trying to get things right, I should put myself in “Play Mode”. From his email:

In “Play,” just write or work on something you want... At the end, if you like what you’ve done, bring it in... If you don’t, discard it... It’s okay if nothing comes from it.

粗翻:

与其烦躁的逼着自己去做某些事情(如工作时卡住),不如先撒会欢 —— 随便写、玩或者休息一会(比如一个小时);如果撒欢时做的事情无关的话,就先放到一边。

即使做的事情无关,但是心情却会因此好起来,能够继续专注于工作。

farseerfc's avatar

【譯】使用 GNU stow 管理你的點文件

譯註

這篇是翻譯自 Brandon Invergo 的博客的英文文章 Using GNU Stow to manage your dotfiles 。 Brandon Invergo 的博客採用 CC-BY-SA 3.0 授權,因此本文也同樣採用 CC-BY-SA 3.0 ,不同於其它我寫的文章是 CC-BY-NC-SA 4.0 授權。

我自己已經使用此文中介紹的方案管理 我自己的 dotfiles 快 3 年了。最早想採用這樣的管理方案是爲了方便在多臺 Arch Linux 系統之間同步配置, 後來逐漸主力系統也更新換代了一次,又同步到了自己的 vps 上去,目前管理多個 Arch Linux 上都多少都有這套配置。甚至裝好 Arch Linux 添加好用戶最初做的事情就是安裝 …

17windy's avatar

[美羽释厄录] 0.95 发布贴 性能和游戏性大优化 12.07.2018更新

12月7日21点15分前下载的小伙伴拜托重新下载下,解决了一个蛙人关卡浣熊叶子无效的bug。

0.95更新日志:

1,感谢美羽和咲冥两位大佬的倾力支持,美羽和灵梦(卷)有了新形象,其中灵梦(卷)的形象由美羽进行了精确描述

2,伤害系统整个重构,优化性能至少50%,消灭卡顿!

3,载入功能升级,加载关卡更快更快更快

4,修改美羽的移动控制,改为弹幕类游戏通用的RAW方式,即按下移动键不会有加减速的缓冲和惯性,直接固定每次的移动距离,改善游戏体验

5,每个BOSS都有了特殊的弹幕风格,蛙人和大X王BOSS战重做,更有挑战性和观赏性

6,BOSS战胜利后会全屏消弹避免喜闻乐见

7,部分关卡的小怪会有偶尔的上下刷新

8,通常关卡整体难度下降,便于刷钱

9,美羽的特殊武器蓄能速度增加了50%

10,灵梦(卷)提供了增益!增加了30%-50%的资金获取量(视不同关卡)

11,部分武器进行了小改动,斩龙剑改造

12,战斗魔偶特殊道具更改为浣熊的叶子

13,修正了某个会导致美羽无敌的BUG

14,修正了英雄愿望有时只会造成一次伤害的BUG

15,修正了修改音量后部分关卡失效的BUG

16,灵梦(卷)商店增加了商品的描述提示,鼠标移到商品上显示

17,主菜单美化

新DLC关卡BOSS征集!请想要暴打美羽/被美羽暴打的碰友至喵窝社区论坛报名哦!

 

目前暂时只提供windows版,还望谅解。

下载链接:

0.95版本地下载

下载 Miu DB V0.95
点击次数: 152, 文件大小: 267.2 MB, 日期: 2018 12月 07

0.95版百度云分流 链接:https://pan.baidu.com/s/1ofJR7Ue4d_YGKgYiXOytAw 提取码:o19f

 

PS:之后可能会有一个月-一个半月的时间暂停更新,忙主要项目,不然会被卷素质三连~

SgDylan's avatar

EmiyaEngine 杂谈录 「其一」

人耳是一对既简单又复杂的器官。
说它简单,是因为人类可以制造电子的替代品;说它复杂,是因为再好的替代品都不能完全还原其功能。
它的原理,简单说只是将声音的机械波转换为神经电信号,但实际上这是包括耳廓、耳洞甚至是表皮绒毛的系统工程。
这些部件通过发挥其物理结构的作用对外界声音进行加工,才有了人体感知声音的前提。
再往后,大脑通过对其进行一系列解构调味,才有了最终感受到的样子。
现在的我们,将这一些系列的调味成为「心理声学」。

SgDylan's avatar

尝试在HEXO内嵌歌曲

SgDylan's avatar

如何为UWP应用开启回环访问权限

SgDylan's avatar

在 Android 设备体验 Hi-Fi

最近搞了个 XMOS 做 USB 驱动芯片,配合 ESS-9018 做 DAC 的 USB DAC。
具体型号就不说了,用的是 XMOS 官方的参考方案。

SgDylan's avatar

修复Windows10上因为MacType导致的蓝屏问题

SgDylan's avatar

Tinc 笔记

Tinc 是一个 MeshVPN 网络的实现。
以下是这玩意的踩坑记录。

SgDylan's avatar

在视频处理中使用SVP4

SVP 是一个不错的视频插帧工具,可以通过详尽的参数设定处理出适合自己的高帧率视频。
目前,SVP 的主要版本是 SVP4。
本次主要记录的是使用 SVP4 配合视频压制工具制作高帧率视频的过程。

SgDylan's avatar

EmiyaEngine 杂谈录 「其二」

上一篇中谈到了心理声学与人造玄学,其中为说明采样虚拟乐器的不完全「HiRes」,
拿了两首所谓的「HiRes」音乐做了可视化谱分析,说到了一些可能不太正确的推论。
本篇继续推进,站到技术层面窥视他们背后的原理。

SgDylan's avatar

使用Python脚本计算单片机纯软件延时计数值

编写单片机程序时,经常为了保证时序使用软件延时程序。
以下是一种精确计算软件延时的方法(强迫症福音)。

SgDylan's avatar

饥荒 Don't Starve Together 服务器安装记录

这是一份饥荒联机服务器搭建记录的流水账。
记录的是在 单核 1GB内存 1Mbps 安装有Ubuntu14.04 的 腾讯云学生机上安装饥荒联机版的过程。
安装中包括了主世界和洞穴世界,且有安装人物Mod和工具Mod。
需要注意的是,这份安装记录适用于 Steam 最新正版饥荒。TGP 版似乎并不支持。

SgDylan's avatar

一种批量下载Bilibili视频的方法

需要的环境及工具:

  1. 一台可以运行 Python3 的机器
  2. Python 3 ( 推荐 Python 3.5.1 )
  3. pip
  4. you-get
SgDylan's avatar

使用手机远程控制 PC 网易云音乐

折腾过 Foobar2000 的人可能知道,Foobar2000 有一款叫做 foo_httpcontrol 的远程控制插件。
同时,有爱好者根据这个插件提供的接口,写出了使用手机控制 Foobar2000 的 Android 应用程序
于是,做一个远程控制网易云音乐程序的想法就诞生了。
考虑到自己一时半会写不出像 foobar2000 controller 这样的 Android 应用程序,于是考虑借用这一套 API 格式实现一个兼容的控制服务端。

SgDylan's avatar

导出 nginx 自动目录的链接到 aria2

不多说废话,就是一个 Javascript 插件,实现的功能如标题所说。
在 tampermonkey 上运行正常,暂时没有发现 BUG。
用不惯 rsync 的可以试试用这个用从 seedbox 拖文件。

SgDylan's avatar

一种阻碍DPI检测上网设备数量的方法

背景
学校最近把三家运营商都并入校园网了,使用一套名为深澜的系统对绑定不同运营商的用户自动加载不同的路由实现网络流量走不同的 ISP 出口。同时,大概是为了更大地盈利,加入了 DPI 和缓存服务器,并同时屏蔽了外部网络的 53 端口。
至此,接入校园网的用户无法使用默认使用 53 端口的 DNS(TCP/UDP),同时只允许接入三台上网设备。

SgDylan's avatar

使用 ESP8266 搭建 IoT 节点

刚好要买 ARM 板子,就顺手一并买了一块传说中的廉价 WiFi 开发板——使用 ESP8266 的 NodeMCU 。
那么就来说说这块据说性能强大、价格低廉,且可以写脚本语言的开发板。

SgDylan's avatar

Roland MIDI 软件合成器安装记录

这是一篇记录软件 MIDI 合成器安装的流水账,如有错误请及时指出。

SgDylan's avatar

在 PotPlayer 中使用 VapourSynth 加载 SVP4

SVP 是很棒的视频插帧软件。SVP 看片爽过吸大麻(大雾)
但是一直以来这东西都是通过 ffdshow raw filter 加载 AviSynth 脚本的方式介入播放器作用的。
从某个版本开始,SVP4 开始支持 VapourSynth 加载,
但是官方的教程还没有跟进,所以就稍微说一下吧。
需要注意的是,这个功能需要 SVP4 Pro,使用 Free 版本的用户请买一份 Pro 先。
顺便,感谢字幕组压片dalao @hoshinokun 的帮助。

's avatar

法国服务器将在一月迁移 终止部分服务

法国服务器准备不再续约了。

考虑到十二月没有时间来迁移网站,暂时决定将服务器续期到 2019 年 1 月 31 日。

届时受影响的服务:

  • 网易云音乐反代 - 关闭服务

其他服务会在一月中旬无缝迁移到新的服务器,不受影响。

AprocySanae's avatar

谁在里面

这篇文章完全是虚构的,比如我几乎晚上不加班,也没有会 JOJO 立的同事。毫无疑问我看过冰菓小说,当然日常系推理也并非冰菓的专利。

我的确寻思过写个和千反田类似的女孩放入书中,以读者的身份引出线索。但是构思时候很悲伤地发现我并不熟悉女性的思考方式。

文辞相当市侩,但是毫无疑问这才是我熟悉的生活。

's avatar

Redis Desktop Manager (RDM) 0.9.999 x64 个人编译版

官方的 Windows/Mac 构建版本需要订阅或做出贡献才能下载,否则只能自己编译。

用 QT 折腾大半天后终于编译好了。

已知问题

  1. 无法切换语言。原因未知,有懂 QT 的大佬指点一下吗?

说明

因为使用的是 VS2017 x64 编译器,需要 Win7+ x64 操作系统。

VS 2017 运行时下载:微软

RDM 下载

IceHoney Blog's avatar

前端开发地图应用的调研

我司的产品终于发布了新版本,所以忙碌的开发暂时告一段落。最近在做下一期的规划,然后就是要做前端网站来满足用户的需求。由于我们的产品是和地图强相关的,所以也对地图做了很多调研。

基本需求

产品需要在国内和国外使用,费用合理,可以换地图的贴图并且能在地图上绘制各种信息。例如多边形或圆形还有贝塞尔曲线。

MapKit JS

苹果居然也出了网页版本的地图产品MapKit JS,可谓是良心。但是目前还处于Beta版本。如果以后要考虑产品的全平台化,显然不是一个很好的选择。不过苹果的产品可以在国内国外使用不用太担心地图偏移问题,而且可以贴图和绘制图形,但是目前网页版还不能绘制贝塞尔曲线,iOS客户端倒是可以。

MapBox

MapBox是一个地图服务提供商,经过调研MapBox使用最新的WebGL技术来渲染,摆脱了传统的下tile来贴图的方式,渲染速度得到了大大的提升。也能解决国内和国外的地图显示问题,但是画图功能就只有画线和多边形。不过提供了底层的画图层的接口,需要自己写WebGL的shader。这就增加了开发成本。。。

GoogleMap

谷歌地图当然好,但是我最后才说。因为谷歌无法在国内使用,这种情况下我就不得不写两套接口来对应,例如国内高德地图,国外谷歌地图,会大大增加开发成本。而且谷歌地图最近刚升级付费条款,费用是按照请求次数来收,所以用户大量增长之后的开销也会非常大。不过谷歌也不能画贝塞尔曲线。。。

地理坐标系

由于是需要在地图上绘制新的tiles,所以自然就涉及到坐标的转换和计算。如何计算一个经纬度落在哪一张tiles上,以及在不同缩放级别下tiles的正常显示和重绘。这些都是需要自己来实现的。 这里有一个还算有名的官方介绍,并给出了Python的源码。可以参考这个来进行实现。

坐标系转换

每个国家都有自己的坐标系系统,虽然GPS使用的WGS 84标准非常流行,但是这个是美国制定的。每个国家当然都需要根据自己国家需要来定制自己的标准。例如中国就有北京54坐标系,西安80坐标系。北京54和西安80是参心坐标系,大地原点分别在苏联和西安。难以表达高度信息,目前国家正在推广2000国家大地坐标系,这个和WGS84一样是地心坐标系,即以地球质量中心为原点。日本也有自己的平面直角坐标系,我们当然需要各种坐标转换,还好有现成的开源项目proj4js

总结

各个地图服务商都各有优劣,但却没有一款完美的。主要是用途也比较特殊,可能在地图服务上进行二次开发的可能性比较高吧。不过提供地图服务的也没几家可以选择的。。。

's avatar

网站部分功能下线 [已恢复]

VPS 因未知原因下线,问题还在排查中。

部分服务器的内容受到影响,包括:

  • 英文博客 (jixun.uk)
  • 评论系统 (c.jixun.moe)
  • 本站的静态资源 (s1.jixun.moe)
  • 托管于本站的资源 (jixun.downloaddl.jixun.moe)
  • 网易云音乐反代服务
  • … 以及其他个人用的子域名服务。

已经修复,根据 Uptime Robot 提供的数据,本次事件导致服务器下线总计 2 小时 25 分。

依云's avatar

通过 Cloudflare DNS 验证来申请 Let's Encrypt 证书

本文来自依云's Blog,转载请注明。

我本地的 MediaWiki 的证书过期啦,干脆申请个免费证书好了。之所以用 HTTPS,是因为 MediaWiki 不喜欢不加密的 HTTP,会登录不了……

在网上寻找时,发现 certbot 就有 Cloudflare 的插件呢!这下就方便了。首先 pacman -S certbot-dns-cloudflare 装上,然后把自己的 Cloudflare 凭证信息写到一个 ini 文件里:

dns_cloudflare_email = cloudflare@example.com
dns_cloudflare_api_key = 0123456789abcdef0123456789abcdef01234567

就这么两行。保存好,设置好权限,然后就可以申请证书了:

sudo certbot certonly -d 域名列表 --dns-cloudflare --dns-cloudflare-credentials 凭证ini文件路径

稍微回答几个问题,证书就在 /etc/letsencrypt/live 下准备好啦。在 nginx 里配置一下就好了。

然后还要加个 cron 任务来更新证书(dcron 格式):

@weekly         ID=cert-renew   certbot renew -q

这样就大功告成了。

依云's avatar

正确地上传至 PyPI 并展示文档

本文来自依云's Blog,转载请注明。

数年过去了,今天经过多次尝试和询问,我终于成功让 nvchecker 的文档以富文件的形式展示在 PyPI 上了!

正确地打包上传命令是这样的:

rm -rf dist && python setup.py sdist && twine check dist/* && twine upload -s dist/*

如果 twine check 不通过,那么修正后重新执行。如果文档包含错误,PyPI 会以纯文本形式展示。

  • 听说要设置 long_description_content_type。好像 Markdown 才要设置的,rst 不用。
  • 听说不支持 # 开头的链接。实际上现在已经支持了。
  • 听说要用 twine,那就用吧。

原来我之前的文档一直没有正确地渲染,是因为有一个标题的「-」少了两个……

关于 PyPI 的资料是挺多的,但是细节不够详细,陈旧信息很多,唉。

Phoenix Nemo's avatar

使用 fs.WriteStream 编写超简单的日志流

虽然 console.log 很好用,但是生产环境需要保存日志的时候就比较蛋疼。暴力 fs.appendFile 会消耗大量的 file handler,因此用 writable stream 来复用 file handler 是更好的选择。

大概是个不能再简单的思路了。先创建一个写入流

1
2
3
const fs = require('fs');

let logStream = fs.createWriteStream('./test.log');

这样便创建了一个文件写入口,需要时直接调用 logStream.write 即可写入数据。
接下来编写一个用于记录日志的函数替代 console.log

1
2
3
function logger (message) {
logStream.write(message);
}

至此基本功能就写完啦。但是太简陋了对不对,还是要再加点装饰。

重写 logger 函数,区分 stdoutstderr

1
2
3
4
5
6
7
8
9
10
11
12
let logInfo = fs.createWriteStream('./stdout.log');
let logError = fs.createWriteStream('./stderr.log');

let Logger = {};

Logger.info = (message) => {
logInfo.write('[INFO] ' + message);
}

Logger.error = (message) => {
logError.write('[ERROR] ' + message);
}

感觉还是少了点什么…日期?

1
2
3
Logger.info = (message) => {
logInfo.write(new Date().toISOString() + ' [INFO] ' + message + '\n');
}

嗯嗯。这就像样了。把代码整合起来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const fs = require('fs');

let logInfo = fs.createWriteStream('./stdout.log');
let logError = fs.createWiteStream('./stderr.log');

let Logger = {};

Logger.info = (message) => {
logInfo.write(new Date().toISOString() + ' [INFO] ' + message + '\n');
}
Logger.error = (message) => {
logError.write(new Date().toISOString() + ' [ERROR] ' + message + '\n');
}

module.exports = Logger;

需要用时

1
Logger.info('This is an information.');

现在看对应的 stdout.log 文件就有相应内容啦。

1
2
~> tail -f stdout.log
2018-11-18T10:52:57.333Z [INFO] This is an information.

不够刺激?

1
2
3
[...Array(10000)].forEach((item, index) => {
Logger.info('Hello! ' + index);
});
1
2
3
4
5
6
7
8
9
10
11
12
~> tail -f stdout.log
...
2018-11-18T10:58:30.661Z [INFO] Hello! 9990
2018-11-18T10:58:30.661Z [INFO] Hello! 9991
2018-11-18T10:58:30.661Z [INFO] Hello! 9992
2018-11-18T10:58:30.661Z [INFO] Hello! 9993
2018-11-18T10:58:30.661Z [INFO] Hello! 9994
2018-11-18T10:58:30.661Z [INFO] Hello! 9995
2018-11-18T10:58:30.661Z [INFO] Hello! 9996
2018-11-18T10:58:30.661Z [INFO] Hello! 9997
2018-11-18T10:58:30.661Z [INFO] Hello! 9998
2018-11-18T10:58:30.661Z [INFO] Hello! 9999

搞定(┌・ω・)┌超简单的吧。

's avatar

十一月十七日 -- 前女友小说,字体,摄影

今天没打游戏。

小说

磨了一点 Your Diary 的感想,就没动了,买了另外一本三秋的书,加上一本书凑免邮。反而是看纸城境介的继母的拖油瓶是前女友看到快 6 点。

很有趣的小说。男性向的。

因为看轻小说不用带脑子,所以这也是不带脑子的评论。这也是我的一种心理安慰。一个人如果因为一本无趣的小说而熬夜,那未免也太空虚了吧。

在访谈中,关于连载,作者纸城大致是这么说的:如果小说被印刷成书出版,那只能让读者享受 3 小时;而如果放在网络上连载,则能够让读者每周都享受 168 小时。

关于这部书有趣的地方,作者大致是这么说的:我写这部作品,就专注于这一点,而不是加入学园祭等各种元素来充实内容,这使得这部作品非常纯粹。

因为我记的不太清楚了,所以就不加 quote 了。当然这也不代表我个人观点,虽然说人会把记忆改造成自己想要的样子,但我觉得这观点怎样都好,所以就忘的差不多了,更别说根据自己的好恶改造了。

我个人觉得误会是这部作品的一个支撑,也是全篇反复出现的一个要素。男女主人公因为小小的误会,关系出现了隔阂,导致最终的分手。男主自认为讨厌女主,但心里还给女主留着位置,他并努力和女主保持着适当的距离;而反观女主,男主在面前的时候针锋相对,不在面前的时候变身大花痴。导致怎么看,都是变相秀恩爱。

这让我想起了作品时间和现实时间同步的一部网络小说,其天气也是忠实于日本某地的天气。可名字忘了。

今天下雨。

看了一点人间失格,感觉不能理解。先不管三张相片是想表达什么(从内容上看推测是概括了主角的一生),几页看下来,大致是一位神经性厌食症少年的独白。具体是不是还要继续往下看。

摄影

我不摄影。

看了一篇关于 Magnum Contact Sheets 的博客,讲的很长很详细,地址忘了。

Contact sheets 是在底片时代,摄影师为了降低成本,就先把底片的缩小版印下来,再在其中挑选想要的照片。从 contact sheets 中可以看到摄影师的思考,过程,以及失败。Magnum 是有名的摄影师社区,其成员都是经过遴选的,因此这本书里的 contact sheets 也可算是大师级别的作品。

看到 Dali Atomicus 的时候,我以为里面的人是随便一个演员,结果一查是达利本人,而其创意也来自达利的画 Leda Atomica,里面的物体都是漂浮着的,在照片中该画被悬在右侧。照片里的猫也是真的,是助手丢出去的。大概那时候没有动物保护组织,可以随便来。照片一共拍了28次,可以说不管是摄影师,达利,打扫的人,还是猫都辛苦了,猫还会被水浇到,所以可能最辛苦。

总而言之,文章想对广大摄影爱好者表达的几点建议,一个是多拍,一个是拍了要看,一个是以前拍的也要看,说不定会有新的发现(因此不要立即删掉觉得不好的照片)。

字体

方正面向移动端阅读,推出了方正悠宋。当然要钱,而且不能发布。因此我没用。当然如果遇到什么好的免费的衬线体,大概是会换的,不然英文是衬线,中文是黑体,不免有些不协调。

注:移动端是这样,电脑端可能不是这样。

Hymmnos 字体也会加回来的,大概。

其他的记不清了。

想不到要写什么了。

's avatar

Fedora 29 安装 FCITX 输入法 + Rime/拼音

上图为安装后的效果


首先安装适配各种程序的基础包:

sudo dnf install fcitx-{ui-light,qt{4,5},table,gtk{2,3},table-{extra,other,chinese},configtool}

安装「中州韵」:

# 启用 fzug - 中文社区源
sudo dnf install https://mirrors.tuna.tsinghua.edu.cn/fzug/free/29/x86_64/fzug-release-29-0.1.noarch.rpm

# 关掉 fzug 的 non-free(非自由软件) 源,因为这个源并不存在
sudo sed -i.bak 's/enabled=1/enabled=0/' /etc/yum.repos.d/fzug-nonfree.repo

# 安装中州韵
sudo dnf install fcitx-rime

如果不想安装 fzug 中文社区源,可以安装普通的拼音:

sudo dnf install fcitx-pinyin

之后运行「im-chooser」在弹出的界面选择 fcitx,然后登出重新登录即可生效。

's avatar

100% 橙汁修改器更新 (4.0)

更新 4.0

很久没有更新这个修改器了…原因是对修改器进行了重做,现在改用 C++ 开发,抛弃掉 .net 环境。

支持联网获取修改器所需数据,希望能解决每个版本的游戏都需要重新编译修改器的问题。

缺点:

  1. 不支持离线使用。每次点击“寻找游戏”都需要联网查询所需数据,可能在后续版本会建立一个缓存机制。
  2. 不支持 XP,也希望我能不需要支持 XP。如果真的需要 XP 的支持的话,请在留言告诉我,我会更新编译器使其兼容。

以后如果不是游戏有大更新,修改器应该也不用更新。

100% Orange Juice 修改器

Felix Yan's avatar

为 glibc localedata 添加民国纪年支持

昨天被 @聞其詳 问起 glibc 对日本平成XX年的纪年支持情况(感谢 @farseerfc 老师),发现 glibc localedata 中并未包括民国纪年支持。在查询文档后稍微鼓捣了一下,简单实现了这个功能:

$ LC_TIME=zh_TW.UTF-8 date +%EY
民國107年
$ LC_TIME=zh_TW.UTF-8 date +%EY --date="1912/4/3"
民國元年
$ LC_TIME=zh_TW.UTF-8 date +%EY --date="1913/4/3"
民國2年
$ LC_TIME=zh_TW.UTF-8 date +%EY --date="1911/4/3"
民前1年
$ LC_TIME=zh_TW.UTF-8 date +%EY --date="1900/4/3"
民前12年

修改方法:

编辑 /usr/share/i18n/locales/zh_TW 文件,找到 END LC_TIME,在它之前加入这样三行:

era "+:2:1913//01//01:+*:民國:%EC%Ey年";/
    "+:1:1912//01//01:1912//12//31:民國:%EC元年";/
    "+:1:1911//12//31:-*:民前:%EC%Ey年"

保存后重新 locale-gen 即可。

不足:暂时没有弄明白怎么实现中文数字,不过阿拉伯数字也还过得去……

提交:glibc 的提交方式好像比较麻烦,所以先写篇博客好了。已提交并合并到 glibc。

发散:这个方法当然还可以用来实现各种自定义年号,比如朝鲜的主体纪年同样在 1912 年为元年,另外还有1970 “Unix 元年”、2013(咚咚咚,敲门声

h404bi's avatar

再谈谈 Scoop 这个 Windows 下的软件包管理器

在 2015 年的《用 Scoop 改善 Windows Powershell》博文中,我曾经介绍过这个令我眼前一亮的 Windows 软件包管理器。那是我刚开始使用上 Scoop 的时候,回看过去对它的介绍,也确像是一见钟情后的入坑纪实。简单,直接。
's avatar

如何被 GitHub Pages 蹬鼻子上脸

被什么蹬鼻子上脸?

GitHub Pages 是 GitHub 不知道在哪一年推出的网站托管服务。用户将网站内容放在一个 GitHub 仓库中(无论仓库是公共还是私有的),然后喝口水的功夫,网站就建立起来了。

GitHub Pages 有如下几个好处:

  1. 不要钱(以这种寒酸网站为基准)
  2. 方便,一键部署,一键 TLS
  3. 使用 GitHub CDN,不容易炸
  4. 炸了也是 GitHub 背锅

用户可以通过如下的几种方式部署 GitHub Pages:

  1. 使用名为 <username/org name>.github.io 的仓库作为网站的根目录 (webroot)
  2. 使用一个仓库的 mastergh-pages 分支作为网站的根目录
  3. 使用一个仓库的 master 分支的 docs/ 文件夹作为网站的根目录

在方式 1 下,默认可以通过<username/org name>.github.io 访问建立的网站;而在方式 2 和 3 下,默认通过 <username/org name>.github.io/<repo name> 进行访问。

除了给定的域名,GitHub Pages 还提供了自定义域名的选项,支持 example.comwww.example.com 形式的域名。具体看 wiki 。

被 GitHub Pages 怎么上脸?

通常来说,建一个博客需要如下几个部分:

  1. IP
  2. 域名
  3. 服务器
  4. 内容

使用网页托管服务,相当于用户交出了对服务器的完全控制,这有其两面性:用户可以不管什么阿帕奇,什么引擎X,但用户在服务器层面上能有多大的自由,完全取决于托管服务商的支持。

在 GitHub Pages 为例,用户失去了:

  1. HTTP redirect 的能力,具体来说,用户只能用一个 meta 标签做重定向,而不是返回 HTTP 301/302 进行重定向。
  2. 个性化错误页面,只能按照 GitHub Pages 的要求指定一个网页作为 404 页面(虽然大多情况下这就够了)。

你说的我都明白,所以这又怎么了?

其实没怎么。

由于上一篇博客中做的修改,现在的 RSS 变成了一个到中文 RSS Feed 的 HTTP 重定向。用 GitHub Pages 会使得无法重定向,导致 RSS 订阅会掉。

另外一个没有提及的问题是 GitHub Pages 的罪恶连锁:

不使用 .github.io -> 自定义域名不能使用 CNAME -> 自定义域名使用 A 记录 -> 每次部署的时候报警

以及

不使用 .github.io -> 自定义域名不能使用 CNAME -> 自定义域名使用 A 记录 -> 随机 302

其中第二个问题是由于 GitHub 方面需要平衡负载而导致的。

下一步?

再说。

's avatar

育碧 key 切断了那条蛇

Yubikey & PAM

之前没看懂 PAM 怎么用,今天重新看了一下pam(8),打算搞好之前想弄的 yubikey 解锁桌面。

pam(8)的结果:这在说什么?

看了一篇讲 PAM 的博客:噢,我明白了(没有懂),甚至应该修改 /etc/pam.d下的哪一个文件都不清楚。

还是另一篇博客让我豁然开朗。

先在 Arch Linux 上安装yubico-pam包。

然后修改/etc/pam.d/system-auth,将下面一行添加到 auth required pam_unix.so ... 那一行的前面。如果添加到后面的话,还会先调用 pam_unix.so 来索取密码,而且失败了就失败了,并不能 fallback 到 Yubikey 登陆,然而将 sufficientpam_yubico 放在最前,当 yubikey 验证成功了就一定成功。

如果写的是 required 而不是 sufficient ,结果就是不仅要 yubikey 验证成功,而且还要接着再输一遍密码,相当于倒过来的二步验证。

auth sufficient pam_yubico.so id=<yubikey API id> authfile=/etc/yubikeys

这样就大功告成了!现在 sudo,解锁屏,登陆都可以用 Yubikey 一摁完成了!

当然,如果 KDE 的用户

  • 只想用它解锁屏,就把这一行放到 /etc/pam.d/kde 里的对应位置,注意当前用户需要有 authfile 的读权限,否则无法使用
  • 只想用它登陆,就把这一行放到 /etc/pam.d/sddm 里的对应位置

如果只想用 yubikey 登陆 console (估计没有这样的人),就把这一行放到 /etc/pam.d/login 里就行了,ssh类似,大概。

而如果想离线也能验证,或者嫌在线验证时间过长的话,就换用 challenge-response 模式就可以了。具体见 Yubico 官网的相关页面,就懒得再翻译一遍了。设置好之后甚至连一摁都不需要了。

Arch Wiki 关于 Yubikey 的条目可以说比较混乱,而 Fedora Wiki 的页面则较为简洁直白,可以作为参考。

顺便一提,也是 Fedora Wiki 告诉我有 modhex 这种东西。 Yubikey 作为键盘输入,它只会向机器发送键盘扫描码,机器再将其转换为按键。因此 Yubikey 不能控制键盘的 layout ,也就导致如果随意输入,在不同的键盘 layout 上可能会输出不同的字符。比如QWERTY的Y,在德语键盘上就成了Z(它交换了Y和Z),而在日语键盘上差不多就是假名 N (说差不多的意思是在假名输入下才是 N)。因此 Yubikey 选择了那些在任何键盘 layout 下都不会变的16个字符,用以表示16进制数,这就是 modhex 。

请关掉假名输入!不然そそそそそそりこはすいきまにすこまきましすいりそなままりこのかいそひひしきのにすきしのき

中断

今天读了一篇关于硬件中断,以及如何用 PIC 处理的博文,因为没怎么看懂,就不翻译了。

玩蛇?玩个蛇皮!

Arcaea 潜力值终于上 9 了,或者说,才上 9 。啊……

慢慢来吧。

lwl12's avatar

更新至第三代服务器环境 | Docker 萌新体验记

博客算是 lwl 第一个用上 VPS 的项目了,和很多初学者一样,lwl 一直在使用一键包来完成服务器环境的架设。随着时间的推移以及请求量的增加,现有的服务器环境维护变得越来越困难,甚至开始出现了一些无法找到原因的问题。为此, lwl 决定开始着手设计和部署第三代服务器运行环境。
IceHoney Blog's avatar

后端开发的技术总结

说实话,最近前端开发的事情并不是很多。所以自己也慢慢开始做后端开发,逐渐向全沾工程师靠拢。现在的开发工作,分工分明,后端也只需要专注API的请求与返回就好了。

API文档

使用API Blueprint作为API规范,并使用RSpec API Blueprint来自动生成文档。 生成的Markdown文件,可以很方便的转换成网页便于客户端开发。例如这个工具aglio

后端开发

现在采用的开发技术框架是Ruby on Rails。不得不吐嘈一句,Ruby on Rails在日本真是压倒性的流行。Ruby on Rails还是MVC架构,原生支持RESTful API。但我觉得下一代的接口标准应该是facebook推出的GraphQL,不过先阶段RESTful API也足够了。

Models

Models主要是用来描述数据库结构,表与表之间的关系。还可以定义对数据库操作的方法,数据之间复杂的业务逻辑基本都是放在这里。

Views

Views主要是用来定义相应的数据的格式,把数据整合成统一的JSON标准供客户端使用。

Controllers

Controllers是请求的入口,用来定义请求的参数,并接收请求进行参数的过滤处理。然后调用Models里定义的方法完成数据的操作,并调用Views来完成数据的响应。

权限管理

权限管理是一件非常复杂的事情,定义某个接口在什么条件下可以调用,需要检查用户是什么身份。所以推荐是使用现有的成熟框架来进行管理。这里使用pundit来管理各个请求的权限检查。

软删除

在实际的项目中,我们需要进行软删除操作。例如用户加入了某个组织,以组织成员的身份发表了文章。当用户退出这个组织的时候,我们并不能直接删除数据库记录。否则无法显示文章的作者。这时候我们就需要软删除操作,对用户来说这条记录已经消失了。但对开发者来说,这条记录还是需要的。我们也使用框架来解决这个问题,这里采用的是Paranoia

测试

后端开发是偏向于纯逻辑的开发,所以测试非常重要。正常情况下的输入输出非常简单,代码的80%都是需要考虑到各种各样的边界条件。需要考虑到用户的各种不同情况下的操作,给出合适的错误提示。所以需要完善的测试来覆盖所有场景,这里采用的是e2e测试,模拟请求,测试后端服务器的响应输出是否符合预期。采用的测试框架是rspec-rails

参考:

Ruby on Rails Guides

's avatar

multilanguage

借助 hexo generator multilingual feed 的帮助,本站的 RSS feed 实现了语言的隔离。

中文文章的 RSS feed RSS feed of English posts

当然 原来的 RSS feed 还是任何语言都会有的。

本来想实现 post 的隔离,但既不会又不想去学。所以就搁置啦!

's avatar

2018 XJNU CTF Web Writeup

比较简单的新疆师范大学的 CTF 比赛 http://ctf.xjnu.edu.cn/
Felix Yan's avatar

请不要把 Wifi Dongle 翻译成加密狗

在许多翻译过来的文本里,无线网卡(Wifi Dongle / Wifi Adapter)被翻译成了“加密狗”。最近在微博大火的一篇《俄罗斯特工又蠢了!实名行动暴露自己还卖了300多特工队友…..》里面,又出现了类似的错误,让我不得不想说说这个问题。

先来看看这个例子:

文章描述了几个黑客在目标附近发射伪造热点钓鱼,此处的未翻译单词包括了 Wifi 和 Dongle。根据上下文,带一个无线网卡发射热点应该是正确的意思,而加密狗在这里和上下文没啥关系……

我尝试在搜索引擎里搜索对应词组,很不幸,惨状令人叹息:

就连正规电子产品的用户界面都中了枪:

这个问题的来源,看起来是国内加密狗早年被简单称呼为 Dongle:

Dongle,按照维基百科的解释,是和 Adapter(适配器)很类似的一个词,泛指了一大类连接、转换器。

Wireless/Wifi Dongle = Wifi 适配器,Bluetooth Dongle = 蓝牙适配器,以此类推。所以,在看到类似 USB Dongle 这样模糊名字的时候,请务必联系上下文。如果原文用了 Wifi Dongle 这样比较明确含义的词组,请翻译为 Wifi 适配器,或者无线适配器,不要再翻译成加密狗了。

17windy's avatar

[美羽释厄录]更新预告

0.92更新预告(进行中):

1,主菜单UI美化

2,载入功能升级,实现战斗场景同步加载(即载入显示完成即可玩)

3,伤害系统重做,以期整体提升游戏性能减少卡顿

4,部分敌人刷新行为修改(影响全部小怪关卡)

5,美羽武器系统数值平衡

6,三大BOSS战继续完善,为不同BOSS增设不同的子弹造型,调整战斗难度,掉落物调整

7,商店场景为可购买物品增加鼠标悬停时的提示(可选,低优先度)

8,斩龙剑性能改造

9,BOSS战胜利自动消除全部子弹

0.91更新(已完成):

1,商店UI优化,商店物品价格调整

2,游戏场景载入时间可感觉的优化缩短

3,降低敌人普通小弹的伤害,大幅降低敌人追踪导弹的伤害

4,增加美羽初始弹药的伤害触发范围,稍微增加美羽初始弹药的伤害,稍微增加刀风类射击的射程

5,Level9 BOSS难度调整(P2弹幕修改、受弹面正常化、稍微降低防御力)

6,Level1+2难度降低

7,三路射击鱼形怪物首次射击延后0.5秒

8,主菜单开始游戏部分菜单底部增加当前Gems数量显示

9,所有战斗场景增加了暂停功能(Esc)

10,修复主菜单的语言本地化设置

11,修复Level6蛙人BOSS战不出小怪的问题

17windy's avatar

[美羽释厄录] 0.91先行版 发布贴 10.02.2018更新

0.91更新日志:

1,商店UI优化,商店物品价格调整

2,游戏场景载入时间可感觉的优化缩短

3,降低敌人普通小弹的伤害,大幅降低敌人追踪导弹的伤害

4,增加美羽初始弹药的伤害触发范围,稍微增加美羽初始弹药的伤害,稍微增加刀风类射击的射程

5,Level9 BOSS难度调整(P2弹幕修改、受弹面正常化、稍微降低防御力)

6,Level1+2难度降低

7,三路射击鱼形怪物首次射击延后0.5秒

8,主菜单开始游戏部分菜单底部增加当前Gems数量显示

9,所有战斗场景增加了暂停功能(Esc)

10,修复主菜单的语言本地化设置

11,修复Level6蛙人BOSS战不出小怪的问题


经过一段时间的开(gu)发(gu)惭愧,美羽释厄录先行版终于发布啦!希望各位朋友能够喜欢:)

游戏类型:

横版飞行射击

游戏主题:

东方+喵窝

游戏作者:

17windy

游戏版本:

先行0.9版

已知问题:

分辨率自适应脚本存在问题,切换分辨率数字标示不明确

游戏UI还很简陋,将在未来继续完善

虽然经过了大量的优化工作,部分战斗仍存在少量掉帧问题…

语言本地化未完工(道具部分多语言问题很大),目前暂以中文文本为主

部分场景载入速度较慢

首发网站:

17.works


感谢释萝对于黑洞背景和美羽人物形象设计的付出。

该版本游戏不用于任何商业目的,欢迎下载试玩,可在不修改游戏安装包并注明作者的情况下随意转载。


先行版目前暂时只提供windows版,还望谅解。

下载链接:

0.91版

下载 Miu DB V0.91
点击次数: 124, 文件大小: 233.9 MB, 日期: 2018 10月 02

0.9版

下载 Miu DB V0.9
点击次数: 107, 文件大小: 240.4 MB, 日期: 2018 10月 01

百度云分流:

0.91版 链接:https://pan.baidu.com/s/1cnWUV-QuDKuZ2rfO9QKtyA 提取码:8dmk

0.9版 链接:https://pan.baidu.com/s/1v2UfCHoyUyoct5AmZfofVA 提取码:0zx7

Phoenix Nemo's avatar

重构 StickerSetBot

关注 Telegraf 有一段时间了。特别是最近 Telegram 上 spammer 猖獗导致 Telegram 对于用户行为限制越来越严格,由此想过写一个简单的 bot 来处理加群请求之类的。

总之原因都是没时间。终于搞定一些事情之后发现之前瞎写的 Telegram 导出贴图 bot 居然备受欢迎…正好 Telegram Bot API 也更新了,来重构吧!

拆分逻辑代码

最头疼的事情首先是当时写这 bot 的时候只顾着考虑各种情况,逻辑像流水一样全部写成一坨。虽然实际不复杂吧但这不是 best practice。于是把每个功能单独拆出来先。

on('command') 的逻辑代码整块移出来作为 handler,然后能够原子化的功能再单独拆分成函数调用。目前的效果虽然还是有不少逻辑层在 handler 里,但是基本达到了比较方便维护的目的。

handler 本来就是拿来写逻辑的啊摔

接下来再清理冗余代码和各种 hard code,加了两个方法让代码看起来更整洁一些。于是就先这样。

迁移框架

好在 Telegraf 和之前用的框架在参数上很多兼容,所以这没有花太多时间。顺便尝试采用了一部分 ES6 的风格,嘛…果然不喜欢。

所以就不要吐槽为什么 ES5 和 ES6 的风格混写了。

之前要一大长串的传参现在只要一个 context 了好方便啊。中间件也好方便啊~

以上。

调试:无尽的 bugfix

并不指望一通大换血之后的代码能一次跑起来…但是没跑起来的原因是我传错了中间件值这不能忍!!为什么一会儿传的是函数本体一会儿传的是函数调用啊摔!!

而且这问题还让我调了两个小时!!!

调通了之后就很舒服了

遇到的坑还有 context 本身不能当 session 用,然而不想再引入 session 中间件于是自己写了个超简陋的内存 session。就是为了多语言支持。因为一觉醒来发现这 bot 语言莫名其妙变中文了(messages 成了全局变量 = =

当然还有 Telegram 自己的坑,比如什么贴纸就是死下载不能然后整个程序就 hang 着了。

一键导出贴纸包

终于!Telegram bot API 添加了 StickerSet 类型。只要有贴纸包名称,就可以获取整个贴纸包的信息。考虑不改变用户习惯的情况下(你哪有什么用户啊可恶)对本身处理贴纸和其他消息的函数做了修改,顺便又拆了俩函数出来(怎么代码越来越多了啊喂!

最后结果就是没有一屏看不到头的函数啦~(你快够

以及加入了用贴纸包链接导出一整组贴纸的功能,算是真正意义上的 StickerSetBot 了。

然后贴纸过多卡死了 Telegram 的 ratelimiting

直接导出单张贴纸

既然功能拆分了那也就方便加更多别的功能啦。比如不新建任务,直接甩过去一张贴纸来获得 PNG 文件~

这只 bot 在这里,源码在这里。欢迎各种玩坏~(记得去发 issue

就酱(,,•﹏•,,)

Felix Yan's avatar

Thunderbolt 3 eGPU Bumblebee 方案尝鲜

最近从公司淘了一块 GTX 1060,淘宝了一个显卡盒折腾 TB3 eGPU 方案。由于笔记本经常带出门,打算采用即插即用的 bumblebee 方案(回家插上盒子用独显,拔下盒子可以带出门,可以正常待机不用重启)。下面记录一下 Arch 上配置的步骤和遇到的坑。

1、准备软件包

# pacman -S bumblebee primus lib32-primus nvidia-dkms lib32-nvidia-utils bolt

2、修改 bumblebee 配置

修改 /etc/bumblebee/xorg.conf.nvidia,在 Section “Device” 中加入:

Option "AllowExternalGpus" "true"

修改 /etc/bumblebee/bumblebee.conf,在 [optirun] 中修改:

Bridge=primus

3、插入 TB 线,验证设备(不建议完全关闭设备验证!)

输入 boltctl 查看设备信息,记下设备的 uuid。

$ boltctl
 ● TUL TBX-550CA
   ├─ type:          peripheral
   ├─ name:          TBX-550CA
   ├─ vendor:        TUL
   ├─ uuid:          00xxxxxx-xxxx-xxxx-ffff-ffffffffffff
   ├─ status:        authorized
   │  ├─ domain:     domain0
   │  └─ authflags:  none
   ├─ authorized:    Fri 28 Sep 2018 08:23:25 AM UTC
   ├─ connected:     Fri 28 Sep 2018 08:23:21 AM UTC
   └─ stored:        Thu 27 Sep 2018 05:22:07 AM UTC
      ├─ policy:     auto
      └─ key:        no

验证设备并设置为自动验证:

$ boltctl enroll --policy=auto 00xxxxxx-xxxx-xxxx-ffff-ffffffffffff

4、启动 bumblebeed

# systemctl start bumblebeed

5、测试、运行程序

$ optirun glxspheres64
Polygons in scene: 62464 (61 spheres * 1024 polys/spheres)
Visual ID of window: 0x13f
Context is Direct
OpenGL Renderer: GeForce GTX 1060 5GB/PCIe/SSE2
……

6、安全删除设备(参考了 jpamills 博客里的脚本)

#!/bin/bash

secs=5
tbt_chain=/sys/bus/thunderbolt/devices/0-0/../../../..

echo "Unplug eGPU script started."
if [ "$(id -u)" != "0" ]; then
        echo "Please run using sudo. Exiting."
        exit 1
fi

systemctl restart bumblebeed
sleep 2
modprobe -r nvidia_modeset
modprobe -r nvidia-uvm
modprobe -r nvidia

if [ -e $tbt_chain/remove ]
then
        echo 1 > $tbt_chain/remove
        echo "Thunderbolt chain removed from PCI tree. Please unplug eGPU now."
        while [ $secs -gt 0 ]; do
                echo -ne "$secs to rescan...\033[0K\r"
                sleep 1
                : $((secs--))
        done
        echo 1 > /sys/bus/pci/rescan
        echo "Rescanned the PCI bus. Completed."
        exit 0
else
        echo "eGPU does not appear to be attached. Exiting."
        exit 1
fi

如果和我一样在盒子上插了外置硬盘,还可以在脚本里加上相应的 umount 语句。删除设备时需要先把使用设备的程序退出。

效果展示

剩下的问题

  • 脚本里可以考虑通过判断 nvidia-smi 列出的 PID 自动杀掉所有还在用卡的进程
  • Vulkan 应用程序暂时无法使用外置卡运行(仍然使用集显),可能需要 bumblebee 提供支持
Phoenix Nemo's avatar

想要导出 Telegram 贴图

Telegram 上出现了越来越多的优质贴纸,想要把这些贴纸用到其他 IM 平台上的时候就会比较麻烦,所以一直想要一键导出一个贴纸包的功能。

可惜的是,Telegram bot API 的限制,并没有任何简单的办法通过贴纸消息获得贴纸包的信息。寻找另外的途径,例如 telegram.me 的贴纸链接会定向到 tg://addstickers?set=[StickerSet]。搜索了一下现成客户端的源码,都是交给 MTProto 的 API 处理,也没有明确的解析过程。而这些客户端所调用的 messages.getStickerSet 也没有在官方的文档中列出。(吐槽:Telegram 的协议、文档和代码真是糟糕,查阅的时候我的表情一直是 黑人问号.gif

由于最近状况不是很好,所以只好暂时放弃继续读 webogram 的源码。因为读 Angular 的东西实在是折磨…

所以依然是选择直接发 sticker 再转为图片发给用户的模式。这样的已经有了相关的 bot,于是改为多个 sticker 打包、支持多语言、支持 jpg 和 png 以及批量缩放功能的 bot。需要安装 Node.js v4.0 及以上版本和支持 webp 的 ImageMagick。

虽然实现效果看起来还可以,但是并未实现最初希望的功能,所以只能是练手用的轮子而已。不过,这个轮子稍微尝试了一些新的东西。例如超简陋的内存数据库,而且很多细节考量更加周到,例如任务锁虽然不是写过最麻烦的,不过应该算是相对完善的。当然也考虑了内存数据库的手动释放以防内存爆炸为此还特地在群里讨论了 object children 被 undefine 而 object 其他 children 还在被引用的状态下是否可以回收部分内存的问题

源码的实现非常简单,但是好久不写代码还是手生,折腾了一下午写功能加一晚上和朋友们 debug。读源码戳 GitHub

这里有一只 bot 跑在测试环境,所以可以尝试一下。如果没理你说明沙盒没开,那么就请自己去跑源码来使用辣ᕕ(ᐛ)ᕗ

有几点坑,比如这个 node-telegram-bot-apionText 方法无法正确匹配 Negative Lookahead 的正则表达式(不应该啊…然而没深究),adm-zip 非常非常不好用,jszip 文档表述不清 API 调用复杂然而用起来了就还不错。

但是最坑的是,只为实现这么一个简单功能的 bot,我的 node_modules 目录下居然有

1
2
Phoenix-X1-Carbon :: js/telegram-stickerimagebot/node_modules ‹master› » ll | wc -l                                                                                               1
104

WHAT??? 104 个依赖包!!!

真是可怕…明明我已经尽可能减少不必要的依赖了…

===== 2018/9/28 更新 =====

Telegram bot API 更新了(早就)

于是这只 bot 可以一键导出一组贴纸了。详情

AlisterTT's avatar

觉得有必要放点什么东西

突然发现最近一篇日志还是去年8月写的,这都9月了,一年没更新,还是随便写点吧。

分享个有意思的东西,关于皮神的奇妙旅行。

前两年基友在日本出差的时候,回来给我带伴手礼,选了个皮神的amiibo,刚好那两天要去Great Hall围观一个颁奖晚会,就顺手把皮神揣口袋里了,于是有了下面的照片:

Processed with VSCO with kk2 preset

Processed with VSCO with hb1 preset

不出意外的话,这应该是历史上第一个在Great Hall里拍写真的皮神。

这两天刚好又有活动,去坝上那边参观,脑子一抽又把皮神揣口袋里了,于是有了下面的照片:

Processed with VSCO with c2 preset

Processed with VSCO with hb2 preset

感觉还是棒棒的,以后出门都把他带上好了。

IceHoney Blog's avatar

跨域请求中的cookies处理

现在的前后端开发已经完全分离,后端服务器和前端服务器分别部署在不同的服务器。同时也对应不同的域名,所以跨域请求领域方面的知识也需要补充。

跨域请求添加header

我们都知道,出于安全考虑,JS是有同源策略限制。所以,我们在对其他域名发起请求的时候需要添加 http header。

    Access-Control-Allow-Origin: *

这个参数的值只能为星号或者具体的网址,星号代表所有网站。

跨域请求添加cookie

JS跨域请求有两个API可以使用,XMLHttpRequestfetchXMLHttpRequest会默认带上cookies,但是fetch默认不会带上。如果需要带上cookies,需要把withCredentials设置为true

跨域请求服务器设置cookie

我们都知道服务器设置cookie是通过set-cookie的 http header来完成。浏览器会读取这个信息设置cookie。但是对于跨与请求,默认是无效的。我们需要再添加一个 http header。

    Access-Control-Allow-Credentials: true

当设置了这个 http header,Access-Control-Allow-Origin就不能设置为星号了,必须指定具体的网址。我们必须指定withCredentialstrue并且Access-Control-Allow-Credentialstrue的时候,服务器返回的set-cookie才会生效。

参考:

Access-Control-Allow-Credentials

CORS

Felix Yan's avatar

Arch Linux 社区中不成文的约定(一)

作为一个年轻和小众的社区(咳咳),Arch Linux 社区中有着许多不成文的约定。本文希望通过稍稍讲解一二,来消除一些新人们常常感到的困惑。由于预感到日后可能还会有更多问题,暂且认为这是系列里的第一篇

  • 修理“坏”包和提醒更新

仓库里一般的包可能有一个或多个维护者,也可能没有维护者,成为“孤儿”。如果坏掉或者过期的包是一个孤儿,申请从仓库里删掉是更有效的方法,这样它可以在 AUR 找到新的主人。发邮件到 aur-general 解释一下情况,并表明自己或者别人想维护它,一般都会很快得到解决。

如果“坏”包有维护者,但他太忙了呢?这种情况下,这个包很可能已经在 Bug Tracker 里泥足深陷。这种时候可以通过帮维护者一个小忙的方式来促进问题的解决。如果有人找到了上游 Bug Report,并且上游已经修复提供了 patch 的话,可以考虑把 patch 贴到 Arch 的 Bug Tracker;如果这件事已经有人做了,可以修改 PKGBUILD 打上 patch,然后把改好的 PKGBUILD 贴上去;如果连 PKGBUILD 都有人准备好了,而且过去了一段时间的话,可以考虑把这份准备好的 srcpkg 或者 diff 直接发邮件给维护者,附上简短的感谢和一个笑脸

同样的道理,如果一个过期包已经被标记过期很久了,也可以准备一个新版的 PKGBUILD 发邮件给维护者。

  • 提供旧版软件包

因为懒得迁移各种各样的原因,你可能希望某些软件包的新旧版本同时提供。在 Arch 的实践中,这种情况被尽量避免了。把无法迁移的古老软件删掉还是提供一个旧版库让古老的软件能用,一定程度上取决于维护者对这个古老的软件有多坚持。

另一个考虑的因素是上游如何看待新旧版本。有的软件新版发布后,旧版就不再维护了,这种情况下 Arch 通常尽力避免成为新的上游。而有的上游则同时维护多个版本,Arch 这边根据其他软件的依赖情况,可能会有选择性地同时维护几个。

  • 第三方 patch 能不能加上

Arch 对 patch 的态度比较保守,在规则里写的是一般只有修复编译和主要功能的上游已经接受的 patch 会考虑。在实践中,有些时候没有这么严格,比如开发者自己写的 patch 一边提交给上游,还没等答复,一边就加到了包里。因为 Arch 打包并没有 Review 过程,实际上加了什么 patch、靠不靠谱就全靠开发者自己掂量了。

一般来说,被上游明确拒绝的功能性 patch 是不怎么会考虑的。修复一个特定问题,尤其是影响比较大的问题的上游有点意见的 patch 有可能会被考虑。修复一个安全问题的 patch 经常会被接受,尤其是已经拿到 CVE 号的。

  • 使用上游二进制 vs 从源码编译

一般常识是发行版们倾向于从源码编译一个软件,理由包括确保二进制真的来自这份源码、尽量使用系统中的动态链接库而不是静态编译一份以满足安全更新和体积方面的考虑、进行必要的修改等。

但是因为太懒一些问题,即使是在 Arch 官方仓库里也直接重新打包了一些上游的二进制。这些问题包括:源代码不开放(nvidia、flash 等)、编译过程中会去下载东西,而且不容易解决(dart、一些 java 软件等)。

  • 文档是否打包

现在互联网十分发达,开发者们查询文档通常都是直接上网搜索。在这样的背景下,是否打包软件包的文档(通常都是开发文档)成为了一个问题。早些时候的包开启文档较多,如果太占体积还会考虑拆一个单独的文档包。后来才增加的新包则很多都没有启用文档,除非被用户要求提供文档才考虑这件事。

's avatar

T-Pot 蜜罐的介绍及使用

T-Pot 蜜罐是德国电信下的一个社区蜜罐项目,是一个基于 Docker 容器的集成了众多针对不同应用蜜罐程序的系统,目前发行的最高版本是 2017 年 11 月 7 日发布的 T-Pot 17.10,根据官方的介绍,每年都会发布一个新的版本。
's avatar

好像太久没有更新了

这里的内容已经一年没有更新了。

与其说是懒得更新更应该说是没有做出什么能让我更新的事情吧。

说起来这段时间一直都比较糟糕,既没有搞出什么新的作品,在学业上也是遇到了一堆问题。真是太失败了。

今后的话……还是希望能提起精神造出一些新的内容来,不过我好像对自己失去信心了呢。

之后再看吧。

Dimpurr's avatar

钉子的谜之 SETUP 18 @ Ningen

本文原载于 人间 / Dimpurr Cheny ,前文 钉子的谜之 SETUP (2014) 。

?‍? 简要介绍一下自己,并且谈谈正在做什么?

这里钉子,现役帝都大学生。曾经写写画画做过不少事情,当过宅圈内知名前端博主,设计过几个流行的 WordPress 主题,发起过一点音乐社区相关小项目,都已经成为过去。大一以来,唯一的成就是为了拯救北邮人技术组废部危机,不得不成为偶像,建立了 BYRIO 开源社区。目前在选择遵循自己内心去做游戏设计和编曲,还是顺应他人期待继续在 CASIA 和 MSRA 的 ML 搬砖日常前犹豫不决。

? 你使用的硬件有?

主役 MacBook Pro + Surface Pro ,经常同时携带 (虽然很重) ,前者用于影音处理、工程开发、平面设计、绘图板画画 (Wacom Intuos PTM CTH680) ,后者用于 PDF 阅读和批注、 OneNote 笔记、 Surface Pen 作画、推 Gal 和小游戏 (V-A HALL, FrostPunk) 。 Surface Pro 虽然性能有限,但是在轻薄的前提上能让自己在任何时空基本具备进行任何工作的能力。

宿舍配备 Linksys WRT1900AC v1 用于享受百兆校园网 (IPv6 免流 + 学校网络中心成员特权套餐) ,一块 26’ DELL UltraSharp Monitor U2415 外接屏一般连接 MBP 用于宿舍组团看 Rick and Morty 或少女歌剧、瀑布流展示作画和人体结构参考资料、工作时看论文和文档等,计划接上 Switch Dock 之后用来在宿舍玩舞力全开。配置 MIDIPLUS X6 键盘 + ATH-AD2000X 开放式大耳用于演奏。

随身 Sony XPERIA XZ1 ,佩戴 Moto 360 。 SHURE SE846 耳塞退烧,前端 iBasso DX90 和耳放 Sony PHA3 常年借给同学。 iPad mini 用于音游 (Cytus II, Arcera, Groove Coaster, Dynamix) , Nintendo Switch 用于 Party Game (分手厨房) 和沉迷死喷浪涂 (Splatoon) 。

? 你使用的软件有?

常年 macOS, Windows 和 Linux 跨平台用户,曾经是 OpenSUSE 党。 macOS 下剪贴板历史 Paste 和快速访问 Spotlight 重度用户, Win 对应工具是 Ditto 和 Keypirinha 。所有常用 App 必须选择跨平台解决方案, 必备滴答清单 + SimpleList 。日常 IM Telegram 和 QQ ,偶尔用 HexChat 挂 IRC 。念念不忘的 Mac 独占 App 有 Sketch, GarageBand, Agenda, OmniFocus 和 XLD 。念念不忘的 Win 或者 Unix 独占 App 没有,非要说的话 PC 游戏。

曾经 Sublime Text 2 党,如今 Visual Studio Code 忠实用户,必备插件是 background 自带魔理沙背景 + GitLens 。终端分别 iTerm2 和 Cmder / MobaXTerm 。 macOS 下用 SourceTree 做 Git GUI ,用 MAMP PRO 做服务器测试环境。写作环境 ByWord 和 Typora ,设计主 Sketch 辅 Axure 和 PhotoShop ,偶尔用 Illustrator 描矢量画或者 InDesign 做小册子。剪辑一般用 Final Cut Pro 或者 Premiere 。三维制作 3DS MAX 和 Blender 。

主要用 CLIP STUDIO PAINT 作画,新的拟真铅笔手感非常好。有时候会使用 Krita , Tyson 大大绘制的 Kiki 启动屏幕非常可爱,自带的丰富笔刷和镜像画笔等功能很能激发创作灵感, BYRIO 社区还组织参与过 Krita 中文文档的翻译工作,在此安利。

? 你梦想中的设备是怎么样的?

梦想是巨硬让 Surface Pro 性能、品控和售后再好一点,水果让 MacBook Pro 再便宜一点,索法不要搞 XZ2 这种歪门邪道好好出 XZP 这种全平衡侧面指纹带耳机孔的好手机。离开大学宿舍后可能会对个人工作站的设备有新的愿望,目前暂时并没有什么其他的梦想。

? 以下附图。

Surface Pro 桌面

Surface Pro 开始

MacBook Pro 桌面

MacBook Pro LaunchPad

本文来自 钉子の次元 - Dimpurr - 千里之行,始於足下。 ,原文地址 钉子的谜之 SETUP 18 @ Ningen

's avatar

Fish Shell 精简手册

Fish —— 一个友好的交互式终端

via these people and places