本文记录一些工作当中常用的小工具、小技巧,有时候自己可以查看备忘,同时也给读者参考。当然,内容是在不断补充的,涉及的维度也会扩展。
Python
Python 是一种脚本语言,想要运行 Python 脚本就需要先安装 Python 环境【就像运行 Java 程序需要 JRE 一样】,安装后别忘记配置环境变量。
官方网站:python 。
唯一需要注意的是安装时先核对脚本的语法,是安装 v2.7.X 版本还是 v3.X 版本,它们的语法有时候不兼容,导致脚本无法跑通。
虚拟环境
在某个项目中,使用 Python 构造 Elasticsearch 请求获取结果数据,但是脚本的内容是针对 Python v3.X 环境的,而服务器上是 Python v2.7 版本的环境,而且个人没有权限更改【如果自己通过编译安装指定的版本,后续使用时如果缺失第三方模块还是需要手动安装,如果又引发模块之间的依赖,手动安装过程会崩溃的】,所以可以在服务器上面虚拟一个指定版本的 Python 环境出来。
1 | -- 在任意目录,虚拟出 Python 2.7 环境 |
缓存问题
假如跑一个脚本,把输出重定向到一个文件中:nohup python test.py > nohup.out 2>&1 &,结果发现 nohup.out 中显示不出来 python 程序中 print 的内容【或者是不及时显示,隔一段时间才会有一点内容】。
这是因为 python 的输出有缓冲机制,导致我们从 nohup.out 中并不能够马上看到输出。其实运行 python 脚本的时候有个 -u 参数,使得 python 不启用缓冲,把程序中的输出内容实时输出到文件:nohup python -u test.py > nohup.out 2>&1 & 。
编码问题
python 的 chardet 模块,可以查看字符串的编码:chardet.detect (data) 。
处理文本文件
在处理 csv 文件时,遇到异常:Error: field larger than field limit <131072>,这其实是因为 Python 读取 csv 文件时有一个默认设置,某列的内容最大长度为 131072【基于 Python v2.5】。
重点在于 Error: field larger than field limit <131072>,是因为 csv 文件中的某个字段的长度大于 csv 框架能处理的最大长度,需要在文件头加上参数配置代码:csv.field_size_limit (sys.maxint) ,这样就可以支持 int 的最大值所对应的长度了。
此外,由于 csv 文件的特殊性,csv 是特定分隔符分隔的文本文件,可能会导致内容混乱的状况,比如某一列包含了大量的换行符【又没有使用双引号封装起来】,会导致 csv 文件认为就是多行数据,这样这些行都是错误的数据【因为列数不够】,如果有连续的换行符,会导致空白行出现,Python 也会报错:line contains NULL byte 。
Excel 的知识
对于分析人员,经常会用到 Excel 工具,用来看数据,或者操作数据。
但是,有时候文本内容过多,不再适合使用 Excel 操作了,不仅很卡,而且有崩溃的风险。
根据我的经验,以最多 5 万行内容,最大 20MB 为好,如果是 Mac OS 系统,需要更少。
下面列举一下 Excel 支持的内容上限:
Excel 2003 支持的最大行数是 65536,Excel 2007 支持的最大行数是 1048576 。
Excel 2003 支持的最大列数是 256,Excel 2007 以及以上支持的最大列数是 16384 。
更多其它规范参考官方介绍:Excel 规范与限制 。
文件编码转换工具
iconv 需要单独安装:
1 | -- 转换文件内容编码,从 gb18030 转到 utf-8 |
文件名编码转换工具
在 Linux 系统中,如果把一个以中文命名的文件上传上去【特别是从 Windows 系统上传上去】,文件名可能会乱码,导致无法使用 Shell 操作文件,此时可以使用 xx 工具转换文件名的编码。
convmv 需要单独安装:
1 | -- 转换文件名编码,从 utf-8 转到 gbk |
常用命令
Shell
进程目录
根据进程编号找到启动进程的目录,从而判断进程的启动路径。
1 | pwdx pid |
负载查看
对于操作系统上面的进程导致的机器负载升高,可以查看到底是哪个进程或者线程导致的:
1 | xxx |
进程查看
查看某个进程的启动目录:
1 | -- 筛选进程名称,获取 pid |
使用 sed 操作文本文件
搜索替换之类的:
1 | 把文件中的 xxx 全部替换为 yyy,不带 -i 参数直接输出内容,不会更改文件 |
查看 Linux 系统的发行版本
lsb_release -a,该命令适用于所有 Linux 系统,会显示出完整的版本信息,包括 Linux 系统的名称,如:Debian、Ubuntu、CentOS 等,和对应的版本号,以及该版本的代号,例如在 Debian 8 中将会显示代号 jessie。
1 | 输出示例: |
cat /etc/issue,该命令适用于所有的 Linux 系统,显示的版本信息较为简略,只有系统名称和对应的版本号。
1 | 输出示例: |
cat /etc/redhat-release,该命令仅适用于 Redhat 系列的 Linux 系统,显示的版本信息也较为简略。
1 | 输出示例: |
uname -a、cat /proc/version,可以查看 Linux 的内核版本:
1 | 输出示例 1: |
查看 Linux 系统的核数
继续阅读之前先搞清楚几个概念:物理 CPU 个数、单颗 CPU 核数、单核 CPU 线程数。
- 一台物理机的
CPU个数 - 一个
CPU的核数 - 一个
CPU核上面支持的线程数
当一台机器有多个物理 CPU,那么各个 CPU 之间就要通过总线进行通信,效率比较低。

此时可以利用多核的特性,在多核 CPU 上,不同的核之间通过 L2 cache 进行通信,存储和外设通过总线与 CPU 通信,效率提高。

当然,如果利用多核超线程,即每个 CPU 核有两个逻辑的处理单元,两个线程共同分享一个 CPU 核的资源,计算起来更快。

因此,一台机器的总核数为:物理机的 CPU 个数 X 一个 CPU 的核数,总逻辑 CPU 个数为:物理机的 CPU 个数 X 一个 CPU 的核数 X 一个 CPU 核上面支持的线程数。
查看一台机器的 CPU 信息,主要就是 /proc/cpuinfo 文件,里面包含了关于 CPU 的信息,以 CentOS 系统为例,输出内容如下【只是截取了一小部分】:
1 | ... |
其中,model name 表示 CPU 的型号;physical id 表示物理 CPU 个数,编号从 0 开始;cpu cores 表示单颗 CPU 核数;processor 表示所有 CPU 线程数,编号从 0 开始。
因此,查看 CPU 信息时可以使用管道、过滤、查找来输出需要的内容:
1 | 查看 CPU 型号信息 |
顺带提一下查看内存的信息:
1 | cat /proc/meminfo |
split 拆分文件
把文件按照 60 行一个文件进行拆分,拆分后的文件以 data_ 作为前缀,以 2 位数字作为后缀:
1 | split -l 60 your_file -d -a 2 data_ |
curl 请求网络
可以模拟请求,传输参数:
1 | POST 请求,参数放在 seeds 中 |
查询 Elasticsearch 的数据:
1 | -- 查询指定索引、指定类型的数据,返回 1 条数据,格式化结果 |
文本文件行数
获取文本文件的内容行数,返回数值:
1 | wc -l 输入文件名称 |
文件去重
对单个文本文件的内容进行去重,返回去重后的文本:
1 | sort 输入文件 | uniq > 输出文件 |
说明:| 竖线表示管道,把前一个命令的输出作为后一个命令的输入,> 右尖括号表示重定向,把前一个命令的输出内容导出到文件中,sort 表示排序,但是并不会去除重复内容,所以会有重复的行,uniq 表示去除重复的内容,则输出结果就是去重后的内容。
随机获取文本内容
随机抽取单个文件中的内容行数,例如随机输出 100 行:
1 | shuf -n 行数 输入文件 > 输出文件 |
说明:-n 后面紧跟着数字,表示行数,不需要空格。
计算交集差集并集
1 | cat 输入文件 1 输入文件 2 | sort | uniq -d > 输出文件 |
说明:cat 表示查看文件内容,uniq 的 -d 参数表示抽取重复的内容,即出现 2 次及以上的内容,在这里得到的结果也就是交集了。
此外,还有 -u 参数表示抽取唯一的内容,则可以计算差集。
1 | cat 输入文件 1 输入文件 2 输入文件 2 | sort | uniq -u > 输出文件(注意输入文件 2 故意重复 2 次) |
说明:uniq 的 -u 参数表示抽取唯一的内容,即只出现一次的内容,这样得到的输出结果必然是只在输入文件 1 中,而不在输入文件 2 中。
1 | cat 输入文件 1 输入文件 2 | sort | uniq > 输出文件 |
说明:这个很容易理解了,合并文件后简单去重,也就是并集了。
Kafka
查看 topic 信息:
1 | kafka-topics.sh --list --zookeeper dev:2181 |
生产数据:
1 | kafka-console-producer.sh --topic your_topic --broker-list dev:9092 |
消费数据:
1 | kafka-console-consumer.sh --zookeeper dev:2181 --topic your_topic |
查看 topic 状态:
1 | kafka-topics.sh --zookeeper dev:2181 --describe --topic your_topic |
查看消费情况【消费组消费量、积压量、生产量】:
1 | kafka-consumer-offset-checker.sh --zookeeper dev:2181 --group your_group --topic your_topic |
Zookeeper
操作:
1 | 登录 |
Redis
操作:
1 | 登录,n 表示桶,默认 0 |
HBase
HBase 操作:
1 | 登录 |
phoenix 操作:
1 | 登录 |
Spark
启动 Spark 命令行,使用 spark-shell --master yarn-client,然后就可以在交互式命令行中写 scala、python 代码了。
举例:读取 2 个文件,做并集:
1 | var list1=sc.textFile ("/tmp/pengfei/file1.txt").flatMap (x => x.split ("\\t")) |
触发任务后在 yarn 中就可以看到任务的运行情况,注意,启动 Spark-shell 的时候也可以直接在本地运行,但是处理数据量大的时候内存会不够用,不建议。启动 Spark-Shell 的时候,可以指定使用 yarn 模式:spark-shell --master yarn-client,如果不指定,默认在本地启动,内存与处理速度会慢。
spark-shell --help,查看启动参数详情,例如以下参数,--executor-memory 4G、--total-executor-cores 4、--executor-cores 2 可以加大内存,增加 core 数。
常用方法举例:dinstinct【去重】、intersection【交集】、subtract【差集】、union【并集】、saveAsTextFile【导出】、textFile【读取】。
分割去重过滤:
1 | .flatMap (x=>x.split ("\\t")).distinct ().filter (x=>11>x.length ()) |
单词计数写回文件,按照 value 降序排列:
1 | val wordcount = sc.textFile ("").flatMap (line => line.split ("\\t")).map (word => (word, 1)).reduceByKey ((a, b) => a + b) |
大数据任务调度系统
yarn
移动队列
在资源紧张的情况下,可以手动移动 Spark 任务的队列,合理利用空闲的资源。
如果 yarn 队列没有资源了,而自己又有 Spark 任务需要跑,在提交 Spark 任务后,可以看到任务在等待分配资源,此时可以把 Spark 任务移动到别的空闲队列去【也可以在提交 Spark 任务的时候指定队列】。
或者某些运行耗时比较长的任务,也可以先移动到别的空闲队列跑,释放自己业务的队列资源给其它任务使用。前提是确保不影响别的队列的正常使用,不能长久占用别人的队列。
使用 yarn 自带的命令:
1 | -- 指定 Spark 任务的 applicationId,以及目标队列名称 |
如果不熟悉这些命令,可以使用 yarn -help、yarn application -help 等命令查看帮助说明文档。
取消任务
如果想 kill 掉一个正在 yarn 环境上运行的 Spark 任务,可以直接使用 kill 命令:
1 | -- 指定 Spark 任务的 applicationId |
当然,如果使用的 yarn-client 模式提交任务,并且有权限看到 Driver 端的进程,也可以直接使用 Linux 的命令 kill 掉进程【不够优雅】。
下载日志
下载已经完成的 Spark 任务的文本日志,在 Saprk 任务的 UI 界面,可以看到 Excutor 的日志,但是当日志多的时候,看起来不方便,搜索就更不用说了。
当任务完成之后,可以使用 yarn 命令下载文本日志进行查看、分析:
1 | -- 指定 Spark 任务的 applicationId,所属用户 |
注意,由于用户权限的问题,在下载日志之前需要切换用户,否则获取不到日志或者抛出权限相关错误:
1 | -- 切换用户,根据实际情况而定 |
操作系统
回车换行
在文本数据处理中,CR、LF、CR/LF 是不同操作系统上使用的换行符,表现为文本另起一行输出。
1 | CR:Carriage Return |
下面列出常见的操作系统标准:
Dos和Windows采用回车符 + 换行符,CR/LF表示下一行UNIX/Linux采用换行符,LF表示下一行- 苹果
MAC OS系统则采用回车符,CR表示下一行
还需要注意,CR 用符号 \\r 表示,十进制 ASCII 编码是 13,十六进制编码为 0x0d,LF 使用 \\n 符号表示,十进制 ASCII 编码是 10,十六制编码为 0x0a 。
所以在 Windows 平台上的换行效果,在文本文件中是使用 0d、0a 这两个字节来实现的,而 UNIX 和苹果平台上的换行效果则是使用 0a 或 0d 一个字符来实现的,节约了存储空间。
在一个操作系统平台上使用另一种换行标准的文本文件,可能会带来意想不到的问题,特别是在程序代码中,有时候代码在编辑器中显示正常,但是在编译打包时却会因为换行符问题而出错【备注:使用 Git 版本控制系统时,Git 客户端已经根据当前的操作系统环境,自动帮助我们实时替换了换行符号】。
例如常见的一个现象,Unix/Mac 系统下的文件在 Windows 里打开的时候,会发现所有的文字变成了一行,而同理,Windows 里的文件在 Unix/Mac 下打开的话,在每行的结尾可能会多出一个 ^M 符号。

