Shell
Table of Contents
序
shell命令解析流程
常见命令
文本处理
- grep
- sed
- awk
- sort
- diff
- vi
其他常用命令
- crontab
- curl 支持ftp,http等多种协议处理
- find
- ftp
- file 查看文件类型
- free
- lsof 查看打开的文件(文件被哪个进程打开;进程打开了哪些文件)
- jq 处理json
- pgrep
- ps
- top
- tar
- tcpdump
- rsync 文件拷贝同步,支持远程拷贝,使用差量快速同步
- df
- du
- bc 强大的可编程计算器
- md5sum
- hexdump
- usradd
- usrmod
- chown
- chmod
学会看手册
命令有很多,而且选项也很多,单靠记忆是很难全部记住的。所以要学会 RTFM。下面是看手册也的一些基本要点:
- man man
- 手册页
The table below shows the section numbers of the manual followed by the types of pages they contain. 1 Executable programs or shell commands 2 System calls (functions provided by the kernel) 3 Library calls (functions within program libraries) 4 Special files (usually found in /dev) 5 File formats and conventions eg /etc/passwd 6 Games 7 Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7) 8 System administration commands (usually only for root) 9 Kernel routines [Non standard]
初探
原则
- 一次做好一件事
- 处理文本,不要处理二进制数据
文本易懂,而且可用的工具更多。 - 使用正则表达式
使用正则,功能会更强大。 - 默认使用标准输入/输出
为了和其他工具在管道中使用 - 避免喋喋不休
仅输出必要的信息。unix工具程序遵循你叫它做什么,它就做什么的设计哲学。它们不会问“Are you sure?” - 输出格式必须与可接受的输入格式一致
保持输入格式一致,以便其他工具可以继续处理 - 让工具去做困难的部分
尽量使用已有成熟的工具 - 构建特定工具前,先想一想
是否有必要,其他人是否也要做,是否这个特殊的要求是一个一般的要求的特例?
规范
可以参考 google shell脚本编程规范
这里特别提两点,变量名使用小写加小划线,环境变量以及全局变量放开头,并用大写加下划线;
shell脚本不需要用.sh作为结尾,除非是作为库函数使用,而且作为库函数使用时,不需要有执行权限。之所以不需要以.sh结尾的原因在于,文件后缀对于
Linux下的可执行文件没有特殊意义,另外,脚本有可能使用其他语言重写,调用方只需要知道脚本的功能,没有必要知道脚本的编写语言。
执行
Linux在执行命令的时候,首先会判断命令是否是一个可执行的二进制文件,如果是,则直接执行。如果不是且文件以`#!`开头,则把该命令作为一个脚本执行(解释器文件)。并以`#!`后面指定的命令作为解释器。
例子
#!/path/to/cmd -pf script content comes here...
变量
bash支持定义readonly变量,整型变量等。
条件判断
bash支持if条件判断(条件测试包括文件是否存在,命令是否执行成功等。
循环
ash支持for以及while循环语句。
参考
日常使用
一些不好的习惯
- 可执行脚本以.sh后缀结尾
- 脚本第一行不是#!/bin/bash
- 喜欢使用root用户或其他具有超级用户权限的用户操作
这样做的坏处首先是不安全,跳过了系统按用户以及权限划分的边界,很容易误操作。打乱了系统的管理。同时,使用超级用户进行日常操作,就像一个野蛮人一
样,侵犯了正常操作的普通用户以及造成不便。在公共服务器上,使用超级用户权限时,需要尊重其他人。 - 给文件或目录加上777权限
没有必要,而且不符合最小权限的原则。 - 习惯一问一答的操作,例如rm -i以及mv -i等
这样一问一答的操作浪费时间,特别是这种日常操作更是如此。另外,这里有一个陷阱,以rm -i为例子,确认式删除好像看起来操作更加谨慎,但实际上可能在
习惯了这种操作之后,还是会顺手输入确认,导致误删。从这个角度而言,直接删除和交互式删除是一样。但是交互式删除浪费了更多的时间,而且,另一方面,
时刻提醒自己,一旦执行rm}就会删除,会让你在删除时更加谨慎,并养成习惯。真正谨慎的操作是养成谨慎的习惯。 - 脚本不检查输入
严格检查外部输入,内部错误则要快速出错。 - 文件或目录名称滥用大写字母
一般使用大写字母的作用是为了强调,但是如果滥用大写字母,就起不到强调的作用了!就像到处使用叹号一样!!而且输入的时候,要多按一个shift键!!!
一些好的习惯
- 保证脚本在任何工作目录都可以正常执行,关键是在脚本里使用绝对路径。
- 合理使用引号。例如,grep的*pattern*参数最好用单引号包起来。
- 谨慎处理批量操作,尽量精确匹配。特别是删除文件等。
- 文件或目录名不要包含对shell有特殊含义的特殊字符,例如() , > , |等。
- 从标准输入读入数据,输出到标准输出,同时错误信息输出到标准错误
一些容易混淆的概念
环境变量
设置环境变量仅对当前进程以及它的子进程有效。
技巧
脚本传递参数
举例
#!/bin/bash echo "执行的文件名:$0"; echo "第一个参数为:$1"; echo "第二个参数为:$2"; echo "第三个参数为:$3"; sh ./dem.sh 1 2 3 执行的文件名:./demo.sh 第一个参数为:1 第二个参数为:2 第三个参数为:3
特殊字符
参数处理 | 说明 |
$# | 传递到脚本的参数个数 |
$* | 以一个单字符串显示所有向脚本传递的参数 |
$$ | 脚本运行的当前进程ID号 |
$! | 后台运行的最后一个进程的ID号 |
$@ | 与$*相同,但是使用时加引号,并在引号中返回每个参数 |
$- | 显示Shell使用的当前选项,与set命令功能相同 |
$? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误 |
参考
持续更新.......