nodejs 安装其实非常简单,大部分情况下 Debian/Ubuntu 下只要使用包管理直接安装
sudo apt-get install nodejs
sudo apt-get install npm
即可。
可是今天网络环境太差,不是 npm package not found 就是 update 半天不动。
官网 提供的安装方式
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install -y nodejs
也是网络环境无法安装
所以使用 二进制 安装
在官网 https://nodejs.org/en/download/ 找到编译好的二进制文件
然后解压到 /usr/local
目录下
然后配置 vim ~/.zshrc
export NODE_HOME=/usr/local/node-v6.11.4-linux-x64/
export PATH=$NODE_HOME/bin:$PATH
使用命令检查
node -v
npm -v
输出即可。
在编写定时备份脚本时遇到一个需求,就是在 Bash 脚本中发送带附件的邮件。于是找到了 mutt。
Mutt 是一个命令行的邮件客户端,Mutt 能够轻松地在命令行发送和读取邮件。 Mutt 支持 POP 和 IMAP 协议。 尽管 Mutt 是基于命令的,但也同样有一个友好的界面。
如果不使用界面,使用 Mutt 命令发邮件也非常方便,只需要一条命令即可发送或者批量发送邮件。
E-mail管理程序。
语法
mutt [-hnpRvxz][-a<文件>][-b<地址>][-c<地址>][-f<邮件文件>][-F<配置文件>][-H<邮件草稿>][-i<文件>][-m<类型>][-s<主题>][邮件地址]
补充说明:mutt 是一个文字模式的邮件管理程序,提供了全屏幕的操作界面。
参数:
-a
<文件> 在邮件中加上附加文件。文件>-b
<地址> 指定密件副本的收信人地址。地址>-c
<地址> 指定副本的收信人地址。地址>-f
<邮件文件> 指定要载入的邮件文件。邮件文件>-F
<配置文件> 指定mutt程序的设置文件,而不读取预设的.muttrc文件。配置文件>-h
显示帮助。-H
<邮件草稿> 将指定的邮件草稿送出。邮件草稿>-i
<文件> 将指定文件插入邮件内文中。文件>-m
<类型> 指定预设的邮件信箱类型。类型>-n
不要去读取程序培植文件(/etc/Muttrc)。-p
在mutt中编辑完邮件后,而不想将邮件立即送出,可将该邮件暂缓寄出。-R
以只读的方式开启邮件文件。-s
<主题> 指定邮件的主题。主题>-v
显示mutt的版本信息以及当初编译此文件时所给予的参数。-x
模拟mailx的编辑方式。-z
与-f参数一并使用时,若邮件文件中没有邮件即不启动mutt。Debian/Ubuntu/Linux Mint 安装
sudo apt-get install -y mutt
发送一封简单的邮件(可能会被主流邮箱认为垃圾邮件,垃圾箱查看一下)
echo "Email body" | mutt -s "Email Title" root@einverne.info
进入命令行交互界面之后使用如下快捷键操作
t
改变接受者邮件地址c
改变 Cc 地址a
来增加附件q
退出y
来发送邮件发送带附件的邮件
echo "body" | mutt -s "mysql backup" root@einverne.info -a /mysql.tar.gz
读取文本中的信息作为内容
mutt -s "Test" xxxx@qq.com
添加多个附件
echo "body" | mutt -s "web backup" root@einverne.info -a /mysql.tar.gz -a /web.tar.gz
抄送和密送
echo "body" | mutt -s "title" -c cc@gmail.com -b bcc@gmail.com root@einverne.info
-c
来抄送-b
来添加密送-s
来添加标题-a
来添加附件设置发件人
编辑配置文件
vi /etc/Muttrc
添加如下内容,防止被作为垃圾邮件
set from="mutt@einverne.info"
set use_from=yes
set envelope_from="yes"
set realname="Ein Verne"
mutt@einverne.info 为发信地址
mutt 发送邮件略慢,需要等待一分钟或者更长才能发送成功,作为备份工具好好利用。
在使用 Spring Boot 构建一套 RESTful 接口的时候经常需要手工维护一份接口文档以提供给不同的客户端使用,有的时候手工维护成本太高,今天发现了一套自动化生成 RESTful 接口文档的工具 Swagger 。
Swagger 能根据 Spring Controller 接口自动生成一个文档页面,在代码中使用注解将接口文档注释,非常方便。 Swagger 整合到 Spring boot 项目中也非常方便。
在 pom.xml
中添加
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
最新的版本可以在 mvnrepository 上查到,或者上官网或者 github。
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket helloApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("info.einverne.springboot.demo"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
// 文档标题
.title("API 文档")
// 文档描述
.description("https://github.com/einverne/thrift-swift-demo/tree/master/spring-boot-demo")
.termsOfServiceUrl("https://github.com/einverne/thrift-swift-demo/tree/master/spring-boot-demo")
.version("v1")
.build();
}
}
通过@Configuration
注解,让Spring来加载该类配置。再通过@EnableSwagger2
注解来启用Swagger2。
apiInfo()
用来创建 API 的基本信息,展现在文档页面中。select()
函数返回一个 ApiSelectorBuilder
实例用来控制哪些接口暴露给 Swagger ,这里使用定义扫描包路径来定义, Swagger 会扫描包下所有 Controller 的定义并产生文档内容,除了被 @ApiIgnore
注解的接口。@ApiOperation注解来给API增加说明、通过@ApiImplicitParams、@ApiImplicitParam注解来给参数增加说明。
一个简单的注释
@ApiOperation(value = "创建用户", notes = "根据User对象创建用户")
@ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User")
@RequestMapping(value = "", method = RequestMethod.POST)
public String postUser(@RequestBody User user) {
users.put(user.getId(), user);
return "success";
}
详细的例子可以参考源代码 https://github.com/einverne/thrift-swift-demo
再添加注释后启动 Spring boot, 访问 http://localhost:8080/swagger-ui.html 即可看到API文档
@Api
注解用于类上,说明类作用
标记在方法上,对一个操作或HTTP方法进行描述。具有相同路径的不同操作会被归组为同一个操作对象。不同的HTTP请求方法及路径组合构成一个唯一操作。此注解的属性有:
注解ApiImplicitParam的容器类,以数组方式存储。
对API的单一参数进行注解。虽然注解@ApiParam同JAX-RS参数相绑定,但这个@ApiImplicitParam注解可以以统一的方式定义参数列表,也是在Servelet及非JAX-RS环境下,唯一的方式参数定义方式。注意这个注解@ApiImplicitParam必须被包含在注解@ApiImplicitParams之内。可以设置以下重要参数属性:
@RequestBody这样的场景请求参数无法使用@ApiImplicitParam注解进行描述
增加对参数的元信息说明。这个注解只能被使用在JAX-RS 1.x/2.x的综合环境下。其主要的属性有:
提供对Swagger model额外信息的描述。在标注@ApiOperation注解的操作内,所有的类将自动被内省(introspected),但利用这个注解可以做一些更加详细的model结构说明。主要属性有:
对model属性的注解,主要的属性值有:
响应配置
多个 Response
考虑到安全的问题,每次请求API需要对用户进行验证与授权。目前主流的验证方式采用请求头部(request header)传递token,即用户登录之后获取一个token,然后每次都使用这个token去请求API。如果想利用 swagger-UI 进行API测试,必须显式为每个需要验证的API指定token参数。这时可以为每个操作添加一个注解 @ApiImplicitParams,具体代码如下:
@ApiImplicitParams({@ApiImplicitParam(name = "TOKEN", value = "Authorization token", required = true, dataType = "string", paramType = "header")})
Swagger 提供了 enable
方法,可以通过设置该方法来选择开启 Swagger 来在线上环境禁用 Swagger。
@Bean
public Docket customImplementation(){
return new Docket(SWAGGER_2)
.apiInfo(apiInfo())
.enable(environmentSpeficicBooleanFlag) //<--- Flag to enable or disable possibly loaded using a property file
.includePatterns(".*pet.*");
}
如果使用 Spring @Profile 也可以
@Bean
@Profile("production")
public Docket customImplementation(){
return new Docket(SWAGGER_2)
.apiInfo(apiInfo())
.enable(false) //<--- Flag set to false in the production profile
.includePatterns(".*pet.*");
}
From: https://stackoverflow.com/a/27976261/1820217
平时在 Linux 上查看磁盘信息都使用 df -lh
, -l
显示本地文件系统, -h
来表示 human readable 。虽然 df 在一定程度上能够满足查询磁盘剩余空间的需求,但是这里要介绍一款强大于 df 的命令 —- di 。
使用如下命令安装
sudo apt install di
di 命令是 disk information 的缩写,直接运行 di 会有如下结果
di
Filesystem Mount Size Used Avail %Used fs Type
/dev/sda1 / 901.2G 188.3G 667.1G 26% ext4
tmpfs /dev/shm 7.8G 0.1G 7.6G 2% tmpfs
tmpfs /run 1.6G 0.1G 1.5G 4% tmpfs
cgmfs /run/cgmanager/ 0.1M 0.0M 0.1M 0% tmpfs
tmpfs /run/lock 5.0M 0.0M 5.0M 0% tmpfs
tmpfs /run/user/0 1.6G 0.0G 1.6G 0% tmpfs
tmpfs /run/user/1000 1.6G 0.0G 1.6G 0% tmpfs
tmpfs /sys/fs/cgroup 7.8G 0.0G 7.8G 0% tmpfs
/dev/sda1 /var/lib/docker 901.2G 188.3G 667.1G 26% ext4
di
默认的输出就是比较人性化的了。
看 di 的使用介绍 man di
就会发现 di 是这么介绍自己的
> di Displays usage information on mounted filesystems. Block values are reported in a human readable format. If the user or group has a disk quota, the values reported are adjusted according the quotas that apply to the user.
di -A
Mount fs Type Filesystem
Options
Size Used Free %Used %Free
Size Used Avail %Used %Free
Size Used Avail %Used
Inodes IUsed IFree %IUsed
/ ext4 /dev/sda1
rw,relatime,errors=remount-ro,data=ordered
901.2G 188.3G 712.9G 21% 79%
901.2G 234.1G 667.1G 26% 74%
855.4G 188.3G 667.1G 22%
60014592 1372538 58642054 2%
/dev/shm tmpfs tmpfs
rw,nosuid,nodev
7.8G 0.1G 7.6G 2% 98%
7.8G 0.1G 7.6G 2% 98%
7.8G 0.1G 7.6G 2%
2036725 741 2035984 0%
/run tmpfs tmpfs
rw,nosuid,noexec,relatime,size=1629380k,mode=755
1.6G 0.1G 1.5G 4% 96%
1.6G 0.1G 1.5G 4% 96%
1.6G 0.1G 1.5G 4%
2036725 777 2035948 0%
/run/cgmanager/fs tmpfs cgmfs
rw,relatime,size=100k,mode=755
0.1M 0.0M 0.1M 0% 100%
0.1M 0.0M 0.1M 0% 100%
0.1M 0.0M 0.1M 0%
2036725 14 2036711 0%
/run/lock tmpfs tmpfs
rw,nosuid,nodev,noexec,relatime,size=5120k
5.0M 0.0M 5.0M 0% 100%
5.0M 0.0M 5.0M 0% 100%
5.0M 0.0M 5.0M 0%
2036725 4 2036721 0%
/run/user/0 tmpfs tmpfs
rw,nosuid,nodev,relatime,size=1629380k,mode=700
1.6G 0.0G 1.6G 0% 100%
1.6G 0.0G 1.6G 0% 100%
1.6G 0.0G 1.6G 0%
2036725 4 2036721 0%
/run/user/1000 tmpfs tmpfs
rw,nosuid,nodev,relatime,size=1629380k,mode=700,uid=1000,gid=1000
1.6G 0.0G 1.6G 0% 100%
1.6G 0.0G 1.6G 0% 100%
1.6G 0.0G 1.6G 0%
2036725 36 2036689 0%
/sys/fs/cgroup tmpfs tmpfs
rw,mode=755
7.8G 0.0G 7.8G 0% 100%
7.8G 0.0G 7.8G 0% 100%
7.8G 0.0G 7.8G 0%
2036725 18 2036707 0%
/var/lib/docker/aufs ext4 /dev/sda1
rw,relatime,errors=remount-ro,data=ordered
901.2G 188.3G 712.9G 21% 79%
901.2G 234.1G 667.1G 26% 74%
855.4G 188.3G 667.1G 22%
60014592 1372538 58642054 2%
使用 -c
选项分割输出
di -c
s,m,b,u,v,p,T
"/dev/sda1","/","901.2G","188.3G","667.1G",26%,"ext4"
"tmpfs","/dev/shm","7.8G","0.1G","7.6G",2%,"tmpfs"
"tmpfs","/run","1.6G","0.1G","1.5G",4%,"tmpfs"
"cgmfs","/run/cgmanager/fs","0.1M","0.0M","0.1M",0%,"tmpfs"
"tmpfs","/run/lock","5.0M","0.0M","5.0M",0%,"tmpfs"
"tmpfs","/run/user/0","1.6G","0.0G","1.6G",0%,"tmpfs"
"tmpfs","/run/user/1000","1.6G","0.0G","1.6G",0%,"tmpfs"
"tmpfs","/sys/fs/cgroup","7.8G","0.0G","7.8G",0%,"tmpfs"
"/dev/sda1","/var/lib/docker/aufs","901.2G","188.3G","667.1G",26%,"ext4"
c 是 --csv-output
的缩写,为了便于程序解析
-t
参数在最后增加统计行
di -t
Filesystem Mount Size Used Avail %Used fs Type
/dev/sda1 / 901.2G 188.4G 667.0G 26% ext4
tmpfs /dev/shm 7.8G 0.1G 7.6G 2% tmpfs
tmpfs /run 1.6G 0.1G 1.5G 4% tmpfs
cgmfs /run/cgmanager/ 0.1M 0.0M 0.1M 0% tmpfs
tmpfs /run/lock 5.0M 0.0M 5.0M 0% tmpfs
tmpfs /run/user/0 1.6G 0.0G 1.6G 0% tmpfs
tmpfs /run/user/1000 1.6G 0.0G 1.6G 0% tmpfs
tmpfs /sys/fs/cgroup 7.8G 0.0G 7.8G 0% tmpfs
/dev/sda1 /var/lib/docker 901.2G 188.4G 667.0G 26% ext4
Total 1.8T 0.4T 1.3T 26%
di -s
默认更具 mount point 输出
di -sm
默认 mount pontdi -sn
不排序,按照挂载表 /etc/fstab 中顺序di -ss
按照特殊设备di -st
根据 filesystem typedi -sr
逆序输出排序方式可以组合使用,如:di –stsrm
:按照类型、设备、挂载点逆序排序。
di –strsrm
:按照类型、设备逆序、挂载点逆序排序。
di -fM
Mount
/
/dev/shm
/run
/run/cgmanager/fs
/run/lock
/run/user/0
/run/user/1000
/sys/fs/cgroup
/var/lib/docker/aufs
只打印 mount point
更多的 f 的选项可以直接参看 man di
虽然 di 提供了比 df 更多更强大的功能,但是也有其缺点,大部分的 Linux 发行版默认是没有预装的。
Maven 是一个项目管理工具,主要用于项目构建,依赖管理,项目信息管理。自动化构建过程,从清理、编译、测试和生成报告、再到打包和部署。Maven 通过一小段描述信息来管理项目。
安装之前先把 JDK 环境配置好。
Debian/Ubuntu/Linux Mint 下
sudo apt install maven
如果要手动安装则按照下面步骤
tar -zxvf apache-Maven-3.3.9-bin.tar.gz
sudo mv apache-maven-3.3.9/ /usr/local/
root身份修改配置命令 sudo vi ~/.bashrc
在文件最后添加:
#set Maven environment
M2_HOME=/usr/local/apache-maven-3.3.9
export Maven_OPTS="-Xms256m -Xmx512m"
export PATH=$M2_HOME/bin:$PATH
保存并关闭。
如果进行了上面步骤在任意目录中mvn命令不能使用,可以在 /etc/profile
文件后面加入下面三行 sudo vim ~/.bashrc
然后输入以下内容
Maven_HOME=/usr/local/apache-maven-3.3.9
export Maven_HOME
export PATH=${PATH}:${Maven_HOME}/bin
设置好Maven的路径之后,需要运行下面的命令 source ~/.bashrc 使刚刚的配置生效
Maven 最熟悉的一个概念就是 POM,Maven 项目会有一个 pom.xml 文件, 在这个文件里面添加相应配置,Maven 就会自动帮你下载相应 jar 包
<dependency>
<groupId>com.google.firebase</groupId> 项目名
<artifactId>firebase-admin</artifactId> 项目模块
<version>5.3.1</version> 项目版本
</dependency>
项目名-项目模块-项目版本 三个坐标定义了项目在 Maven 世界中的基本坐标,任何 jar,pom, war 都是基于这些坐标进行区分的。
groupId
定义了项目组,组和项目所在组织或公司,或者开源项目名称,一般为公司域名反写,比如 com.google.firebase 等等
artifactId
定义了 Maven 项目的名称,在组中的唯一 ID,在同一个项目中可能有不同的子项目,可以定义不同的 artifactId。 artifactId 也是构建完成项目后生成的 jar 包或者 war 包的文件名的一部分。
version
顾名思义,就是项目的版本号,如果项目维发布,一般在开发中的版本号习惯性加上SNAPSHOT, 比如 1.0-SNAPSHOT
根据上面的例子,比如上面定义的Maven坐标,可以在对应的中央仓库中 https://repo1.maven.org/maven2/com/google/firebase/firebase-admin/5.3.1/
目录下找到对应的文件。
scope
定义了依赖范围,如果依赖范围为 test ,那么该依赖只对测试有效,也就是说在测试代码中引入 junit 有效,在主代码中用 junit 会造成编译错误。如果不声明依赖范围则默认为 compile ,表示该依赖对主代码和测试代码都有效。
Maven 有以下几种依赖范围:
依赖范围和classpath 的关系
依赖范围 Scope | 编译classpath有效 | 测试classpath有效 | 运行classpath有效 | 例子 |
---|---|---|---|---|
compile | Y | Y | Y | spring-core |
test | - | Y | - | junit |
provided | Y | Y | - | servlet-api |
runtime | - | - | Y | JDBC 驱动 |
system | Y | Y | - | 本地的, Maven 仓库之外的类库 |
Maven 依赖调解 Dependency Mediation ,第一原则:路径最近者优先;第二原则:第一声明者优先。
SNAPSHOT 快照版本只应该在组织内部的项目或者模块之间的依赖使用,组织对于这些快照版本的依赖具有完全的理解和控制权。项目不应该依赖于任何组织外部的快照版本,由于快照的不稳定性,依赖会产生潜在的危险,即使项目构建今天是成功的,由于外部快照版本可能变化,而导致未来构建失败。
在上面介绍 Maven 的作用的时候提到了Maven 的两个核心概念:坐标和依赖,这也是 Maven 首要解决的问题。这里要引入 Maven 另外一个核心概念:仓库。 Maven 时间中通过坐标来定位依赖,Maven 通过仓库来统一管理这些依赖。
Maven 项目的每一个构件对应着仓库的路径为: groupId/artifactId/version/artifactId-version.packageing
Maven 的仓库分为远程仓库和本地仓库,当第一次运行 Maven 命令时,需要网络连接,从远程仓库下载可用的依赖和插件。而当以后在运行 Maven 命令的时候,Maven 会自动先检查本地 ~/.m2/repository
目录下的依赖,如果本地有缓存优先从本地获取,在找不到的情况下去远程仓库寻找。
常用的在线依赖查看网站
Maven 的生命周期是抽象的,实际行为都有插件完成。
清理项目,包含三个阶段
定义了真正构建时所需要执行的步骤
建立和发布项目站点
具体的流程可以参考下图
下面是一个标准的 Maven 工程
src/main/java - 存放项目.java文件;
src/main/resources - 存放项目资源文件;
src/test/java - 存放测试类.java文件;
src/test/resources - 存放测试资源文件;
target - 项目输出目录;
pom.xml - Maven核心文件(Project Object Model);
mvn archetype:create 创建Maven项目
mvn compile 编译源代码
mvn deploy 发布项目
mvn test-compile 编译测试源代码
mvn test 运行应用程序中的单元测试
mvn site 生成项目相关信息的网站
mvn clean 清除项目目录中的生成结果
mvn package 根据项目生成的jar
mvn install 在本地Repository中安装jar
mvn eclipse:eclipse 生成eclipse项目文件
mvnjetty:run 启动jetty服务
mvntomcat:run 启动tomcat服务
mvn clean package -DMaven.test.skip=true 清除以前的包后重新打包,跳过测试类
mvn clean package 清除以前的包后重新打包
平时开发环境使用的是 jetty,而 Java Web 有一个更好更快的服务器 Resin,这篇文章就来说一下什么是 Resin,以及在 Debug 中如何使用。
Resin是一个提供高性能的,支持 Java/PHP 的应用服务器。目前有两个版本:一个是GPL下的开源版本,提供给一些爱好者、开发人员和低流量网站使用;一种是收费的专业版本,增加了一些更加适用于生产环境的特性。
Resin也可以和许多其他的web服务器一起工作,比如Apache Server和IIS等。Resin支持Servlets 2.3标准和JSP 1.2标准。熟悉ASP和PHP的用户可以发现用Resin来进行JSP编程是件很容易的事情。Resin支持负载平衡,可以增加WEB站点的可靠性。方法是增加服务器的数量。比如一台Server的错误率是1%的话,那么支持负载平衡的两个Resin服务器就可以使错误率降到0.01%。到目前为止,Resin对WEB应用的支持已经远远超过Tomcat等各种大型的Server。
在 Resin 的官方 quick start 教程中有各大平台详细的安装指导。我在使用 apt 安装时没有成功,这里就记录下手工安装的过程。
在 http://caucho.com/download 网址下载, Resin 有两个版本, Pro 版和GPL开源版,个人使用开源基础版本已经足够。安装过程如下:
JAVA_HOME
中tar -vzxf resin-4.0.x.tar.gz
根据下载的最新版本解压cd resin-
./configure
更多参数参考 configure optionsmake
sudo make install
sudo resinctl start
, 或者运行 java -jar lib/resin.jar start
http://localhost:8080
可以使用 sudo resinctl stop
来停止运行,更多内容可以参考官方指南 。
第一步,添加 Resin Local 选项,在 IDEA 中 Run/Debug Configuration
中添加 Resin Local 选项
点击configure按钮,在弹出窗Application Servers中选择部分一中安装的Resin目录路径和目录下Resin的配置文件路径。
Run/Debug Configurations 中Server页面配置,基本都是默认。
Run/Debug Configurations 中Deployment页面配置,注意红色方框部分选择。选择resin.xml而不是JMX否则项目的index路径是localhost:8080/appname/ 而不是localhost:8080/
在Resin的服务器配置下 Depolyment中 Depolyment method:有 JMX 和resin.xml 两种选择, JMX 是把项目打包的文件放在resin 服务器下webapp下 只有在服务器启动时 才把项目给拷贝过去 无法在intellij中实时更新; resin.xml 是在C盘Temp 目录下 copy了一份resin.xml的配置文件 然后把服务器目录空间指向了你的项目工作空间 可以实现IntelliJ 修改实时更新。IntelliJ 默认的选择是JMX 所以我们要选中resin.xml模式。同时当项目 Artifacts 指向的目录是 ROOT 时 上图中的Use default context name(always true if depolyment method is JMX)取消勾选
执行build,得到war文件。执行resin run/debug,会自动在你选择的浏览器中打开项目index页面。也可以在IDEA下方的Application Servers面板中进行Resin的启动,停止等操作。Resin启动的打印信息也在此窗口显示。
antigen 是 zsh 的插件管理工具,在他 GitHub 主页上的一句话非常形象的解释了他的功能。
Antigen is to zsh, what Vundle is to vim.
curl -L git.io/antigen > antigen.zsh
或者
apt-get install zsh-antigen
如果使用过 Vim 的 Vundle 对 antigen 的配置应该不陌生。
source /path-to-antigen-clone/antigen.zsh
# Load the oh-my-zsh's library.
antigen use oh-my-zsh
# Bundles from the default repo (robbyrussell's oh-my-zsh).
antigen bundle git
antigen bundle heroku
antigen bundle pip
antigen bundle lein
antigen bundle command-not-found
# Syntax highlighting bundle.
antigen bundle zsh-users/zsh-syntax-highlighting
# Load the theme.
antigen theme robbyrussell
# Tell antigen that you're done.
antigen apply
使配置生效 source ~/.zshrc
可以从这个页面 查看更多的插件。
在程序中经常要使用到 Unix timestamp 和日期的转换,通常情况下都是Google一个时间戳转换的网页在进行转换,其实 Linux 命令中就有能够快速实现转换的命令。主要都是集中在 date 这个命令。date 命令主要用于显示或设定系统时间和日期。
Linux 用来修正系统的时区
sudo dpkg-reconfigure tzdata
选择 Asia > Shanghai
date +%s # 返回 11 位时间戳,%s 表示从 1970-01-01 0点(epoch开始的秒数
date +%s%3N # 返回 14 位时间戳,毫秒
date +%s%N # 返回 11 + 9 位纳秒
$ date +%s
1504516338
$ date -d @1504516338
Mon Sep 4 17:12:18 CST 2017
使用 -d
参数可以用来将输入 String 转成特定格式日期,如果不指定具体时间,date会使用 00:00:00
$ date -d "06/04/1989"
Sun Jun 4 00:00:00 CDT 1989
$ date -d "04 June 1989"
Sun Jun 4 00:00:00 CDT 1989
$ date -d "June 04 1989"
Sun Jun 4 00:00:00 CDT 1989
$ date -d "June 04 1989 12:01:01"
Sun Jun 4 12:01:01 CDT 1989
-d
选项也有一些其他很强大的功能,比如
$ date -d '5 minutes ago' # 5 分钟前的时间
Mon Sep 4 17:22:58 CST 2017
$ date -d '100 days' # 100 天以后的日期
Wed Dec 13 17:29:14 CST 2017
$ date -d '-100 days' # 100 天以前的日子
Sat May 27 17:30:01 CST 2017
$ date -d '100 days ago' # 同上
Sat May 27 17:31:10 CST 2017
$ date -d 'next monday'
Mon Sep 11 00:00:00 CST 2017
可以使用+来输出不同格式
date +%<format options>
比如
$ date '+%Y-%m-%d %H:%M:%S'
2017-09-04 17:38:46
Format options | Purpose of Option | Output |
date +%a | 缩略方式显示星期 (like Mon, Tue, Wed) | Thu |
date +%A | 全称显示星期(like Monday, Tuesday) | Thursday |
date +%b | Displays Month name in short (like Jan, Feb, Mar ) | Feb |
date +%B | Displays Month name in full short (like January, February) | February |
date +%d | Displays Day of month (e.g., 01) | 07 |
date +%D | Displays Current Date; shown in MM/DD/YY | 02/07/13 |
date +%F | Displays Date; shown in YYYY-MM-DD | 2013-02-07 |
date +%H | Displays hour in (00..23) format | 23 |
date +%I | Displays hour (01..12) format | 11 |
date +%j | Displays day of year (001..366) | 038 |
date +%m | Displays month (01..12) | 02 |
date +%M | Displays minute (00..59) | 44 |
date +%S | Displays second (00..60) | 17 |
date +%N | Displays nanoseconds (000000000..999999999) | 573587606 |
date +%T | Displays time; shown as HH:MM:SS Note: Hours in 24 Format | 23:44:17 |
date +%u | Displays day of week (1..7); 1 is Monday | 4 |
date +%U | Displays week number of year, with Sunday as first day of week (00..53) | 05 |
date +%Y | Displays full year i.e. YYYY | 2013 |
date +%Z | alphabetic time zone abbreviation (e.g., EDT) | IS |
我已经用了很长一段时间 Vim 了,但是 Vim 最可贵之处便在于你永远达不到 Vim 的天花板,在使用的过程中我永远会发现操作 Vim 的其他便捷方法。最近看了一个关于 Vim 的讲座 ,革新我对 Vim 命令的认识。可以说掌握这样的一个世界观可以对 Vim 的操作上到另外一个层次。下面就总结一下这个视频中的精髓内容。
@ChrisToomey 定义了一种 Vim Language,Vim 的语法由动词+名词组成,比如:
d 删除
w 单词
将两个字母组合起来就是 删除单词
这个经常使用的命令非常容易记住。
重复和撤销,相信使用过一段时间 Vim 的人应该会知道 .
表示重复上一次命令, u
表示撤销上一次操作。而重复和撤销是针对命令而不是针对输入的,因此每使用一次 .
或者 u
都是命令级别。
Verbs: 常用的动作举例
d Delete
c Change delete and enter insert mode
y yank
> intend 缩进
v 选择
Nouns: 常见的动作 Motion
w 移动到下一个 word 开始
e 移动到下一个 word 的结尾
b 移动到上一个 word 的开始 back
2j 向下移动 2 lines
Vim中定义了很多移动操作
基于内容 Nouns: Text Objects
w => words 表示移动一个单词
s => sentences 移动一个句子
p => paragraphs 向下移动一个段落
t => tags (html xml)
动作 motions
a => all
i => in
t => 'till
f => find forward
F => find backward
iw => inner word
it => inner tag
i" => inner quotes
ip => inner paragraph
as => a sentence
命令 commands
d => delete(also cut)
c => change(delete, then into insert mode)
y => yank (copy)
v => visual select
组合举例
diw delete in word
yi) yank all text inside the parentheses
上面的 Text Object
{command}{text object or motion}
在单词中间, diw
删除光标下的单词,dit
删除光标下tag中的内容
Nouns: Parameterized Text Objects
f,F => find the next character
t,T => find till
/,? => search
比如有一行文本
the program print ("Hello, World!")
如果想要删除 Hello 前面的内容,可以在行首使用 dtH
, 解读这个命令可以理解为 d => delete unti H
从这里删除直到遇到H。典型的 verb + noun 组合。
记住动作加移动,能够很快的记忆很多命令。
比如使用 https://github.com/tpope/vim-surround 这个插件,可以轻松的实现,使用命令 cs"'
来将
"hello world"
变成
'hello world'
命令的语义解释就是 change surroundding double quote to single quote 将包围的双引号变成单引号
使用 cs'<p>
将单引号变成 <p>
<p>hello world</p>
使用 cst"
将surrounding变成双引号
"hello world"
或者可以使用 ds"
来将 surrounding 双引号删除 delete surrounding “
hello world
Vim 中的 “.” 命令,以命令为单位,重复上一个命令。
Vim 允许记录一个宏来完成一组命令
qa # 将命令记录到寄存器a 中
q # 再次q 结束记录
@a # 使用寄存器
@@ # 使用上一次寄存器
一些相关的命令
sudo fdisk -l # 列出磁盘分区表
结果是这样的:
Disk /dev/ram0: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram1: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram2: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram3: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram4: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram5: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram6: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram7: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram8: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram9: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram10: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram11: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram12: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram13: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram14: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram15: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/mmcblk0: 7.4 GiB, 7948206080 bytes, 15523840 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x1fdbda7f
Device Boot Start End Sectors Size Id Type
/dev/mmcblk0p1 8192 93813 85622 41.8M c W95 FAT32 (LBA)
/dev/mmcblk0p2 94208 15523839 15429632 7.4G 83 Linux
Disk /dev/sda: 1.4 TiB, 1500301909504 bytes, 2930277167 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x4c63688c
Device Boot Start End Sectors Size Id Type
/dev/sda1 2048 2930272255 2930270208 1.4T 7 HPFS/NTFS/exFAT
在最后可以看到一块磁盘 /dev/sda1
。
然后可以使用如下的方式手动挂载。
为了让 Linux 能够读取 NTFS 格式的硬盘,需要安装 ntfs-3g
。然后可以手动挂载。
sudo apt-get install ntfs-3g
sudo mkdir -p /media/sda1
sudo mount -t ntfs-3g /dev/sda1 /media/sda1
挂载完成后可以查看
sudo df -h
Filesystem Size Used Avail Use% Mounted on
/dev/root 7.3G 2.2G 4.8G 31% /
devtmpfs 460M 0 460M 0% /dev
tmpfs 464M 0 464M 0% /dev/shm
tmpfs 464M 13M 452M 3% /run
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 464M 0 464M 0% /sys/fs/cgroup
/dev/mmcblk0p1 42M 21M 21M 51% /boot
tmpfs 93M 0 93M 0% /run/user/1000
/dev/sda1 1.4T 1.1T 363G 75% /media/sda1
通过编辑fstab来让系统自动挂载
sudo vim /etc/fstab
插入
/dev/sda1 /mnt/hdd ext4 defaults 0 0
从而实现USB设备的自动挂载
sudo vim /etc/udev/rules.d/10-usbstorage.rules
KERNEL!="sd*", GOTO="media_by_label_auto_mount_end"
SUBSYSTEM!="block",GOTO="media_by_label_auto_mount_end"
IMPORT{program}="/sbin/blkid -o udev -p %N"
ENV{ID_FS_TYPE}=="", GOTO="media_by_label_auto_mount_end"
ENV{ID_FS_LABEL}!="", ENV{dir_name}="%E{ID_FS_LABEL}"
ENV{ID_FS_LABEL}=="", ENV{dir_name}="Untitled-%k"
ACTION=="add", ENV{mount_options}="relatime,sync"
ACTION=="add", ENV{ID_FS_TYPE}=="vfat", ENV{mount_options}="iocharset=utf8,umask=000"
ACTION=="add", ENV{ID_FS_TYPE}=="ntfs", ENV{mount_options}="iocharset=utf8,umask=000"
ACTION=="add", RUN+="/bin/mkdir -p /media/%E{dir_name}", RUN+="/bin/mount -o $env{mount_options} /dev/%k /media/%E{dir_name}"
ACTION=="remove", ENV{dir_name}!="", RUN+="/bin/umount -l /media/%E{dir_name}", RUN+="/bin/rmdir /media/%E{dir_name}"
LABEL="media_by_label_auto_mount_end"