2016年6月1日星期三

command line as OS

典型场景是:服务器远程登陆,只有命令行界面,此时不得不用命令行工具处理日常工作任务,所以就用,边用边查手册,用久了所以熟悉

日常任务有:
  • 文件上传、下载。一般来说就是sz,rz,wget,curl,scp等。
    • for循环wget,分分钟多进程下载。
    • wget -c 分分钟断点续传。
  • 压缩、解压。所以得会用tar,zip等命令。我一开始的时候,问一个老手tar cvzf,tar xvzf后面一排参数啥意思,老手说:”早就忘记了,天天都这么用“。所以我认为它和一个按钮一个菜单没什么区别,命令行参数的选项和参数一般是经常用就熟悉,久不用就容易忘记,此时复查是正常的事情。顺便吐槽下windows下7z的菜单里直接解压tar.gz要解压两次真是麻烦事,命令行当然可以一次搞定。
  • 目录和文件的创建、移除、拷贝、移动。基本命令是:mkdir,rm,mv等。这是最基本的常规操作了,一般来说需要注意的有:
    • 非空目录的移除,
    • 递归删除时拼接路径的安全隐患(递归删除根目录就一点都不好玩了)
    • 删除时文件被占用
      • 如果可能只是短时被占用,可以sleep几十毫秒再删,重试n次退出。
    • 考虑采用”删除xxx.old, 移动xxx到xxx.old, 拷贝yyy到xxx“的方式代替”直接删除xxx,移动yyy到xxx“的方案、
    • 文件系统
      • 理解硬盘驱动,冗余磁盘阵列,inode,文件和目录,缓存策略等。
  • 文本显示、查找、替换、统计。在命令行下分析程序的日志,必备的技能就是文本操作。基本的命令有cat,tail,less,head,grep,sed,awk,wc,xargs等,这组命令行基本要通过管道来配合使用。我个人觉的awk的设计有点古老,awk的脚本我是一点都不觉得写起来流畅和爽快,sed的稍微好点,但也一般。如果是在windows下,这种流式过滤的工作,我是宁可开个LinqPAD写Linq来做,其实很多时候写脚本我都实际上觉的用正式点的高级语言做会更好。很多shell脚本写的人天马行空,别人读起来就不好玩了,毕竟写shell的人不写注释,遍地意大利面条。吐槽归吐槽,现实上我们不得不妥协,该用还得用。毕竟一切数据都可以输出成文本,所以文本的流式分析是基本技能。
    • 我认为这组命令的组合使用能让人体会到管道的好处。管道让多进程之间的流式操作流畅进行。顺便我认为shell的一个特点是,它天生是多进程程序,一个shell里随便一堆命令就是多进程操作,可能很多人写着的时候并没有意识到这点哦。进一步,多主机之间ssh授权后,shell里的ssh远程命令的组织又天生带有点分布式属性,也许这能带来一些启发。
      • ssh 信任就是非对称加密。
        • A机留私钥; B机在.ssh目录放公钥,在.ssh/authorized_keys里填上公钥内容。
        • 则A机执行ssh user@B cmd 的时候,B机会用公钥和A机之间建立ssh连接,然后执行命令。
          • git 的客户端向git的仓库之间建立ssh授权也是这个过程,实际上任何依赖于ssh建立授权的都是这个过程。
          • 这实际上是一种“反连”协议,思考下私钥在哪里就知道了。
    • 理解管道的另一个要素是,需要理解fork,vfork、clone,exec;需要理解标准输入输出。fork之后,在exec子进程之前重定向父进程的标准输出,重定向子进程的标准输入,这样它们就被流式串在一起。
      • 好吧,被awk粉丝吐槽了:D
  • 文本编辑。
    • vi基本技能。shell下编辑文本只能用这个了,我认为vi或者vim里最重要的技能就三个:导航、查找、替换,带着这个思维去记忆那些命令会明确很多。我觉的任何一个程序的核心功能就几个,每个核心功能的核心命令也就几个,其他的就按需查用即可。~~
      • 理解模式的概念,同样的键盘按钮,在不同vim模式下,操作代表不同的语义。想象一下相机是如何由有限的几个按钮做到多组不同功能的支持。
        • 我认为快捷键并不是vim/emacs之类的最大特点,任何一个支持快捷键的编辑器,你都可以通过熟练掌握常见的快捷键使得操作快捷高效,比如notepad、visual studio、word等,理解这点有助于我们看清事实,驾驭工具。
  • 资源监控。输出的信息都可以配合grep等使用,比如ps aux|grep processname.
    • 任务管理器型:vmstat, top, htop,
    • 进程:ps
      • cpu的虚拟化。
      • 理解OS对process的调度:Scheduling (computing)
        • FIFO,SJF,STCF,RR,MLFQ
        • 理解os调度process的话,再去看协程,用户态协程需要自己做调度:)
        • IO密集和CPU密集?
    • 磁盘:du, iotop, iostat
    • 文件句柄:lsof
      • 比如查看一个进程打开的文件描述符,反向查看哪些进程打开了某个文件。
    • 内存
      • 物理内存的虚拟化(进程的内存分布,内部浪费和外部浪费),分页,页错误。
  • 调试和Hook。开发的话会需要调试程序和Hook程序等。
    • 通过ulimit -c unlimited让程序崩溃时产生coredump,然后用gdb调试,看崩溃堆栈,变量、单步等,这是gdb的常规操作。linux下开发必备技能了。ulimit 还可以限制其他资源,比如-n限制文件句柄个数,-s限制堆栈大小等,具体查文档。
    • 系统调用、堆栈等的Hook:strace,dtrace、pstack等,这组算是lowlevel的神器,在很多时候能起到一针见血的效果。
      • 顺便,可以理解下系统调用的原理,中断的实现原理,这样你在使用strace监控一个程序的系统调用的时候,脑子里会有更清晰的思路。系统调用并不是一个简单的函数调用这件事么..
        • Things UNIX can do atomically 多进程之间可以对文件和文件夹加锁
          • 说起锁,想起Dijkstra,锁、信号量、等并发编程同步的机制最早都是他搞清楚的。
            • 什么是”原子“的,在CS里,这是一个及其重要的概念。
            • 锁应该保护的是数据还是行为?
            • 锁的尽量局部化。
        • 感兴趣?:Operating Systems: Three Easy Pieces
    • export LD_LIBRARY_PATH=$PWD;
      • 理解系统查找共享库的搜索路径顺序。
    • readelf: 都说了任何东西都可以输出成文本来看了,看个依赖库路径还是容易的。
    • perf

      "Have a C program and want to know which functions it's spending the most time in? perf is a sampling profiler for Linux that can tell you that." (这个我还没用过)

    • Linux debugging tools I love
  • 网络。
    • tcpdump抓包是一定要掌握的,抓tcp、udp包是必备的技能。输出pcap格式文件也是要的。如果是有图形界面的话,wireshake在windows和linux下都能用,如果是windows上还可以用microsoft networkmonitor。说实话,我觉的microsoft networkmonitor做的比wireshake好用。
      • 一个tcp连接,三次握手、四次挥手;建立在tcp连接之上的http连接,http request包在什么时候发,seq号是怎样变动的;诸如此类,都可以在这个地方查看。
        • 为什么要三次握手。syn、ack、ackack,它们是原子不可分的么,在更复杂的协议里,一个syn,一个ack、一个ackack本身可能就是一组子协议三者中任何一个环节被打破(Break),都会导致握手失败
          • P2P打洞的原理
            • NAT,限ip,限port,限ip和port,随机ip和port
          • DNS的原理,host,
            • DNS污染
            • gethostbyname不能ipv6,getaddressinfo会卡死,自己写全异步dns协议去解析。
        • 为什么要四次挥手。自己设计流式协议的话,如果你不需要这种Feature,就可以暴力Close了。
          • 知其然,知其所以然。
        • Http协议说到底是一个Tcp协议,这点很重要。
        • 协议森林:协议森林 - Vamei
          • 拥塞控制算法,根据历史数据记录估算未来数据,这是一种学习(统计)
            • Deep Learning,NN
      • 一台机子有多个网卡(ifconfig),或者单网卡,多ip,绑定到0.0.0.0的时候,收发包是怎样的情况?
      • 理解tcp和udp的区别
        • 拆开ip包头,tcp和udp包头,以及做checksum校验的拟包头,理解协议包是如何被Stack的。
          • 话说最早我想当然认为tcp包头里面才是ip包包头,然而事实上这个鸡蛋黄是上层的包头在下层协议包的包体里。不知道是否有同类人有过这种直觉的错觉。
      • windows版本:WinDump - Home
    • nc命令用来探测主机之间的tcp端口或者udp端口是否联通。
    • netstat查看tcp和udp连接情况。
    • iptable的配置,配置tcp、udp端口啥的都要用到。
    • iptraf: 实时网络监控,比如监控某个网卡上的Ip包流量。
      • 估算吞吐量,延迟等。
  • 数据库操作。命令行下,操作mysql和sqlite是常见的事情,这个基本就是常规的sql操作语句。
    • 将数据库dump出SQL文本格式,到别的机子上导入什么的。。
      • 以前有个人打开了这么一份文本,惊讶说:“哇,谁写的SQL创建代码,这么整洁,连注释啥的都很规整...”
    • 理解关系型数据库的范式,事务,一致性。
      • 理解B+树、Block。
      • 基于行存储Block的数据库,基于列存储Block的数据库,各自的优缺点
        • 局部性原理,行Block存储是行记录读写偏好,列的则是部分字段读写偏好
          • trad off,没有最好,只有最合适
    • NoSQL的也操作一些。
      • Map-Reduce,这都已经烂大街了,实际上我不认为会操作和使用NoSQL的数据库就可以,熟练操作一组API本身只需要多次练习就可以达到,不具有门槛。理解系统背后的设计优点,以及其所不能解决的问题才够(有很多领域,都存在不可能三角
        • 以思考”原子“的组件为线,朝着做减法的思维去思考,而不要一味的加功能,堆积木。
      • Apache系列。。
        • 不过积木长什么样子,还是要看看,但并非高大上就神马。
  • 版本管理等
    • svn、git,这个本来就要会的,只是很多人用图形界面的工具多了后,可能命令行使用并不熟悉,但是在Linux shell下,这也算基本技能。
      • 理解“围绕数据结构设计接口”,git是关于commit的链表的数据结构的一组api。
  • 元数据分布式同步,ZoopKeeper
  • 其他选择
    • 更现代的shell:fish
    • 更好的http请求:httpie
  • windows上的使用
    • cygwin太大了,可以选用下面的组合,这样在windows的命令行下也可以使用上述大部分命令行。还是有很多便利的。
  • 手册类:the art of command line,BUT,并不是所有命令在所有环境下都能用。