解锁新年

今年是个暖冬,去年的此时,还下了一场小雪,而今年一切都平静了很多。临近年底,人却得了感冒,各种发炎,喉咙像冒了火,一直咳嗽,病怏怏的弄了好几天,吃药也不见效果。

时间飞逝,新年的倒计时还是如约而致,都想用一些特别的方式来致敬新的一天,当然对于自己来说,其实可选的也就是跑步了。临近的这两年也都有报名,但种种原因,空气质量、气温过低,熬夜等等原因,都让自己没能战胜被窝。而今年又恰逢生病。

朋友都建议感冒放弃,但对于我,这个起跑的意义似乎又大了一些,不止是一场跑步,而是一个态度,一种对待未来,对待难题的态度。于是乎,没有选择就是最好的结果。

定好了 5:20 的闹钟,相对于上海的比赛,会发现每次外地的比赛会有更多的休息时间,因为会住附近的酒店,酒店会有早餐,等等。

为了御寒,翻出来好久不穿的长裤,准备了 3 件跑步的短袖,又准备了一件外套。加了一件薄款的羽绒服,出门时用。

最后一个交易日,市场行情也琢磨不定,没再多花心思。

> 赛事

6 点上海的冬日,还是挺冷的,走在高架上,城市的建筑笼罩在淡淡的黑色中,房顶镶着金红色的边,一切都这般的美。南京路上的彩灯应该是通宵的,回想在它乡的傍晚,不禁感叹了上海这个不夜之城。

存包,预热,等开赛,哦,忘记说了,这次的迎新赛事是静安区举办的,从静安寺出发,过石门一路、上海站到前闸北公园。静安一直都很高大上,这次,终于有机会用另一种方式看看这个区域。

在存包里,没有脱掉里面的跑步外套,于是穿着有史最厚的衣服,开始漫漫征途,不知是不是冷的原因,耳机一直有种要掉的感觉,于是取了下来拿在手里。

南京路的灯光在晨光中漫漫暗了下去,随即转入其它的道路。边上的建筑也开始从金碧辉煌变得普通起来,陆续开始有民宅,街上的行人也开始多了。

大约过了 4 公里,才隐约感觉身上开始起热,这是多冷的天呀。

边上跑了一位静安公安的帅哥,一路上就见他和周边的警察打招呼,像是在自己的主场。

可能是不用担心散热问题,一路跑下来感觉很轻松,没有因为劳累而采用跟随策略,也很放空,所以全程很舒服的一个状态就差不多结束了。

赛事的最后一公里,是穿越一个隧道,下坡时那种感觉真的健步如飞,而平时所有的隧道都是开车经过的,跑起来的距离感明显不同。在后面的爬坡路段,因为临近终点,所以也是满速向前的,感觉心率都 180 了。

解锁城市

我很喜欢用脚步去丈量城市,这样的速度能让人看到更多,这样的疲惫更让人印象深刻。

随车开过的地方,总像两个场景,人在车里,而城市在车外。

生活需要感悟,用的是慢速度。

> 祝语新年

拿到奖牌,拍了两张照,到附近的咖啡厅休息,临窗的位置刚好有阳光晒进来,照在身上,暖暖的,一杯太妃的甜唤醒一年的美好。

我是个定了计划会想尽千方百计去完成的人,这也是为什么会在意新年第一天的计划。

保持好节奏,新的一年,接着干!全力冲梦想!

2019 回顾 - 我的设备

2019 又要结束了,回望这一年真的是经历颇多,感触也不少。想写一些东西来记录下,但又不知如何下笔。打开电脑,盒上电脑,换台电脑,反复间,好像一个轮回,于是想找一些简单的话题先开始写写。

作为一个数码爱好者,就从身边的设备写起吧。

> 显示器

年初时心痒痒,一心想入手点东西,思来想去,还是换个显示器吧,当时在公司,两台 U2518 来回接线的体验一点都不好,就定来下这次买显示器,指标上一定要支持 USB Type-C,这样一根线可以充电、传数据、接显示器。选了好久,甚至做了张表单,最后才定了 U3218Q(从官方通过 QQ 下单的感觉很复古),主要参数:

  • 32寸
  • 4K
  • USB Type-C (内建 DP1.4,PD 60W,USB 3.0)

32 寸大屏配上窄边框的视觉效果非常好,4K 的分辨率显的字有点小。但常用的工作模式依然是 4K,把编辑器的字体放大点就好,也偶尔也尝试在 3360x1890 下。字体大小会更舒服一些,但会有缩放产生的模糊。

最近需要聚焦的工作,全新尝试 1920x1080,没想到效果非常的好,一来显示面积小了,就不会去打开一些多余的软件摆在可视区域,减少了视觉噪音。二来,这就是标准的 HiDPI,清晰度非常的高,视觉上带来了全新体验。

如果是 6K/7K,打开 HiDPI 便是极好。

年中 Apple 预告了 Pro Display XDR。这简直就是爱情的模样了。直到价格出来 :(。
如果 DELL 能出这么一款,就用 LCD 普通面板,价格在 1W 多,该多好呢。

> 电脑

18 年底入了台 15 MacBook Pro 中配,16G 内存加升 512 SSD,一切正常,表面上贴满了标志,经常连笔记本键盘使用,整机非常新。

这个机器的键盘依然是蝶式,有好几个朋友的同款都已经维修过了。

因为太过正常,所以没什么感觉,就是最近经常出差,带上这么重的一东西,肩膀有点受不了。即使是换了双肩包后。

公司的一台 DIY PC,因办公地点原因,现在家使用,了解了下 UEFI 并安装好最新的 macOS Catalina 后,这台 Hackintosh 成了现在的办公主力。

毕竟 32G 内存,i7-8900K 的配置做什么都不在话下,速度带来的幸福感提升还是很明显的。

要说问题吗,就是这么大的机箱,在房价的面前显的有点昂贵。

用完黑苹果后,也有考虑过 NUC,但还是等它出了 USB-C 供电版本后再说吧。

当然如果 iMac 出一款 32 寸屏幕的话,那便是极香的。毕竟是一直想再入一台 iMac 的,直到 3218 用过后再也回不到 27 的屏了。

> 键盘鼠标

从日本带了几把 Filco Minila Air,留下了 Brown 和 Black,但 Black 实在太重了,出掉后,又跑秋叶原入了一把双模 87 Brown,当然还是大F。

论手感 Minila 真的很赞,很紧致,87 有点旷的感觉。同样的茶轴,有两种不一样的感觉。

但蓝牙 3 的品质真的是头疼,现在 87 是用有线连接使用,Minila 则在包里随我征战各方。

Magic Mouse 1 已经用了大约 7 年了,算是长情,虽然一直会断开重联,但也没想过要换掉,就一直在包里随用随取。

她的灵魂在于上面那个触摸板。

G903 陪了我一年,电池已经不怎么行了。但优雅的造型和清晰的指向,清脆的点击,都深得我心。

当下这款有个 Bug,按键会失灵,官方会换新,这就是我的期待。

> 手机

今年入手了一台小米 9SE,主力机器依然是 iPhone X。

入米九的原因主要是公司的华为测试机太难用了,而 iPhone 不支持 NFC,这对于上下班刷门卡来说,太不方便了,同时还有夜景的需求。9SE 的大小和 iPhone X 一致,叠放时比较方便拿。

iPhone X 表现依然超凡,外形上也很漂亮,像件实用的艺术品,一直在服务着,从没掉过链子,这一点小米就完全不行,在稍差点的环境中,简直就是个 Bug。

iPhone 11 在店里感受了下,说实话,真心没感动。更像是疲劳期,对新的东西也没什么更高的期待。

iPad Pro 今年的使用率稍微高一点点,主要是各种画图,也就是那支笔。经常拿出来画一些架构图,流程图之类,或做一些速记。

> 手表

Apple Watch 4 好像是今年买的。一直带着,设定好了指标,坚持完成着,几乎没有间断。

常和朋友开玩笑说:一直以为自己保持身材的秘方只是贫穷,后来看到 Apple Activity 记录时,才发现还是有很多的努力的。

> HomePod

记不清是什么时间入的了,在香港广场,带着她坐 71 路回的家。

使用频率还可以。满意度很高,虽然偶尔也会断线,但相对于之前的那款水晶音箱来说,这连接便捷性,连接品质和音质都让人很满意。

安安静静的放在书房的桌面,你用她时,她都在,无论从哪个设备连接,都很快,很少出问题,简直就是完美了,除非哪天想不开,叫了声 Hey Siri。

> AirPods

AirPods 2 是刚出的第二天在香港广场入的。这款产品是今年所有产品里使用率最高的了,几乎每天都带在耳朵上。

起初担心跑步会掉,还用个头巾包住,后来各种长跑、马拉松,耳机都是必备了。

音质不做评论,不专业。但苹果对蓝牙的把控,真的是绝世高手,蓝牙耳机玩过很多,但 AirPods 这种多机共联,而且如此稳定,快捷的,也只能是苹果了。

不便的话,就是调节音量了。

AirPods Pro 去南京东小试了下,有点想吐,是中号的耳塞,Apple 说有马达通风来保证耳道压强,但自己从小就不喜欢入耳式。

> 小结

这些设备早已超出自身的范畴了,她们带来各种功能、便利性的同时,也在影响着生活的方式。

安静时,找个沿江的 Bar,听着音乐,发发呆,做些有创造性的工作,亦或写写人生感悟。傍晚时分,用新的夜景模式去拍拍城市的灯光。

2020 生活还会继续,而这些设备也会继续安静的服务着生活。

Homebrew in Action [revised]

▎介绍

Homebrew 作为 macOS 上强大的包管理器,为系统软件提供了非常方便的安装方式,独特式的解决了包的依赖问题,并不再需要烦人的 sudo,一键式编译,无参数困扰,值得拥有。


▎安装

Homebrew 依赖于 Xcode Command Line 和 Ruby。可以在终端中输入下面命令查看本机的 Ruby 安装情况。

1
$ ruby -v

确认 Ruby 可被正常使用后,继续输入下面命令,进行 brew 的安装:

1
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

> 安装背后

Homebrew 将本机的 /usr/local 目录初始化为 Git 的工作树,并将目录所有者变更为 $USER,也就是你当前所操作的用户,所以以后的操作都不再需要 sudo,这是安全的,全新的 macOS 默认是没有该目录的,也就是说该目录并非是系统所有。

/usr/local 下创建以下目录:

1
2
3
4
5
6
- bin          用于存放所安装程充的启动链接(相当于快捷方式)  
- Cellar 所有 brew 安装的程序,都将以[程序名/版本号]存放于本目录下
- etc brew 所安装程序的配置文件默认存放路径
- Library Homebrew 系统自身文件夹
+– Formula 程序的下载路径和编译参数及安装路径等配置文件存放地
+– Homebrew brew 程序自身命令集

上述为 Homebrew 所用用到的几个目录,其它也有使用,但于 brew 关联不大,请参考 Unix 系统相关资料。

最后,将 brew 的程序启动项放到 /usr/local/bin 下,所以,必须保证该目录属于 Bash 的环境变量,关于如何配置环境变量,请查阅相关资料。


▎开始使用

用 brew 安装第一个程序,这里使用 node 作为示例

1
$ brew install node

有些程序会同时提供两个下载,一个为稳定版,另一个为尝鲜版(通过head参数获取),如果已安装过稳定版的程序后,想同时安装尝鲜版可以通过 force 参数来完成。

1
2
$ brew install --HEAD node
$ brew install --force --HEAD node

接下来可以看到 brew 启动下载,通过 Formula 目录中的 node.rb 文件中的路径去下载源码,然后就是 configure,同时指定 prefix 到 Cellar 目录,接下来 make & install。最后,将 node 的运行文件通过软链接到 /usr/loca/bin 下,方便命令行启用。因为 /usr/local 的目录所有者为当前用户,所以这里不再需要 sudo 进行提权,很方便。

然后,可以很方便的通过以下命令来卸载所安装程序

1
$ brew uninstall node
1
2
# 显示当前所有已安装程序的名称
$ brew list

Homebrew 提供 update 参数来对系统进行更新,其实就是对 Formula 目录进行 Git pull,将服务器最新的程序安装配置文件同步到本地,同时,会标明新加入和更新,同时会对本机已经安装并有更新的程序用*号来标名。

1
$ brew update

通过 outdated 命令查看哪些 Formula 有更新

1
$ brew outdated

如果看到已安装程序有更新版本,像 Node.js 刚发布 13.5.0,这里运行完 brew update,会看到node*的标志出现,运行以下命令来安装最新版的 Node.js 13.5.0。

1
2
$ brew upgrade [formula]
$ brew upgrade

这时会出现和安装一样的过程,再次在终端中输入 node -v 可看到已是最新版本。但如果同时出现多个程序的升级,一个个通过程序名升级未免过于麻烦,这时,试下下面的这条命令,所有有更新的程序都会被自动下载,编译安装。

安装完最新版本后,旧的版本会自动删除,但仍有旧版本存在的可能性,可通过 cleanup 命令来删除,和 upgrade 一样,提供单程序和所有程序旧版的移除。

1
2
$ brew cleanup [formula]
$ brew cleanup

如何知道 Homebrew 官方是否有某个程序的安装呢,通过 search 命令来查看

1
$ brew search [formula]
查看已安装程序信息,brew 提供了 info 和 list 参数:
1
2
3
4
5
$ brew info [formula]
显示该程序的安装路径,相关提示及 formula 服务器所在位置

$ brew list [formula]
# 显示该formula的所有文件列表

▎介绍 Bottles

Mac 的平台特性比较标准和简单,比如说只有不多的 macOS 版本,CPU 架构也会比较简单只有 X64 64Bit。

在这种条件下,如果每个人都要下载源码,然后再 build,会浪费大量的时间。如果能按平台、架构来提前构建好,直接使用编译后的二进制,就会省下很多时间。

这就是 Homebrew Bottles。

brew 在安装应用时,会先去查一下对应机器和环境的 Bottle 是否存在,如果存在就下载。如果不存在或下载失败,则进行二进制源码下载、构建安装。


▎介绍 Cask

这是 cli 的部分:https://github.com/Homebrew/homebrew-cask
core,也就是最常装的 app,都在这里:https://github.com/Homebrew/homebrew-core
https://github.com/Homebrew/homebrew-cask-fonts

Homebrew-Cask extends Homebrew and brings its elegance, simplicity, and speed to macOS applications and large binaries alike.

一些传统软件的安装都是手工的点击下一步,如何实现自动化呢,Brew cask 就是做这件事情的。

像一些图形软件,商业软件,都可以通过 Cask 来进行安装,像 Google Chrome, VSCode,iTerm2 等。

homebrew-cask 现在默认集成在主程序中。

主要命令

1
2
3
4
5
6
7
$ brew cask tap 
# brew tap homebrew/cask-fonts

$ brew search [formula]

$ brew install [formula]
# 这里并没有用 brew cask install

常用的 Casks

cask-fonts

一些开源的字库,都在这里被包含了。


▎Formula 分析

所有的 formula 都在这个仓库里:https://github.com/Homebrew/homebrew-core

在终端中输入 brew edit [formula],启用默认编辑器打开该 formula。

1
2
3
4
5
6
7
8
9
10
class Wget < Formula
homepage "https://www.gnu.org/software/wget/"
url "https://ftp.gnu.org/gnu/wget/wget-1.15.tar.gz"
sha256 "52126be8cf1bddd7536886e74c053ad7d0ed2aa89b4b630f76785bac21695fcd"

def install
system "./configure", "--prefix=#{prefix}"
system "make", "install"
end
end

可以看出几个属性:

  • url 是指当前稳定版的下载路径
  • head 是尝鲜版的路径,可以使用 github 项目路径
  • homepage 指向到 formule 的官方网站
  • sha256 则对应 formula 的下载文件校验值
  • depends_on 属于用于解决依赖关系,brew如发现当前程序依赖其它程序,便会检查依赖程序是否已经安装,如未安装,则会先安装依赖程序的稳定版。
  • options 用来指定默认编译参数
  • install 则是安装的过程,指定编译参数,make & install
  • caveats 用作安装完成之后的输出提示。

> 制作自己的 Formula

Homebrew 提供 create 命令来快速创建一个新的 Formula,通过指定下载文件源码路径,或 github 程序位置(含可用版版本号,Git Tag)即可,创建完成后,会自动打开所新建formula的配置文件,填入homepage等参数,然后在终端中通过audit命令来进行检验。

1
2
$ brew create http://example.com/foo-0.1.tar.gz
$ brew audit foo

当然,如果你想将该程序保存到github上,可以直接fork Homebrew的项目,然后通过git进行commit,push到自己的fork中,也可以将该文件合并到官方的库中,参见github。

1
2
$ git commit Library/Formula/foo.rb
$ git push

▎国内用户

因为访问 github 及 bottles 比较慢,所以这样使用替换访问源的方式,来加速。

分别是 homebrew 本身,以及 homebrew bottles 两个部分的替换。

> 替换及重置 Homebrew 默认源

Homebrew 自身是使用 Github 来更新的,所以替换的方法是将 git 地址指向到新的境内的地址上即可。

- 清华

1
2
3
4
5
6
7
git -C "$(brew --repo)" remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git

git -C "$(brew --repo homebrew/core)" remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git

git -C "$(brew --repo homebrew/cask)" remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-cask.git

brew update

- 还原为默认

1
2
3
4
5
6
7
git -C "$(brew --repo)" remote set-url origin https://github.com/Homebrew/brew.git

git -C "$(brew --repo homebrew/core)" remote set-url origin https://github.com/Homebrew/homebrew-core.git

git -C "$(brew --repo homebrew/cask)" remote set-url origin https://github.com/Homebrew/homebrew-cask.git

brew update

> Homebrew Bottles 源

1
2
3
echo 'export HOMEBREW_BOTTLE_DOMAIN=https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles' >> ~/.bash_profile

source ~/.bash_profile

▎问答:

Q: 如何将第三方提供的 Formula 在本地使用?

A: Homebrew 暂不提供第三方源的支持,但官方已表示未来会加入该功能,所以现在能做的就是将第三方 formula 下载后,放到 /usr/local/Library/Formulas/ 然后用文件名作 formula 正常安装。
这里也提供一个非官方的源,安程程序会更多一些:https://github.com/adamv/homebrew-alt

Q: 关于 Ruby 的安装

A: 对于 Ruby 自身,更推荐使用 rbenv 来进行多版本的安装管理。

Q: 如何安装旧版本的 Formula?

A: 参见 http://stackoverflow.com/questions/3987683/homebrew-install-specific-version-of-formula

Q: 尝试着加了几个 Formula,怎么删除?

A: 到 /usr/local/Library/Formula 目录下,找到所加的formula对应文件,删除即可。如果你了解git,也可到/usr/local下运行 git clean -d -f,来清除未被track的脏数据。


▎参考:

OpenJDK 配置使用

OpenJDK 是 JDK 的开放源码版本,以 GPL 协议的形式发布,而 JDK 则是采用 JRL 协议,对商业使用进行收费。


## ▎OpenJDK Versions
### > OracleSDK / JavaSE

根据付费商业许可(但可供开发使用) , 适用于那些不想使用 GPLv2 + CE,或者将 Oracle JDK 与 Oracle 产品或服务一起使用的用户。


### > Oracle OpenJDK

Oracke 自身还维护着另一个协议的 Java 版本:OpenJDK,像是 RedHat 和 CentOS 的关系。

1
2
3
4
5
$ java --version

openjdk 12 2019-03-19
OpenJDK Runtime Environment (build 12+33)
OpenJDK 64-Bit Server VM (build 12+33, mixed mode, sharing)

### > AdoptOpenJDK

- AdoptOpenJDK builds

这些版本也是免费的、完全无品牌的 OpenJDK 版本,基于 GPL 开源协议(+Classpath Extension),以免费软件的形式提供社区版的 OpenJDK 二进制包,公司也可安全且放心使用。与由 Oracle 的 OpenJDK 构建版本不同,这些版本会提供更长的支持,像 Java 11 一样,至少提供 4 年的免费长期支持(LTS)计划。AdoptOpenJDK 是一个由社区驱动的项目,如果其他群组在 OpenJDK 的源码仓库中创建和发布了安全修复程序,它们也会提供构建。 IBM 和 Red Hat 也曾表示他们打算提供这些安全补丁。

1
2
3
4
5
6
7
8
9
brew tap AdoptOpenJDK/openjdk
brew search openjdk


Where version is:

adoptopenjdk
adoptopenjdk11-openj9
adoptopenjdk12

▎macOS x64 OpenJDK 安装

Make sure you have downloaded the latest macOS x64 jdk binary to a directory that will not move or be deleted, and use Terminal/Command Prompt to cd into it.

手动下载安装

提取 .tar.gz。将下载好的文件放到:/Library/Java/JavaVirtualMachines

使用 homebrew
1
2
brew tap AdoptOpenJDK/openjdk
brew cask install adoptopenjdk12
将此版本的 Java 添加到您的PATH中:
1
export PATH=$PWD/jdk-11.0.2+9/Contents/Home/bin:$PATH
1
2
3
4
5
6
# Set PATH for JAVA
# ===================
# export JAVA_HOME=/Library/Java/JavaVirtualMachines/adoptopenjdk-11.0.1.jdk/Contents/Home
export JAVA_HOME=/Library/Java/JavaVirtualMachines/openjdk-12.jdk/Contents/Home
export CLASS_HOME=$JAVA_HOME/lib
export PATH=$JAVA_HOME/bin:$PATH
检查Java是否正确安装:
1
2
3
4
5
$ java --version

openjdk 12 2019-03-19
OpenJDK Runtime Environment (build 12+33)
OpenJDK 64-Bit Server VM (build 12+33, mixed mode, sharing)

▎支持开源软件的哲学思考

软件产业已经普通认同开源软件推动了行业的发展。 由于其开源自由的性质 , OSS许可证允许人们修改和改编其他人的软件,而不用担心会受到惩罚。

许多人也喜欢 OSS 软件中 的 像啤酒一样免费 的性质,但这给作者带来了巨大的成本! 像其他任何人一样,软件开发人员需要生存。 像 Oracle 供应商 (每年至少投入上千万美金) 投入大量的资金 到 Java SE 的开发上,他们也需要获取相应的补偿。

所以,尽管你不会被强制付费去使用一个软件,但有时我们最终用户也应该思考一下如何能支持 Java SE 生态系统,以确保它有一个持久的未来!

编程最佳字体

最近一直在寻找一款适合自己书写和编程的字体。

中文是没有什么问题的。主要是英文。

需求是等宽字体,数字字母清晰可辨,像 0O1lI 这种。

对于编程最火的几个字体是:

  • Source Code Pro
  • SF Mono / Menlo / Monaco
  • FiraCode / Hack

> Source Code Pro

Adobe 出品,在一些常见的开源编辑器都是默认首选。

> SF Mono / Menlo / Monaco

这是一个递进关系的相关字体。

出新的系统已经换成了 San Francisco Mono

> FiraCode

也是开源字体里选择比较多的。

这几个字体都属于矮胖型的。有点不是很喜欢。

> Pragmata Pro

Pragmata Pro 从样式上是我最喜欢的,但是收费颇高,而且非 ASCII 标点支持的很差,对于需要大量中英混排的人来说,简直是个灾难。

如果它能解决标点问题,顺便把授权费用降低点,也会是一个不错的选择。

> Noto Sans Mono CJK SC

不过我最终还是找到了一个不错的字体。

  • 首先这个字体是中英文一体的,做了统一适配,不会出现中文和英文混排时的冲突。
  • 英文字体属于瘦高型的,符合需求。

缺点是:

  • 不能单独安装。需要安装整个 Noto Sans CJK SC
  • 对数字 0 没有中间标识。不易区分。
  • 和 Noto Sans Mono 不同,这款字体的英文是专门为 CJK SC 设计过的。

如何下载安装

https://www.google.com/get/noto/help/cjk/

NotoSansMonoCJKsc 一共有两个字重,分别对应下载文件:

或者通过 brew 来进行安装。

1
brew install font-noto-sans-cjk-sc

适用 APP

  • Markdown Editor
  • VSCode
  • iTerm

基本上常用的编辑器就是 VSCode,Markdown 以及最常用的终端。

这是 VSCode 的 FontFamily 设置:

1
'Noto Sans Mono CJK SC', 'SF Mono', 'Fira Code', Hack, Menlo, Monaco

snap/snapcraft 使用指南

为每个 Linux 桌面、服务器、云端或设备打包任何应用程序,并且直接交付更新。

snapcraft 是一个正在为其在 Linux 中的地位而奋斗的包管理系统,它为你重新设想了分发软件的方式。这套新的跨发行版的工具可以用来帮助你构建和发布 snap 软件包。接下来我们将会讲述怎么使用 CircleCI 2.0 来加速这个过程以及一些在这个过程中的可能遇到的问题。

# 介绍

> Channels

Channels allow users to subscribe to different release cadences for an app, be it by major version bumps or in-development releases.

$ sudo snap install docker –channel=17.03/stable

# 常用使用说明

1
2
3
4
5
6
7
8
9
$ snap download hello-world

# Fetching snap "hello-world”
# Fetching assertions for "hello-world”

# $ sudo snap ack hello-world_27.assert
# $ sudo snap install hello-world_27.snap

hello-world 6.3 from 'canonical' installed
1
2
3
4
5
$ snap list

# Name Version Rev Developer Notes
# <snip>
# hello-world 6.3 27 canonical -

# 背后的原理

现在系统装软件,都是用这个装的了。

/snap 目录下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
:/snap$ tree -L 1
.
├── bin
├── chromium
├── core
├── core18
├── gnome-3-26-1604
├── gnome-calculator
├── gnome-characters
├── gnome-logs
├── gnome-system-monitor
├── gtk-common-themes
├── node
├── postman
└── README

# 常用软件安装

Package any app for every Linux desktop, server, cloud or device, and deliver updates directly.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
find
abort Abort a pending change
ack Adds an assertion to the system
alias Sets up a manual alias
aliases Lists aliases in the system
buy Buys a snap
changes List system changes
connect Connects a plug to a slot
disable Disables a snap in the system
disconnect Disconnects a plug from a slot
download Downloads the given snap
enable Enables a snap in the system
find Finds packages to install
get Prints configuration options
help Help
info show detailed information about a snap
install Installs a snap to the system
interfaces Lists interfaces in the system
known Shows known assertions of the provided type
list List installed snaps
login Authenticates on snapd and the store
logout Log out of the store
prefer Prefer aliases from a snap and disable conflicts
refresh Refreshes a snap in the system
remove Removes a snap from the system
revert Reverts the given snap to the previous state
run Run the given snap command
set Changes configuration options
tasks List a change's tasks
try Tests a snap in the system
unalias Unalias a manual alias or an entire snap
version Shows version details
watch Watch a change in progress
  • Download snap “core” (3017) from channel “stable” (The download has been cancelled: context canceled)

core 16-2.28.1 canonical - snapd runtime environment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ sudo snap install --help
Usage:
snap [OPTIONS] install [install-OPTIONS] <snap>...

The install command installs the named snap in the system.

Application Options:
--version Print the version and exit

Help Options:
-h, --help Show this help message

[install command options]
--channel= Use this channel instead of stable
--edge Install from the edge channel
--beta Install from the beta channel
--candidate Install from the candidate channel
--stable Install from the stable channel
--devmode Put snap in development mode and disable security confinement
--jailmode Put snap in enforced confinement mode
--classic Put snap in classic mode and disable security confinement
--revision= Install the given revision of a snap, to which you must have developer access
--dangerous Install the given snap file even if there are no pre-acknowledged signatures for it, meaning it was not
verified and could be dangerous (--devmode implies this)
--unaliased Install the given snap without enabling its automatic aliases

一个问题,这玩意太慢了,有没有办法加个代理,换个 mirror
或者先离线下载,然后再手动安装呢????

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
Usage:
snap [OPTIONS] <command>

Install, configure, refresh and remove snap packages. Snaps are
'universal' packages that work across many different Linux systems,
enabling secure distribution of the latest apps and utilities for
cloud, servers, desktops and the internet of things.

This is the CLI for snapd, a background service that takes care of
snaps on the system. Start with 'snap list' to see installed snaps.


Application Options:
--version Print the version and exit

Help Options:
-h, --help Show this help message

Available commands:
abort Abort a pending change
ack Adds an assertion to the system
alias Sets up a manual alias
aliases Lists aliases in the system
buy Buys a snap
changes List system changes
connect Connects a plug to a slot
disable Disables a snap in the system
disconnect Disconnects a plug from a slot
download Downloads the given snap
enable Enables a snap in the system
find Finds packages to install (aliases: search)
get Prints configuration options
help Help
info show detailed information about a snap
install Installs a snap to the system
interface Lists snap interfaces
interfaces Lists interfaces in the system
known Shows known assertions of the provided type
list List installed snaps
login Authenticates on snapd and the store
logout Log out of the store
logs Retrieve logs of services
prefer Prefer aliases from a snap and disable conflicts
refresh Refreshes a snap in the system
remove Removes a snap from the system
restart Restart services
revert Reverts the given snap to the previous state
run Run the given snap command
services Query the status of services
set Changes configuration options
start Start services
stop Stop services
switch Switches snap to a different channel
tasks List a change's tasks (aliases: change)
try Tests a snap in the system
unalias Unalias a manual alias or an entire snap
version Shows version details
watch Watch a change in progress
whoami Prints the email the user is logged in with.

# 实例

安装 Node 10 LTS

https://snapcraft.io/node

sudo snap install node –channel=10/stable —classic

竟然自带了 yarn

删除呢?

Linux 环境变量配置(翻新)

Linux 是多用户操作系统,每个用户登陆后都有属于自己的环境,定义着自己专有的变量值。同时 Linux 是基于文件,和 Windows 的注册表很不相同。

本文是基于 Ubuntu 所写,其它 Linux 系统设置其本雷同。2018/12/18 升级内容到 18.04 版本。

举例来说,在终端下,你输入一个命令,会出现 Command not found , 但系统中已经安装过该程序,只是不在标准位置,此时你只能通过全路径的方式来执行 /usr/local/app/bin/run,但每次输入很是繁琐,这时就可以通过添加该目录到系统环境变量 PATH 中来实现执行文件的查找。

http://imcn.me/wp-content/uploads/2010/04/ubuntu-ad1.jpg


# 变量认识及使用

> 显示当前所有的变量值

环境变量是在终端(Shell)中被使用,也可以通过 Shell 来对其进行操作,所有变量值均使用大写。

打印所有变量值:

1
2
$ env
$ export

打印系统 PATH 中的所有路径:

1
$ echo $PATH

打印 USER 变量值:

1
$ echo $USER

也可通过 set 来显示本地定义的变量集

> 设置新的变量

在 Shell 中,可以通过 export 命令来设置新的变量,如下,创建新的变量 MYVAR

1
2
$ export MYVAR=”lanvige.com”
$ echo $MYVAR

> 使用 readonly 命令创建只读变量

1
2
$ export MYVAR=”lanvige.com”
$ readonly MYVAR

> 清除环境变量

在 Shell 中可以使用 unset 命令来清除变量值

1
$ unset MYVAR

> 常用到的环境变量

1
2
3
4
5
PATH          决定了shell将到哪些目录中寻找命令或程序
HOME       当前用户主目录
LOGNAME/USER   当前用户的登录名
HOSTNAME     指主机的名称
SHELL       前用户Shell类型

# 环境变量模式

> interactive & non-interactive | 交互式和非交互式

其实 BASH 有两种工作模式,就是:交互式和非交互式

交互式模式:就是在终端上执行,shell 等待你的输入,并且立即执行你提交的命令。这种模式被称作交互式是因为shell与用户进行交互。当你退出后,shell也终止了。

非交互模式:以 Shell Script(非交互) 方式执行。在这种模式下,Shell 不与你进行交互,而是读取存放在文件中的命令,执行它们。当它读到文件的结尾EOF,Shell 也就终止了。

区别:读取的配置文件不同,交互式读取 ~/.bashrc 文件;非交互式读取的是环境变量 BASH_ENV(通常情况下)所指定的配置文件。

> login shell & non-login shells | 登陆 Shell 与非登陆 Shell

用文本方式登录之后,得到的就是一个 login shell,如果在这个 shell 里执行一下 bash 命令,就得到一个 non-login shell

对于用户来说,login shellnon-login shell 的主要区别是:启动 shell 时所执行的 startup 文件不同。

  • 登陆 shell 执行文件为:/etc/profile~/.profile~/.bashrc
  • 非登陆 shell 执行的文件仅为:~/.bashrc,如果在运行之前,修改 profile 文件的话对它不起作用。。

~/.profile: 是 interactive & login shell 方式进入 bash 运行的
~/.bashrcinteractive & non-login 方式进入 bash 运行的

通常二者设置大致相同。在系统中前者会调用后者。


# 配置环境变量文件

> 认识环境变量文件

在 Ubuntu 18.04 中有如下文件可以设置环境变量,对应着系统级别[所有用户]和用户级别[个人用户],分别放在 /etc/~/ 下。同时这几个文件有着明确执行顺序。

- /etc/profile || /etc/bash.bashrc

系统登录时,定制用户环境时使用的第一个文件,为系统的所有用户设置环境变量,当用户第一次登录时,该文件被执行。

profile 中调用了 bash.bashrc。

- ~/.profile

交互式登录 shell - interactive & login shells,在 login 方式登陆时,该文件被执行,且仅执行一次。

该文件会在每次bash shell打开时被执行,在当前Shell中添加环境变量。

- ~/.bashrc

交互式非登录 shell - interactive non-login shells

当登录时以及每次打开新的 shell 时,该文件被读取。(non-login 形式执行时,读取此文件。若是以 login 形式执行,则不会读取此文件)
某用户专有设定文档,可以设定路径,命令别名,每次 shell script 的执行都会使用它一次

- ~/.bash_logout

当每次退出系统(退出bash shell)时,执行该文件。

> 各种模式的读取顺序

  • 图形模式登录:/etc/profile > ~/.profile
  • 图形模式登录后,打开终端时:/etc/bash > bashrc > ~/.bashrc
  • 文本模式登录时,顺序读取:/etc/bash > /etc/bashrc > /etc/profile > ~/.bash_profile
  • 从其它用户 su 到该用户,则分两种情况:
    • 如果带-l参数(或-参数,–login参数),如:su -l username,则bash是lonin的,它将顺序读取以下配置文件:/etc/bash > bashrc > /etc/profile > ~/.bash_profile
    • 如果没有带 -l 参数,则 bash 是 non-login 的,它将顺序读取:/etc/bash > /etc/bashrc > ~/.bashrc
  • 注销时,或退出su登录的用户,如果是longin方式,那么bash会读取:~/.bash_logout
  • 执行自定义的shell文件时,若使用bash -l a.sh的方式,则bash会读取行:/etc/profile > ~/.bash_profile,若使用其它方式,如:bash a.sh./a.shsh a.sh(这个不属于bash shell),则不会读取上面的任何文件。

# 实例:设置永久环境变量

刚已经演示如何添加环境变量,但通过 export 方式所添加变量值的生命周期仅为当前 shell,重新打开新的 shell 时,该变量会丢失,如何设置一个永久的变量值,可以根据你的需求将变量值添加到上述5个文件中的其中一个来实现。

如果我们想在变量中加入新的path,则可以如下:

1
$ vim ./bashrc

添加如下行在未尾,这里需考虑 PATH 查找优先级,如一个命令在不同的 PATH 中出现,会使用最前定义的 PATH 值,多个 PATH 间用:隔开。

1
export PATH="PATH=$PATH:<PATH 1>:<PATH 2>"

使其生效

刚有提到,当改变配置文件时,重启shell才能使其生效,但通过source命令也能达到同样的效果,如果修改的是.bashrc文件,则输入。

1
$ source ~/.bashrc

FAQ::


> rc 全称

配置文件 .bashrcrc 的含义是 resource configuration

> ISSUE: 执行脚本时的问题:

在 Unicorn&Nginx 的 Init 脚本配置中,需要使用 rbenv 中的shims,但 rbenv 的环境变量被配置在了~/.bashrc中,如果直接执行像unicorn来启动服务是没有问题的,但在脚本文件中调用 unicorn 就不行。会有 Command Not Found 的问题,在 sh 文件中配置 PATH 也不会生效。最后将rbenv的环境变量配置移动到 ~/.profile 中问题就解决了。


# REF::


Babel v7 指南

  1. 1. > plugin
  2. 2. > preset
  3. 3. >> preset-env
  4. 4. > 同时使用
  • 配置
    1. 1. > 配置文件 .babelrc
    2. 2. > JS code
    3. 3. > CLI Parameter
  • 开始使用
    1. 1. > @babel/cli | 静态编译
    2. 2. > @babel/register | 动态编译
    3. 3. > @babel/node | 动态编译
  • 实战
  • Babel 7 做出了重大升级,之前的配置已经完全不能使用。在项目升级到 Node 10 后,旧版本的 Babel 会报很多的错误,借机做了一次升级。


    ## 概念入门

    Babel 是一个转码器,它可以将 JavaScript 中的一个语法进行编译转换,以让旧的引擎支持。

    这里有两个重要的概念,plugin 和 preset。

    > plugin

    Babel 本质就是一个编译器,有着常见的三步:解析,转义和输出。哪些代码需要被转义,就是在 plugin 中定义的。plugin 对应的是 feature。

    可以在这里看到各个版本中对应的更新和 node 的支持度:http://node.green/

    下面列出了 ECMA 2015 版本中的变化点。每个点都是一个 plugin。

    • arrow-functions
    • block-scoped-functions
    • block-scoping
    • classes
    • computed-properties
    • destructuring
    • duplicate-keys
    • for-of
    • function-name
    • instanceof
    • literals
    • new-target
    • object-super
    • parameters
    • shorthand-properties
    • spread
    • sticky-regex
    • template-literals
    • typeof-symbol
    • unicode-regex

    更多版本 plugin 参见:https://babeljs.io/docs/en/plugins

    > preset

    preset 如果单独配置就会很长,很繁琐。而一些定义好的组合,被称为 preset,可以让更多的重用。

    在 Babel 7 之前,前用的 preset 是 latest, es2015, es2016, es2017。之后版本中,去掉了这种方式,换成了 stage-x 和 env。

    目前常用的 Preset 为:

    • env
    • stage-0
    • stage-1
    • stage-2
    • stage-3
    • flow
    • react
    • minify
    • typescript

    >> preset-env

    env 代替了 latest,官方主要推荐使用这种,env 就是根据你要使用的场景,智能帮你加载所需要的 plugins。

    它的默认配置如下:(但这样是很不推荐的,它会把所有的 plugins 都加载上,也就是会翻译为最古老的代码,增加翻译时间。)

    1
    2
    3
    {
    "presets": ["@babel/preset-env"]
    }

    推荐配合使用 targets,常用如下:

    • targets.esmodules bool 是否使用 esmodules
    • targets.node 配置 nodejs 的版本号
    • targets.browsers 配置浏览器的版本,智能加载所需要的 plugins
    • include / exclude 强制使用/不使用某个 plugins

    > 同时使用

    如果同时配置了 preset 和 plugin 时,编译器会按如下顺序进行解析:

    • Plugins 优先
    • Plugins 列表内的优先级是自前到后
    • Preset 里的优先级则从后到前

    配置

    Babel 是通过配置中的 Plugins 来进行编译,那如何使用配置呢?

    Babel 有几种使用方式

    • Configuration File
    • JS Code
    • CLI Parameter

    > 配置文件 .babelrc

    1
    2
    3
    4
    5
    6
    {
    "presets": [[
    "@babel/preset-env", { "targets": { "node": "10.4.1" }}]
    ],
    "plugins": ["@babel/plugin-transform-modules-commonjs"]
    }

    > JS code

    这种是在动态注入时使用,一般会应用于开发环境。用于 @babel/register 模式中。

    1
    2
    3
    4
    5
    require("@babel/register")({
    presets: [[
    "@babel/preset-env", { targets: { node: "10.4.1" }}]
    ]
    });

    > CLI Parameter

    这里的 CLI 指的是 @babel/cli 和 @babel/node。

    但参数的更高阶用法没有找到,比如说在 presets 后面使用 target

    1
    $ babel script.js --out-file script-compiled.js --presets=@babel/preset-env

    开始使用

    在使用场景上,会有两种方式:

    • 静态编译
    • 动态编译

    > @babel/cli | 静态编译

    通过下面命令来编译 js,然后将编译好的文件进行线上环境发布。

    1
    2
    3
    4
    5
    $ babel script.js
    # 额外指定配置
    $ babel script.js --out-file script-compiled.js --presets=es2015,react
    # 忽略 babelrc
    $ babel --no-babelrc script.js --out-file script-compiled.js --presets=es2015,react

    > @babel/register | 动态编译

    @babel/register 模块改写了 require 命令,为它加上一个钩子。此后,每当使用 require 加载 .js、.jsx、.es和 .es6 后缀名的文件,就会动态先用 Babel 进行转码,再进行 require。

    另外,由于它是实时转码,所以会产生效率问题,只适合在开发环境使用。

    需要注意的是,babel-register 只会对 require 命令加载的文件转码,而不会对当前文件转码。

    1
    2
    3
    4
    5
    6
    7
    require("@babel/register")({
    presets: [[
    "@babel/preset-env", { targets: { node: "10.4.1" }}]
    ]
    });

    require("./src/index.js");

    > @babel/node | 动态编译

    Babel 提供了 @babel@node,作为 @babel@register 的更高阶的封装,可以 runtime 编译,而且不用额外的中间层代码。

    1
    $ babel-node --debug --presets es2015 -- script.js --debug

    实战

    Server 端用 Node.js 10.4.1,开发中用到的 feature 列表中,只有一项还暂不支持:

    • es2015 module-commonjs

    所以在配置 babel 时,根据自己的需求,只需要单独引入就可以了,这样,编译出来的代码几乎相同了,.babelrc 配置如下:

    1
    2
    3
    4
    5
    {
    "presets": [[
    "@babel/preset-env", { "targets": { "node": "10.4.1" }}]
    ]
    }

    也可以写成:

    1
    2
    3
    {
    "plugins": ["@babel/plugin-transform-modules-commonjs"]
    }

    ## REF::