…
1. 终端命令行移动
- 到行首
ctrl + a
- 到行尾
ctrl + e
- 往左删除到行首
ctrl + u
- 往右删除到行尾
ctrl + k
- 往左删除1个单词
ctrl + w
- 往右删除1个字符
ctrl + d
- 左移1个字符
ctrl + b
- 右移1个字符
ctrl + f
2. 写脚本常用的
2.1. flock-执行脚本时,加一个文件锁,防止同时执行两次
| 1 | 
 | 
- "$0": 当前执行的脚本文件名
- exec: 执行一个新程序
- env FLOCKER="$0": 设置环境变量
- flock:- -e互斥锁,- -n非阻塞
- 最后一个冒号':': 也是bash内置命令,没用,相当于一个nop操作,方便一些时候重定向
如果环境变量中 "${FLOCKER}" != "$0" , 说明该脚本没有在运行,就启动运行: exec env FLOCKER="$0" flock -en "$0" "$0" "$@";
会设置环境变量,然后 flock 对脚本文件加锁, 然后再运行一遍该脚本 "$0" "$@", 这时候环境变量就有值了,会执行一个:(nop)继续运行;
如果 flock 加锁失败,因为是用 exec 直接起的程序,失败就直接退出了,不会再执行脚本
这段代码是 man flock 中的样板.
2.2. 查找最新的一个文件名
| 1 | ll -rt | awk -F' ' '{print $9}' |tail -n 1 | 
2.3. 查找某个程序的pid
| 1 | function get_pid(){ | 
3. linux二进制发送
用nc
| 1 | # 创建命名管道 | 
4. 字符串转二进制再做base64
| 1 | echo '35343633343335221008085013000400'| xxd -r -ps | base64 | 
5. 时间戳
| 1 | # 输出 20211008145359 | 
6. 计算校验码
| 1 | echo -n "0F 80 00 67 01 51 36 18 97 37 00 00 " | xorcal | 
7. 十六进制转ascii,再base64
| 1 | echo -n "23 23 02 fe" | hex2ascii | base64 | 
8. tr 替换,删除
| 1 | cat file | tr 'abc' 'xyz' | 
9. zip
| 1 | # 压缩 | 
10. 读取输入
| 1 | read -p "nihao:" name | 
11. 文件前后缀
| 1 | filename=ss.tar.gz | 
12. switch case 语句
| 1 | case ${arg} in | 
13. if 语句
| 1 | if [] | 
14. 判断
存在 filename 打印 exists,不存在打印 not exists
| 1 | [ -e filename ] && echo "exists" || echo "not exists" | 
14.1. test condition:
| 1 | [ ]: 跟test一样的,只能用 -a, -o, 是bash 命令 | 
14.2. 判断文件
- -b: 存在 && 块设备
- -c: 存在 && 字符设备
- -d: 存在 && 目录
- -e: 存在
- -f: 存在 && 普通文件
- -L: 存在 && 符号连接
- -p: 存在 && 管道
- -s: 存在 && 非空
- -S: 存在 && 套接字文件
14.3. 判断文件权限
- -r: 存在 && 可读
- -w: 存在 && 可写
- -x: 存在 && 可执行
- -u: 存在 && 该文件有 SUID 权限
- -g: 存在 && 该文件有 SGID 权限
- -k: 存在 && 该文件有 SBIT 权限
14.4. 两个文件对比
- f1 -nt f2: f1 比 f2 的修改时间新
- f1 -ot f2: f1 比 f2 的修改时间早
- f1 -ef f2: f1 和 f2 的 inode 是否一样,针对硬链接判断两个文件是否一样
14.5. 整数判断
- -eq: ==
- -ne: !=
- -gt: >
- -lt: <
- -ge: >=
- -le: <=
14.6. 字符串判断
- -z: 为空
- -n: 不为空
- ==: 相等
- !=: 不等
14.7. 多个条件
- -a: and
- -o: or
- !: not
15. 查看二进制文件
| 1 | od -t x1 file | 
-A n: 不需要行号
16. 数学计算
| 1 | let a=10-1 | 
17. 手动计算系统当前占用总RSS
| 1 | ps aux |awk '{sum+=$6} END {print sum/1024}' | 
18. 查看线程数
18.1. 查看程序的线程数
top -H, 系统的线程数
18.2. 某个程序的线程
| 1 | pstree -p pid |wc -l | 
| 1 | ps -eLl |grep pid | 
19. awk
| 1 | # 语法形式 | 
awk '{pattern + action}' {filenames}
根据 pattern 查找一行中的内容,然后做 action
pattern:
- /正则表达式/
- 关系表达式: 使用运算符操作,进行字符串或数字的比较测试
- 模式匹配表达式: ~ 或 ~!
- BEGING语句块,pattern语句块,END语句块
action:
- 变量或数组赋值
- 输出命令
- 内置函数
- 控制流语句
- awk 求和 - cat data | awk '{sum+=$1} END {print "sum = ", sum}'
- awk 平均值 - cat data | awk '{sum+=$1} END {print "avg = ", sum/NR}'
- awk 最大值 - cat data | awk 'BEGIN {max=0} {if ($1>max) max=$1 fi} END {print "max = ", max}'
- awk 最小值 - cat data | awk 'BEGIN {min=199999} {if ($1 < min) min=$1 fi} END {print "min = ", min}'
- awk 第2列不同值出现的次数 - awk '{sum[$2]+=1} END {for (i in sum) print i"\t"sum[i]}' test.txt
- awk 判断 第一列大于1,输出该行 - awk '$1 > 1 {print $0}'
- awk 进制转换 - 十六进制转十进制 - echo '12AF' |awk '{print strtonum("0x"$0)}'
- awk 十进制转十六进制 - echo '1234' | awk '{print("%x\n", $0)}'
- awk 八进制转十进制 - echo '012347' | awk '{print strtonum($0)}'
 
- 数组 - awk -F ' ' '{a[$1]=$3; if (a[$1]>"202201011") a[$1]="202201011";} END {for (i in a){print i,a[i]}}}'
- 多个分隔符 - awk -F '[ /:]'
- 去重并保留原顺序 
| 1 | cat list.txt | awk '!x[$0]++' | 
awk 表达式为true,执行后续语句,为false,跳过该行;
x[] 是个 map, 用当前行$0做key,如果之前没有该key, x[$0]查不到,返回false, !返回真, 打印该行,并++(相当于insert);
后续再来个key, 有该值,!返回假,跳过该行;
有个好处是,不用那么大的内存。
- 每行分割成一个单独文件
demo.txt
| 1 | sample_1 a b c | 
| 1 | cat demo.txt | awk -F ' ' '{out=$1".txt"; print >(out); close(out)}' | 
会分成3个文件,每个文件一行:
| 1 | sample_1.txt | 
20. sed 替换
- 将所有aaa替换成bbb
sed -i "s/aaa/bbb/g" file 
- 替换行
sed -i '/匹配字符串/s/替换源字符串/替换目标字符串/g' filename
- 删除匹配行
sed -i '/匹配字符串/d'  filename 
- 替换换行符成空格
sed -i ':a;N;$!ba;s/\n/ /g' file
通过 :a创建一个标记
通过N追加当前行和下一行到模式区域
如果处于最后一行前,跳转到之前的标记处。 $!ba ($! 意思是不在最后一行做这操作 (最后一行就被当成最后的一行)).
最后置换操作把模式区域(就是整个文件)的每一个换行符换成一个空格。
- 删除换行
sed -i ':a;N;$!ba;s/\n//g' file
- 删除纯空行
sed '/^\s*$/d' file
- 删除纯空行和由空格组成的空行
sed '/^[ ]*$/d' file
- 打印过去8分钟数据
| 1 | `sed -n "/`date -d "8 minute ago" +"%Y-%m-%d %H:%M"`/,\$p" file |grep OutOfMemoryError | wc -l` | 
放到脚本中:
| 1 | 
 | 
21. 正则
- 不以某些字符串开头
^(?!str)
22. 读文件
| 1 | while read ll | 
23. 将16进制字符串转换成二进制文件
data.raw.txt中存放的是16进制字符串,
head data.raw.txt
| 1 | 3031636481860159070000000025013000000189b4c5aabe0140d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5 | 
| 1 | for ll in `cat data.raw.txt` ; do echo -n $ll | sed 's/\([0-9a-zA-Z]\{2\}\) */\\\\x\1/g' | xargs echo -ne >> a.log ; done | 
转换成这样
od -t x1 a.log |head
| 1 | 0000000 30 31 63 64 81 86 01 59 07 00 00 00 00 25 01 30 | 
24. 特殊参数
- $#: 所有参数个数,不包括开头文件
- $@: 所有参数
25. 解析命令行脚本参数
在创建shell脚本时,尽量保持选项与Linux通用的选项含义相同,Linux通用选项有:
-a 显示所有对象
-c 生产一个计数
-d 指定一个目录
-e 扩展一个对象
-f 指定读入数据的文件
-h 显示命令的帮助信息
-i 忽略文本大小写
-l 产生输出得长格式文本
-n 使用非交互模式
-o 指定将所有输出重定向到输出文件
-q 以安静模式运行
-r 递归的处理目录和文件
-s 以安静模式运行
-v 生成详细输出
-x 排除某个对象
-y 对所有问题回答yes
| 1 | # 1. 手工处理 | 
26. 获取当前外网网卡
| 1 | ip a |grep -i 'up' |grep -vi loopback | awk -F ':' '{print $2}' |grep -io '[^ ].*' | 
27. xargs 参数
如果xargs要将命令行参数传给多个命令,可以使用-I参数。
| 1 | cat foo.txt | xargs -I file sh -c 'echo file; mkdir file' | 
28. grep
- 集合差集, 不能有空行,否则空行会匹配所有
| 1 | grep -F -v -f use.log all.log # 从all.log中去掉use.log中的数据 | 
- -F: 匹配行
- -f: 从文件中获取要匹配的行
- -v: 反选
- 贪婪模式有: 
| 1 | {m,n} | 
- 非贪婪模式有:
| 1 | {m,n}? | 
centos上需要用 grep -oP 才生效.
29. for循环
| 1 | for ((i=1;i<=10;i++)) | 
30. find
按时间查找:
- -atime: 访问时间(读取),
- -mtime: 修改内容了(写入),
- -ctime: 元数据发生了变化(写入,文件属性,属主)
24小时内为第0天,当前时间 2022-4-24 16:04:22, 则第0天为 2022-4-23 16:04:22 ~ 2022-4-24 16:04:22
- +1: 1天前,1x24小时之前的, ~ 2022-4-22 16:04:22
- 3 : 第2天
- -3: 3天内
删除1天前的文件:
| 1 | find . -mtime +1 -delete | 
查找大小为0的文件:
| 1 | find . -type f -size 0c | 
- -type f: 常规文件
- -size 0c: c表示 bytes, 默认是 b,表示 512bytes的个数
对找到的文件进行操作:
| 1 | find . -type f -exec ls -l {} | 
查找多个类型文件:
| 1 | find . -name "*.cpp" -o -name "*.h" | 
31. rysnc同步
rsync 默认使用文件大小和修改时间决定文件是否需要更新。
- -a: 递归同步子目录,同步元信息(修改时间、权限等),同步软链接
- -P: 等于- --progress --partial, 显示进度,从中断的地方恢复
- --partial参数允许恢复中断的传输。不使用该参数时,rsync会删除传输到一半被打断的文件;使用该参数后,传输到一半的文件也会同步到目标目录,下次同步时再恢复中断的传输。一般需要与- --append或- --append-verify配合使用。
- --size-only参数表示只同步大小有变化的文件,不考虑文件修改时间的差异
- -u、--update参数表示同步时跳过目标目录中修改时间更新的文件,即不同步这些有更新的时间戳的文件。
- -v参数表示输出细节。- -vv表示输出更详细的信息,- -vvv表示输出最详细的信息。
- -n参数或- --dry-run参数模拟将要执行的操作,而并不真的执行。配合- -v参数使用,可以看到哪些内容会被同步过去。
- -c、--checksum参数改变rsync的校验方式。默认情况下,rsync 只检查文件的大小和最后修改日期是否发生变化,如果发生变化,就重新传输;使用这个参数以后,则通过判断文件内容的校验和,决定是否重新传输。
- --delete参数删除只存在于目标目录、不存在于源目标的文件,即保证目标目录是源目标的镜像。
| 1 | # 排除1种文件 | 
32. 十六进制转换
echo ‘0123456789’ |xxd -r -ps >> ss.bin
33. npm
- 设置本地源 
 npm config get registry
 npm config set registry http://10.8.7.101:7001/
- 查看全局包安装路径 
 npm root -g
- 查看本地安装包 
 npm list -g –depth 0
34. 数组
| 1 | # 新建数组 | 
35. 获取脚本所在路径
| 1 | # 正确实现 | 
36. 清空屏幕
清空当前屏幕: clear 或者快捷键 ctrl+l
但往上翻还会出现之前的历史,使用 reset 会连之前的历史也清掉,适合编译调试,tput reset 单纯reset会快一些,可以设置 alias rst="tput reset" 方便使用。
37. sort
只排序第1列,保持第2列的输入顺序
| 1 | sort -s -k 1,1 | 
38. 查看TCP网络状态
| 1 | netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' |