…
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]}' |