用docker申请letsencrypt通配符证书

用 docker 申请 letsencrypt 证书的好处就是不需要在宿主机上安装依赖,只要用下面的命令即可:

1
2
3
4
5
6
docker run -it --rm \
--name certbot \
-v /mnt/letsencrypt:/etc/letsencrypt \
-v /mnt/bak/letsencrypt:/var/lib/letsencrypt \
certbot/certbot \
certonly --manual --agree-tos --server https://acme-v02.api.letsencrypt.org/directory --preferred-challenges dns -d *.YOUR-DOMAIN.com -d YOUR-DOMAIN.com

具体的命令释义如下:

1
2
3
4
5
6
-v /mnt/letsencrypt:/etc/letsencrypt -v /mnt/bak/letsencrypt:/var/lib/letsencrypt # 挂载目录,certbot申请到的或备份的证书会放在这两个目录
--manual # 交互模式
--agree-tos # 同意服务协议
--server https://acme-v02.api.letsencrypt.org/directory # 指定使用acmev2协议的服务器,因为通配符证书的申请需要这个协议
–preferred-challenges dns # 使用dns检验来证明你拥有这个域名
-d *.YOUR-DOMAIN.com -d YOUR-DOMAIN.com # 指定了需要申请证书的通配符域名,根域名要额外再写一次

Read More

热敏打印机原理及其驱动相关知识

【说明】本文内容均来自网络,用于学习热敏打印机相关知识。

热敏打印机的工作原理是打印头上安装有半导体加热元件,打印头加热并接触热敏打印纸后就可以打印出需要的图案。

热敏打印机化学反应是在高温下进行的,当温度低于60℃时,纸需要经过相当长,甚至长达几年的时间才能变成深色;而当温度为200℃时,这种反映会在几微秒内完成。

打印机安装驱动的原因就是打印机厂商千差万别,不同的打印机往往都有各自的驱动,很难实现万能驱动。但是,在 POS 打印机行业却有一条捷径,就是现在市面上的 POS 打印机基本上都支持爱普生指令,也就是说,只要将程序和打印机联通,直接向端口里面写爱普生指令就可以控制打印机,打印机接受到爱普生指令以后,自行进行解析,然后打印出相应的内容。

Read More

cannot recover key

Android studio 运行项目报错 can not recover key,找了半天发现 keystore 和 key password 必须保持一致才行。可以找到刚才生成的 jks 文件,然后用下面两条命令把密码改成一致:

1
2
keytool -storepasswd -new [新的 keystore 密码] -keystore [jks文件路径]
keytool -keypasswd -alias [新别名] -new [新密码] -keystore [jks文件路径]

axios忽略https证书错误

使用 axios 请求 https 网站的数据时,如果证书已过期,会报错:

1
Error: certificate has expired

可以使用下面的方法忽略证书错误:

1
2
3
4
5
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' // 不拒绝过期的和无效的证书
const agent = new https.Agent({
rejectUnauthorized: false
})
axios.get('https://something.com/foo', { httpsAgent: agent })

jenkins 学习笔记

这里采用 docker 容器来安装和部署 jenkins,首先下载官方镜像:

1
docker pull jenkins/jenkins:lts

然后启动:

1
2
3
4
5
6
7
8
9
# 临时运行
docker run -p 8080:8080 -p 50000:50000 jenkins/jenkins:lts

# 长期维护
docker volume create jenkins-data # 创建数据卷
docker run -d -p 8080:8080 -p 50000:50000 \
-v jenkins-data:/var/jenkins_home \
--name jenkins \
jenkins/jenkins:lts

然后命令行会随机生成管理员密码,先记下来,如果忘了,也可以用下面的命令查看:

1
cat /var/jenkins_home/secrets/initialAdminPassword

Read More

yarn 安装时出现 node incompatible

今天用 yarn 安装依赖失败,报下面的错:

1
The engine "node" is incompatible with this module. Expected version ">=4 <=9". Got "10.14.2"

网上很多人说用 yarn --ignore-engines 可以解决这个问题,然而这样做是有风险的。这个问题产生的原因是依赖包 upath 导致的,它在 package.json 里面限制 node engine 只能是 4~9 版本的,只要把 upath 给升级就行了,解决方法如下:

1
2
3
rm -rf node_modules/
rm yarn.lock
yarn install

这样就会更新 upath 到最新版本。

centos 安装 mozjpeg

首先安装 nasm 环境:

1
yum -y install build-essential nasm libtool

然后下载源码编译:

1
2
3
4
5
6
7
wget https://github.com/mozilla/mozjpeg/archive/v3.3.1.zip
unzip v3.3.1.zip
cd mozjpeg-3.3.1
autoreconf -fiv
./configure
make
make install

安装后的可执行文件所在的目录是 /opt/mozjpeg/bin

1
2
3
4
5
6
7
8
[root@VM_156_24_centos mozjpeg-3.3.1]# ls -hl /opt/mozjpeg/bin
总用量 268K
-rwxr-xr-x 1 root root 56K 1月 23 10:04 cjpeg
-rwxr-xr-x 1 root root 45K 1月 23 10:04 djpeg
-rwxr-xr-x 1 root root 53K 1月 23 10:04 jpegtran
-rwxr-xr-x 1 root root 14K 1月 23 10:04 rdjpgcom
-rwxr-xr-x 1 root root 63K 1月 23 10:04 tjbench
-rwxr-xr-x 1 root root 14K 1月 23 10:04 wrjpgcom

a.jpg 按照 80% 的压缩率保存到 a1.jpg

1
/opt/mozjpeg/bin/cjpeg -quality 80 a.jpg > a1.jpg

cjpeg 默认的压缩率是 75%,-quality 参数可以自定义压缩率。

gulp 学习笔记

在 gulp 的任务中,gulp.src 接口将匹配到的文件转化为可读的文件流,通过 .pipe 流经各插件进行处理,最终推送给 gulp.dest 所生成的可写文件流,生成文件写入磁盘。其中涉及到下面几个重要的库:

Vinyl

Vinyl 是一个文件描述器,通过它可以在内存中构建临时文件对象。

1
2
3
const Vinyl = require('vinyl')
const empty = new Vinyl()
console.dir(empty)

最终打印出来:

1
2
3
4
5
6
7
File {
stat: null,
_contents: null,
history: [],
_cwd: '/job/gulp-tutorial',
_isVinyl: true,
_symlink: null }

Read More

Angular 中 video 自动静音播放

在页面里面加了一个 video,想让这个视频在页面加载之后自动播放,用下面的写法:

1
2
3
4
5
6
7
8
9
10
11
 <video
id="officeVideo"
preload="metadata"
poster="assets/media/office.jpg"
playsinline
autoplay
muted
loop
>
<source src="assets/media/office.mp4" type="video/mp4" />
</video>

但是在谷歌浏览器下测试,发现第一次可以自动播放,再刷新就暂停了,很奇怪,网上找了一些解决方案开始尝试,例如下面的代码用 jQuery 找到这个 video 元素,手动调用 play 函数:

1
2
3
const el = $('#officeVideo')
const video = el.get(0)
video.play()

Read More

MongoDB查询空值

JavaScript 中有 undefined 和 null 两种表示空的类型,在用 MongoDB 查询的时候,也会遇到这种情况,例如插入下面的文档:

1
2
3
4
5
db.getCollection('products').insertMany([
{ name: "巧克力", department: null },
{ name: "牛奶" },
{ name: "蛋糕", department: "糕点类" }
])

如果用 $exists 操作符查询 department 不存在的商品:

1
db.getCollection('products').find({department:{$exists: false}})

我们发现就只会得到牛奶:

1
2
3
4
5
[
{
"name" : "牛奶"
}
]

Read More