name: "Hello World"
description: "Greet someone and record the time"
inputs:
who-to-greet: # id of input
description: "Who to greet"
required: true
default: "World"
outputs:
time: # id of output
description: "The time we we greeted you"
runs:
using: "node12"
main: "src/index.js"
编写代码
代码的位置是 actions/release/src/index.js
const core = require("@actions/core");
const github = require("@actions/github");
try {
// `who-to-greet` input defined in action metadata file
const nameToGreet = core.getInput("who-to-greet");
console.log(`Hello ${nameToGreet}!`);
const time = new Date().toTimeString();
core.setOutput("time", time);
// Get the JSON webhook payload for the event that triggered the workflow
const payload = JSON.stringify(github.context.payload, null, 2);
console.log(`The event payload: ${payload}`);
} catch (error) {
core.setFailed(error.message);
}
描述文件说明了 action 的 输入、输出、以及从哪开始运行 action。要注意的是, main 的路径是相对于 action.yml 文件,而不是相对根目录。
使用 action
在 .github/workflows/main.yml 创建一个 workflow
on: [push]
jobs:
hello_world_job:
runs-on: ubuntu-latest
name: A job to say hello
steps:
# To use this repository's private action, you must check out the repository
- name: Checkout
uses: actions/checkout@v2
- name: Hello world action step
uses: ./actions/release
id: hello
with:
who-to-greet: "Mona the Octocat"
# Use the output from the `hello` step
- name: Get the output time
run: echo "The time was ${{ steps.hello.outputs.time }}"
Object 类位于java.lang ,我们可以看到源码中写到 Every class has {@code Object} as a superclass. All objects 即 Object 类是所有类的父类。
public final native Class<?> getClass();
public native int hashCode();
public boolean equals(Object obj);
protected native Object clone() throws CloneNotSupportedException;
public String toString();
public final native void notify();
public final native void notifyAll();
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException;
public final void wait() throws InterruptedException;
protected void finalize() throws Throwable { }
getClass 方法
* @return The {@code Class} object that represents the runtime
* class of this object.
public final native Class<?> getClass();
从源码中可以看到 getClass 是 final 方法,无法被继承。同时是 native 方法。即其他语言例如 C 与 C++ 实现的方法。结果为对象的运行时 Class 对象。
举个例子
package im.yfd.demo;
class A {
}
class B extends A {
}
class Test{
public static void main(String[] args) {
A a = new A();
A b = new B();
System.out.println(a.getClass());
System.out.println(b.getClass());
a = b;
System.out.println(a.getClass());
}
}
返回结果
class im.yfd.demo.A
class im.yfd.demo.B
class im.yfd.demo.B
public class Person {
Person(String name) {
this.name = name;
}
private String name;
@Override
public boolean equals(Object object) {
if (this == object) {
return false;
}
if (object == null || object.getClass() != this.getClass()) {
return false;
}
Person p = (Person) object;
if (p.name == null) {
return this.name == null;
}
return p.name.equals(this.name);
}
}
class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Person a = new Person("name");
Person b = new Person("name");
Map<Person, String> map = new HashMap<>();
map.put(a, "a");
System.out.println(a.equals(b));
System.out.println(map.get(a));
System.out.println(map.get(b));
}
}
class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Test test = new Test();
Test testClone = (Test) test.clone();
}
}
会报错 Exception in thread "main" java.lang.CloneNotSupportedException。
finalize 方法
finalize 方法会在对象被回收时候调用。
class Test {
String name;
@Override
public void finalize() {
System.out.println("GC: " + name);
}
public static void main(String[] args) throws CloneNotSupportedException {
Test test = new Test();
test.name = "1";
System.out.println("test 1");
System.gc();
test = new Test();
System.gc();
System.out.println("test 2");
}
}
7 months ago 4 minutes read (About 611 words) https://blog.yfd.im/
使用 JavaScript 编写自定义 Github Action
Github Action 有可以通过 JavaScript 和 docker 来编写。这篇文章讲的是如何使用 javascript 来编写 GitHub Action。
为了方便,我编写的是项目内置的 GitHub action。
编写描述文件
创建 action 的描述文件
actions/release/action.yml
编写代码
代码的位置是
actions/release/src/index.js
描述文件说明了 action 的 输入、输出、以及从哪开始运行 action。要注意的是, main 的路径是相对于 action.yml 文件,而不是相对根目录。
使用 action
在
.github/workflows/main.yml
创建一个 workflow提交代码以后,我们就可以发现,~ 成功~(失败)了。
[![](https://diamondyuan.oplinjie.cn/2020-04-16-write_custom_github_action_using_javascript_01.png)
运行结果
](https://diamondyuan.oplinjie.cn/2020-04-16-write_custom_github_action_using_javascript_01.png)
解决问题
查看 官方 demo , 发现他把 node_modules 上传到了 GitHub 🤦♂️。
继续看官方文档,提到了
zeit/ncc
。可以把依赖全部打包成一个文件。那就很简单了。1. 修改代码路径
2. 修改 package.json
3. 修改入口
4. 成功运行
[![](https://diamondyuan.oplinjie.cn/2020-04-16-https-::diamondyuan.oplinjie.cn:2020-04-16-write_custom_github_action_using_javascript_02.png)
运行成功
](https://diamondyuan.oplinjie.cn/2020-04-16-https-::diamondyuan.oplinjie.cn:2020-04-16-write_custom_github_action_using_javascript_02.png)
参考文档
8 months ago 2 minutes read (About 225 words)
[PayPal 汇率设置](/2020/03/21/PayPal 汇率设置 /)
Switch 的欧服和日服最近都不能直接绑定信用卡来购买游戏,需要台湾的 PayPal 来曲线救国。
而 PayPal 自带的汇率是远高于银行自带的汇率,所以要在网页上切换货币转换方式。
1. 首先要进入自动付款设置页面
链接是 https://www.paypal.com/myaccount/autopay/
[![](https://diamondyuan.oplinjie.cn/2020-03-21-PayPal%20%E6%B1%87%E7%8E%87%E8%AE%BE%E7%BD%AE_01.png)
image.png
](https://diamondyuan.oplinjie.cn/2020-03-21-PayPal%20%E6%B1%87%E7%8E%87%E8%AE%BE%E7%BD%AE_01.png)
2. 选择 Nintendo 账户后,点击编辑按钮
[![](https://diamondyuan.oplinjie.cn/2020-03-21-PayPal%20%E6%B1%87%E7%8E%87%E8%AE%BE%E7%BD%AE_02.png)
image.png
](https://diamondyuan.oplinjie.cn/2020-03-21-PayPal%20%E6%B1%87%E7%8E%87%E8%AE%BE%E7%BD%AE_02.png)
3. 在弹出的弹框中,点击查看货币转换选项按钮
[![](https://diamondyuan.oplinjie.cn/2020-03-21-PayPal%20%E6%B1%87%E7%8E%87%E8%AE%BE%E7%BD%AE_03.png)
image.png
](https://diamondyuan.oplinjie.cn/2020-03-21-PayPal%20%E6%B1%87%E7%8E%87%E8%AE%BE%E7%BD%AE_03.png)
4. 设置成根据 MasterCard 转换
[![](https://diamondyuan.oplinjie.cn/2020-03-21-PayPal%20%E6%B1%87%E7%8E%87%E8%AE%BE%E7%BD%AE_04.png)
image.png
](https://diamondyuan.oplinjie.cn/2020-03-21-PayPal%20%E6%B1%87%E7%8E%87%E8%AE%BE%E7%BD%AE_04.png)
妈妈再也不怕我被坑钱了。
8 months ago 2 minutes read (About 228 words)
zsh (nvm) 启动时间优化
使用
time zsh -i -c exit
可以看到 zsh 的启动时间。本来都已经习惯了,今天突发奇想研究了一下,发现是 nvm 拖慢了我的 zsh。
解决方案
搜了一下 nvm 的 issue,找到了 解决方案 。
.zshrc
,把 下方 nvm 启动的代码删除。效果
a year ago
源码解析
5 minutes read (About 702 words)
1. 编译与运行 VS Code
环境
>= 10.16.0
,< 11.0.0
Xcode 以及命令行工具 (Command Line Tool),安装后会自动安装
gcc
和make
安装完毕后,运行 yarn 命令来安装全部的依赖。
Read More
3 years ago
LeetCode/LintCode 刷题
3 minutes read (About 408 words)
Leetcode 215 数组中的第 K 个最大元素
Leetcode 215 数组中的第 K 个最大元素
在未排序的数组中找到第 k 个最大的元素。请注意,它是数组有序排列后的第 k 个最大元素,而不是第 k 个不同元素。
例如,
给出
[3,2,1,5,6,4]
和 k = 2,返回 5。注意事项:
你可以假设 k 总是有效的,1 ≤ k ≤ 数组的长度。
思路 1 堆
可以先取 k 个元素,放到一个数组中,然后把数组转换成最小堆。之后遍历剩下的全部元素,和最小堆的根进行比较。如果比根要大,则替换根,之后把数组重新转换成最小堆。遍历完成后,最小堆堆根即为第 k 大的元素。
题目链接
Leetcode-cn
Leetcode
3 years ago 3 minutes read (About 426 words)
Elasticsearch 入门教程(1) 安装 Elasticsearch 与 Kibana
本文基于版本 6.1.1
Elasticsearch 是基于 Lucene 的开源搜索引擎。封装了底层 Lucene 的接口并且提供了 REST API 的接口。开箱即用。
使用 docker 安装
用 docker-compose 部署最为方便。把下面的内容保存到 docker-compose.yaml 中,然后执行
docker-compose up -d
就可以启动容器。构建镜像的 Dockerfile 分别 如下
如果运行成功,那么 es 会在本地的 9200 端口运行。用 curl 请求 9200 端口,可以获取当前集群的名称,版本等信息。
访问 localhost:5601 就可以看到 Kibana 的页面了
注意点
max virtual memory areas vm.max_map_count [65530] is too low
如果执行失败 出现
max virtual memory areas vm.max*map*count [65530] is too low
的错误。需要执行下面的命令。3 years ago
Java 基础
6 minutes read (About 932 words)
Java Object 方法简析
Java Object 方法简析
Object 类位于
java.lang
,我们可以看到源码中写到Every class has {@code Object} as a superclass. All objects
即 Object 类是所有类的父类。getClass 方法
从源码中可以看到 getClass 是 final 方法,无法被继承。同时是 native 方法。即其他语言例如 C 与 C++ 实现的方法。结果为对象的运行时 Class 对象。
举个例子
返回结果
hashCode 方法与 equals 方法
equals
equals 主要用于判断两个对象是否相等。约定 equals 有下列几个性质。
当 object object1 object2 均为非空时。
Object 类中的默认实现为比较两个地址是否相同。等价于
==
hashCode
hashCode 也是一个 native 方法。该方法返回对象的哈希码,通常用在哈希表中。例如常用的 HashMap。
对于 hashCode,我们 应该 遵循如下规则:
在一个应用程序执行期间,任何时间对同一个对象调用 hashCode 方法。都必须返回用一个整数。这个整数在两次对同一个应用程序的执行在不需要保持一致。
如果两个对象通过 equals 比较相等,那么 hashCode 方法必须产生同样的结果。
如果两个对象通过 equals 比较不相等,那么 hashCode 方法产生的结果 不需要 向灯。但是如果不同对象产生不同的结果。那么有助于提高哈希表的效率
当重写 equals 时候 必须也要重写 hashcode 。否则在 HashMap 中就会出错。
例如上面的代码的返回结果就是
因为 HashMap 会先根据 hashcode 来决定对象在哪个桶中。再在同一个桶中根据 equals 判断 key 是否相同。
clone 方法
clone 会返回对象的拷贝。如果直接调用
会报错
Exception in thread "main" java.lang.CloneNotSupportedException
。finalize 方法
finalize 方法会在对象被回收时候调用。
例如上面的代码返回结果
3 years ago
技术与折腾
4 minutes read (About 586 words)
阿里云折腾记
起源
博客挂在 Github 上不要钱,但是总感觉访问有些慢。而且有时候会想跑一些脚本和服务,就一直考虑过买一台服务器。在大学里对 Linux 用的不多,唯一一次就是在阿里云上买了一个学生主机,玩了几天以后感觉没什么用不会玩,就没有再续费了。前几天逛阿里云的时候,居然看到了一个叫云上浙江的活动。西湖区的公司,没用过阿里云的话可以免费领 2000 无任何限制的代金券。简直是天上掉了馅饼。因为我刚好有一个杭州的公司,所以就新注册了一个账户。中间虽然有一些小波折,但是最终还是成功领到了钱。千挑万选之下选了 ECS 香港 2 核 4G 1M 带宽 100G 硬盘。虽然带宽 1M 有点小,不过只需要 1980 就能买这个配置的服务器三年。还是非常划算的。更何况也不需要我自己出钱。
SSH 相关设定
为了不用输入密码和安全考虑,肯定是要用 SHH key 登录,阿里云控制面板的云服务器 ECS - 绑定密钥对 - 创建密钥, 输入名字例如 test 就可以直接生成密钥对, 生成完成以后会自动下载一个 test.pem 的私钥, 然后选择之前已经买好的 ECS。绑定之后不需要重启就可以利用这个私钥登录了。用阿里云的服务生成和绑定只要是和自己写的项目FastAirport 有关。
安装 docker
假如我们服务的 IP 是 aaa.bbb.ccc.ddd SSH 的接口是 1234
部署 hexo
原先的博客是放在 Github pages 上的。分成了blog和GeorgeYuen.github.io, 虽然这样不要钱,也比较方便, 不过既然搬家到了自己的服务器上,那肯定是要折腾一下的。后来用 Daocloud 做了持续部署。
其他放在另外的文章里面说吧,一下子也说不完。
3 years ago
技术与折腾
8 minutes read (About 1245 words)
如何在自己电脑上搭建一个电子书网站
搭建了一个个人的电子书网站
作为一个松鼠党,从高中逛E-INK开始就收集各类电子书,这么多年下来也积攒了一大笔积蓄。下书入流水,看书如抽丝。那么这些书的管理就成了一个问题。最后选了半天还是决定用 calibre 来管理自己的电子书。
calibre 虽然速度有些慢,不过应该是目前为止能找到的最好的电子书管理工具了。和 kindle 的结合也很好。考虑数据的备份,除了在自己的 Mac 上存放了书库以外,还利用 Resilio Sync 把书库存到了群晖上。这样就算是电脑被偷数据也不会丢了。不过 calibre 的数据库有一个缺点,他在电脑上储存文件的目录结构是 / calibre/author/books
而且会把全部的汉字转换成拼音。直接用 Mac 上的 calibre 看的话挺方便的,但是远程用手机访问群晖的话看到的都是类似于拼音文件。找书很不方便。所以就想找一下有没有 calibre 的 web 版本。
搜了一下果然有人已经早好轮子了calibre-web 一个用 Python 写的一个 Web app。
官方介绍是这样的:Calibre Web is a web app providing a clean interface for browsing, reading and downloading eBooks using an existing Calibre database.
直接利用 calibre 的数据库,然后支持下载,上传,在线阅读,数据修改,发送到 kindle。而且手机端和 web 端都支持,真是完美符合我的需求。不过要吐槽一点,这个源码居然不打 tag,程序更新完全是靠 git 拉取来更新。真的是大开眼界。
既然调研好了,那么就开始搭建吧。
网站搭建
背景说明
其实上面啥都不需要,只需要一台能运行 docker 的设备就可以了。内存大约 100m 不知道树莓派能不能撑得住。 Python 的效率真低呀。
首先先是电脑上安装 calibre,然后同步自己的书库到群晖。这一步网上教程太多,就不详细介绍了。
同步完之后,我们的群晖上就有了数据库。例如我的目录是 /Backup / 书库 里面有一个数据库文件 metadata.db
数据库有了,就开始安装程序。程序安装很简单,只需要一个 python 环境就可以了。
执行命令以后你就把网站搭好了,访问http://localhost:8083 就可以看到自己搭建的网站了。
不过妈妈说了,能用 docker 解决的问题都用 docker 解决。
Dockerfile 如下。
项目的主页有一个镜像了,但是我个人有点没看懂,而且镜像里面是不带项目本身的,在第一次启动镜像的时候会从 git 上面拉取最新的源码,然后重启。其实挺符合这个开源项目的风格的,利用 git 进行版本更新。写得其实比我好。有需要的小伙伴可以自己研究安装。
安装说明
说了半天废话,那么图文教大家如何安装吧。
首先安装群晖的 docker 点开注册表 双击选择阿里云。
搜索 calibre, 找到我写好的的镜像后双击下载。因为在国内,所以挺快的。感谢阿里爸爸。
安装完双击启动容器
配置一下本地目录和装载目录。本地目录就是你电子说所在的位置。
如果你需要电子书编辑的功能,那么不要勾选只读。英文我只想浏览和下载,所以选择了只读。
设置完成以后点击确认 应用。你的个人服务器就布置好了。
举个例子
例如我群晖的路由访问页面是 192.168.3.101:6001,那么 192.168.3.101:8083 就可以看到自己部署的网站了。
3 years ago
技术与折腾
8 minutes read (About 1229 words)
利用 Daocloud 完成 Hexo 的持续部署
本文不仅限于 hexo,可以适用于任何项目。
因为买了阿里云的服务器,而且受不了Github的速度,就准备把自己的博客迁移到国内的网站。而且把网站放在 docker 里以后,无论在哪台服务器,只要安装了 docker,都可以很快捷得部署自己的博客。之前先说一下
思路,一开始我是把 blog 的源码(不含 node_modules)直接 copy 到 hexo 的镜像中,然后下载 npm 的模块,再执行 generate。执行完以后把 public 目录下的文件全部复制到一个 nginx 的镜像下面。需要部署的时候,只需要拉取那个 nginx 镜像就可以了。
但是这样有一个缺点,每次更新博客,都要重新下载一遍 node_modules。如果不换国内源的话,发布一次要等很久。于是就换了一个思路。因为博客的依赖基本上是不变的,package-lock.json 与 package.json 基本上不更新,所以可以先把这两个文件复制到 hexo 里面,预先下载好,生成一个新的 base 镜像。每次发布的时候,都从这个镜像开始动手。只需要 hexo g。然后就可以把 public 文件提取了。build 速度从原来的 7 分钟提升到了 40 秒。等依赖或者插件更新的时候,可以手动更新一下 base 镜像。
思路有了,那就开始动手布置吧。详细文件可以看我的Github 希望大家喜欢的话可以 star。
首先是 base 镜像,除非添加新的插件或者 hexo 更新,不然基本上不会替换。
构建镜像,主要基于 base 镜像是把博客源码复制进去,然后生成 public 文件。
发布镜像 把博客的 html 文件复制到 nginx 镜像中。
如果是部署在 github,那么可以把这个文件替换成一个有 git 的镜像,把代码提交到 git 中。
本来这样就可以了,原本是准备自己造一套轮子的,但是后来实在是嫌麻烦,就直接用了 daocloud 的服务,反正也不要钱,还可以为自己服务器节约一些硬盘。如果用 docker 官方的 hub,我不是很清楚提取文件和打包应该如何,可能需要自己在本机写一下脚本吧。其他的博客生成器使用思路都差不多,只需要改一下 dockerfile 的命令就好了。
窝在 daocloud 上建了两个项目。blog 和 blog-base。都关联了 github。还有两个 ymal 文件,直接贴出来。
第一个是 blog-base 的流程,只有装新的插件而且打 tag 以后,才会触发这项目,更新 base。
第二个上 blog 项目,用了两个 dockerfile。每次更新代码会先临时生成一个镜像,提取出 public 文件后复制到 nginx 的镜像中。这些操作都在 daocloud 的服务器上完成,不需要占用自己电脑的空间。我一个空的 hexo 博客 + nginx 大约是 15mb。而一个 node+hexo 的镜像在 700mb 左右。
最后只需要拉取最终生成的镜像,就可以在任何电脑上布置自己的博客了。更新博客的话只需要往 hexo/source/_posts 里添加一篇文件并且 push 到 github,就会自动触发 daocloud, 构建一个新的博客镜像。基于这个镜像,窝在 daocloud 上发布了一个应用,并且设置为自动更新。每次有新的镜像出来就会自动拉取镜像到我的阿里云上,并且发布。
这个思路可以用在任何的项目上,比如我司的 JAVA 项目,就是把源码拷贝到一个 gradle 的镜像里,构建好以后提取 jar 出来,再放到一个只有 jre 的镜像中。可以缩小最终生成的 docker 镜像的大小。
Previous
Next