0%

标准 I/O 流

Linux shell 可以接收和发送字符序列或字符流形式的输入和输出。无论实际的字符流是来自还是来自文件,键盘,显示器上的窗口或其他IO设备,字符流都可以通过文件IO技术进行访问。Linux shell 使用3种标准的I/O流,每种流都与一个文件描述符。Linux 内核采用文件描述符(file descriptor)来访问文件。文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。

1
2
3
stdout   //标准输出流,它显示命令运行的输出,文件描述符为 1
stderr //标准错误流,它显示命令运行的错误输出,文件描述符为 2
stdin //标准输入流,它为命令提供输入,文件描述符为 0

输入流通常通过终端敲击键盘为程序提供输入。输出流通常向终端输出显示文本字符。

linuxcom

重定向

在Linux命令行模式中,如果命令所需的输入不是来自键盘,而是来自指定的文件,这就是输入重定向。同理,命令的输出也可以不显示在屏幕上,而是写入到指定文件中,这就是输出重定向。

> 符号

格式 {stdout|stderr} > filename,使用 > 符号将左侧输出重定向到一个文件中。需要注意的是:如果文件名不存在则创建它,如果存在则覆盖

1
2
3
echo "hello" > a.txt
➜ cat a.txt
hello
阅读全文 »

npm

npm(node依赖包管理器,node package manager),官方或权威机构提供了一个公共的软件源(类似 Homebrew、yum),可方便我们下载并管理 JavaScript 依赖

安装了 node 就包含了 npm 的安装

安装依赖,-g参数表示全局安装,不带参数则安装在当前目录

1
2
npm install lodash
npm install -g vue-cli

可查看已安装的全局依赖(默认安装到 /usr/local/lib/node_modules 目录下),--depth显示的树深度,不加-g参数查看当前目录安装的依赖

1
2
3
4
5
➜ npm ls -g --depth=0
/usr/local/lib
├── npm@5.6.0
├── nrm@1.0.2
└── vue-cli@2.9.2

卸载依赖

1
npm uninstall lodash

搜索某个依赖,以及显示某个依赖的具体信息,经测试,只有官方的源可以search,其他源未做相应支持

阅读全文 »

前言

JavaScript是目前前端开发中最流行的语言,在学习的过程中会遇到各种JS有关的名词。本文章的主要目的是介绍ECMAScript(or ES)、CommonJSNode.jsVue.jsAngularJS等与JavaScript之间的联系。

ECMAScript

ECMAScriptJavaScript的关系是,前者是后者的规范,后者是前者的一种实现(另外的实现还有JscriptActionScript等)。

JavaScript的创造者Netscape公司,将JavaScript提交给国际标准化组织ECMA,希望这种语言能够成为国际标准,标准委员会最终决定,标准在每年的6月份正式发布一次,作为当年的正式版本。

目前的几乎所有的浏览器(不包括低版本的IE),都已经支持ES5了,而写代码时最好采用ES6语法(毕竟语法糖写起来更舒服,还添加了很多必要的新特性,而且浏览器全面支持ES6是迟早的事)。不用担心浏览器不能识别新语法,Bable就是用来解决这种问题的工具。

Babel是一个广泛使用的ES6转码器,可以将ES6代码转为ES5代码,从而在浏览器环境运行。

1
2
3
4
5
6
7
// 转码前
input.map(item => item + 1);

// 转码后
input.map(function (item) {
return item + 1;
});

Node.js

在介绍CommonJS之前有必要先介绍一下Node.js。首先明确一点,JavaScriptPython一样,是一种脚本语言,或者是解释型语言,和C、C++ 这种需要编译成可执行文件再运行的语言不同,它的运行只需要解释器能够解释执行即可,而不需要编译器。浏览器就包含了解释执行网页中的JavaScript代码的功能。

阅读全文 »

Preface

本文摘自油条的知乎文章 摸索HTTP,自己结合实验一步一步探究HTTP协议

Prerequisites

  • OS: MacOS或Linux各发行版
  • curlnc命令
  • 多台电脑,最好是有自己的服务器

nc

nc(or netcat)命令用于建立TCP和UDP监听和连接,它可以建立TCP连接、发送UDP包、监听任意TCP和UDP端口、端口扫描和处理IPv4和IPv6等。它比telnet命令更加实用,在网络工具中有“瑞士军刀”的美誉。

  • 打开两个终端。一个充当客户端,一个充当服务端。

  • 让服务端nc启动之后监听8000端口,等待TCP连接

    1
    nc -l 8000 //server
  • 切换到客户端,如果是不同的机器则将localhost换成服务端主机的IP

    1
    nc localhost 8000 //client
  • 现在在任意一个终端中输入些字符,敲击回车,另一个终端会显示相应字符,说明双方已经成功建立TCP连接进行通信,需要注意的是一定要服务端先建立监听

Tips

  • 可以直接用nc命令来传输文件

    1
    2
    nc -l {port} > filename // 接收端
    nc {接受者IP} {port} < filename // 发送端
  • 亲测这条命令非常实用,适用于在你的本地和服务器未建立ssh认证时(不能使用scp),或内网网络传输文件,或你的两台电脑不能登陆同一微信传输文件时

HTTP响应

阅读全文 »

Preface

最近同事在将jar包上传到服务器执行spark-submit时,运行的时间总是不确定的,有时甚至等待数十分钟。遂想到当初自己在服务器上运行Tomcat时也遇到这种问题,往往第一次运行很快,后面要等很长时间。最近查阅相关资料,终于发现问题所在。

Concepts

首先要明白操作系统如何产生随机数以及内核熵池的一些概念

  • 随机数在许多领域都有重要应用,如密码学、网络安全等。Linux内核从1.3.30版本开始实现了一个高强度的随机数产生器

  • Linux 内核采用来描述数据的随机性。熵是描述系统混乱无序程度的物理量,一个系统的熵越大则说明该系统的有序性越差,即不确定性越大。在信息学中,熵被用来表征一个符号或系统的不确定性,熵越大,表明系统所含有用信息量越少,不确定度越大

  • 计算机本身是可预测的系统,因此,用计算机算法不可能产生真正的随机数。要生成高强度的随机数需要许多不确定的外界参数。你比如说编程中的随机数种子就是一个外界参数,如果你的种子数确定,那么生成的随机序列是可以预测的

  • 恰好机器的环境中充满了各种各样的噪声,如硬件设备发生中断的时间,用户点击鼠标的时间间隔等是完全随机的,事先无法预测。Linux内核实现的随机数产生器正是利用系统中的这些随机噪声来产生高质量随机数序列

  • 内核维护了一个熵池用来收集来自设备驱动程序和其它来源的环境噪音。为跟踪熵池中数据的随机性,内核在将数据加入池的时候将估算数据的随机性,这个过程称作熵估算。熵估算值描述池中包含的随机数位数,其值越大表示池中数据的随机性越好

  • 内核提供了两个字符设备/dev/random/dev/urandom以让用户调用获得随机数序列,/dev/random输出的随机数序列质量更高,适合于高强度的加密算法,但它只返回熵估算值所允许的最长的随机数序列,否则请求将被阻塞直到熵估算值增大到一定域值。/dev/urandom总是立即返回所请求的随机数序列,”u”代表unlocked非阻塞

  • 当熵池为空时,来自/dev/random的读操作将被阻塞,直到熵池收集到足够的环境噪声数据。这么做的目的是生成尽可能随机的数据。对于生成高质量的加密密钥或者是需要长期保护的场景,一定要这么做。

Ok,其实到这里,原因就已经明了了,在启动Tomcat生成SessionID时和spark-submit连接数据库时,用到了 /dev/random生成的随机数,却因为熵池用空而进入阻塞,这也解释了为什么第一次的执行很快,后面却很慢。

Solving

Apache官网上也有描述如何优化Tomcat的运行效率,有两种方法解决这个问题

  • 修改${java_home}/jre/lib/security/java.security中的这一行
    1
    securerandom.source=file:/dev/random
    替换为
    1
    securerandom.source=file:/dev/./urandom
  • 或者在Tomcat的catalina.sh中加入如下行
    1
    -Djava.security.egd=file:/dev/./urandom

Tips

阅读全文 »