# shell - shell 变量: http://www.imooc.com/learn/336 - shell 运算符: http://www.imooc.com/learn/355 - 环境变量配置文件: http://www.imooc.com/learn/361 - 正则表达式: http://www.imooc.com/learn/378 - 流程控制: http://www.imooc.com/learn/408 - 主控脚本实现: http://www.imooc.com/learn/522 - 应用运行状态: http://www.imooc.com/learn/539 - 应用日志分析: http://www.imooc.com/learn/540 - [shell文本处理: sql -> shell](https://github.com/pyloque/shellquery_ppt) shell 简化管理操作, php / java 主要实现功能 命名规则 数据类型: 默认 string 分类: 用户自定义变量 / 环境变量 / 预定义变量 ``` # 用户自定变量 name='foo bar' # = 2边没有空格 x=${x}456"$x" # 变量叠加, 其实就是 字符串连接 echo $name # 变量查看; 调用变量时才需要 $ set -u # 查看变量, 当变量不存在时提示 unset name # 环境变量 export x # 声明 环境变量; 其实就是 declare -x env # 查看 环境变量 echo $PATH # 系统搜索 命令 的路径 PATH="$PATH":/root # 临时路径到 path 中 locale # 语系查询 LANG # 当前使用的语言 /etc/ysyconfig/i18n # 默认语言配置 # 位置参数变量 $1 -$9 ${10} # 给脚本传递变量 sum=$(($1 + $2)) $# # 参数个数 $* # 所有参数, 当做一个 $@ # 所有参数, 当做多个 # 预定义变量 $? # 上一条命令的返回值 $$ # 当前进程的 pid $! # 后台运行的最后一个进程的 pid read -p '提示信息' -t 30 -n 30 -s passwd # prompt time nchar secure echo -e "\n" ``` ![运算符](http://7xq89b.com1.z0.glb.clouddn.com/shell-expr.jpg) ![变量测试](http://7xq89b.com1.z0.glb.clouddn.com/shell-var-test.jpg) ``` $(date) # 执行系统命令, 然后赋值给变量 `date` # 同上 declare +/- -aixrp # array integer 环境变量 readonly prompt declare -i c=$a+$b $(expr $a + $b) # expr/let, 进行数组运算, 必须要有空格 $((运算式)) / $[运算式] echo ${arr[*]} # 输出数组所有值 echo ${arr} # 输出数组第一个值 # 变量测试 x=${y-var} # 可以决定 x/y 的值 ``` ![环境变量配置文件 加载顺序](http://7xq89b.com1.z0.glb.clouddn.com/shell-x.jpg) ![shell 登录显示信息](http://7xq89b.com1.z0.glb.clouddn.com/shell-issue.jpg) ``` source 配置文件 # 加载配置文件, 默认需要 注销->重新登录 才能生效 # umask 默认权限 # 文件最大: 666, 目录最大 777 # umask 指定需要被减去的权限 # 其他环境配置文件 ~/.bash_logout ~/.bash_history /etc/issue # 本地终端 /etc/issue.net -> /etc/ssh/ssh_config -> banner # 决定远程登录 /etc/motd # 登录后显示信息 ``` 通配符: `* ? []` -> 完全匹配 正则: grep / awk / sed -> 包含匹配, 在文件中搜索符合条件的字符串 ``` \ 转义符 * 前一个字符 >=0 次, 要小心 a* 和 .* 是一样的 . 一个字符 ^/$ 行首/行尾 [] 范围内任意一个 [^] 取反 \{n,m\} 前一个字符 n~m 次, 注意是否需要添加左右边界 # 例子 [0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\} # 日期: Y-m-d [0-9]\{1,3\}\.[0-9]\{1.3\}.[0-9]\{1,3\}\.[0-9]\{1.3\} # ip # grep: 行提取 grep -n -v rexp file # num: 行号 v: 取反 # cut: 列提取, 对 列 的格式要求高 cut -f 2 -d ':' file # f: 列 d: 分隔符; 要注意 分隔符 # printf 格式化输出 %ns %ni %m.nf # awk -> 列 awk 'pattern{action}' file pattern: BEGIN / END / 条件语句 awk '{print $2 "\t" $4}' file # 相当于 cut -f 2,4; print 会自动在末尾加上 \n awk 'BEGIN{FS=":"}' # 使用不同的分隔符, 必须写在最前面, 默认使用 空格/\t 分隔 awk -F'\'' /error/ file # 指定 ' 为分割符, 匹配文件中的 error 部分 # sed -> 行 sed [option] 'action' file option: -n 只显示需要处理的数据 -e 同时应用多个 action -i 保存修改到文件 action: a 追加 c 行替换 i 插入 p 打印 s 字符串替换 d 删除 sed -e 'action;action' # 同时应用多个 action # sort sort -f -n -r -t -k n,m # f 忽略大小写 n 以数值排序, 默认为字符串 r 反向排序 t 分隔符, 默认为 \t k 指定范围 # wc wc -l -w -m # l line w word m char ``` ![文件类型判断](http://7xq89b.com1.z0.glb.clouddn.com/shell-file-type.jpg) 条件判断式 ``` # 文件判断 test -e file # 文件类型 [ -e file] # 注意要有空格 -w file # 判断是否有 w 权限, 注意不区分用户 file1 -nt -ot -ef file2 # new old equeal: 使用 iNode 判断 # 数组判断 n1 -eq -ne -gt -lt -ge -le n2 # 字符串判断 -z -n == != # 多重条件判断 -a -o ! # and/or/not ``` 流程控制 ``` env|grep USER|cut -d '=' -f 2 # 获取登录用户 df -h|grep vda1|awk '{print $5}'|cut -d '%' -f 1 # 获取系统盘使用率 [ -n $(ps aux|grep nginx|grep -v grep)] # 判断进程是否运行 [ -z $(echo $num|sed 's/[0-9]//g')] # 判断是否为全数字 # if [condition] && echo yes || echo no # 类似3元操作符的栗子 if [condition]; then # then 可以换行 todo elif [condition]; then todo else todo fi # case case $var in con1) todo ;; con2) todo ;; *) todo ;; esas # for for $var in array do todo done for((i=1;i<10;i=i+1)) do # 不能使用 i++ todo done # while while [condition] do todo 修改循环条件 done ``` ``` echo -e "\e[1;31m daydaygo \e[1;0m" # shell 高亮显示, 注意要 闭合 颜色输出, 否则会影响后面的输入的颜色 # vim /etc/vimrc # vim 系统配置文件 ~/.vimrc # 配置文件 "Add by daydaygo" syntax on set autoindent set cindent set ru set number set cursorline set cursorcolumn autocmd BufNewFile *.py,*.sh, exec ":call SetTitle()" let $author_name="daydaygo" let $author_email="1252409767@qq.com" func SetTitle() call setline(1, "\####################################") call append(line("."), "\# File Name: ".expand("%")) call append(line(".")+1, "\# Author: ".$author_name) call append(line(".")+2, "\# Email: ".$author_email) call append(line(".")+3, "\# Created Time: ".strftime("%c")) call append(line(".")+4, "\#================================") if &filetype == 'sh' call append(line(".")+5, "\#!/bin/bash") else call append(line(".")+5, "\#!/usr/bin/python") endif call append(line(".")+6, "") autocmd BufNewFile * normal G endfunc ``` - 系统信息&运行状态拉取 内存相关信息 cache: 主要用于打开的文件; LRU; 文件读取特别高 buffer: 主要用于目录项 / iNode 等; FIFO; iNode 比较高 ``` # os 信息 uname -a uname -srmo cat /etc/issue # os 版本 hostname # uname -a; echo $HOST hostname -I # 内网ip curl -s http://ipecho.net/plain # 外网ip cat /etc/resolv.conf # dns 信息 ping -c 2 baidu.com &>/dev/null && echo 'net ok' || echo 'net down' /proc # 系统实时信息, top 等工具都是读取这里的文件 /proc/meminfo # 内存信息 # 内存 free -m # 查看内存使用情况 # 第一行: 系统使用内存: total - free # 第二行: 应用使用内存: total - (free + cache + buffer) # cpu top -n 1 -b|grep 'load average' # 获取 cpu 使用 # 硬盘 df -h|grep -vE 'vda|tmpfs'|awk '{print $1 " " $5}' ``` 网络命令: ping nslookup(dns) nm-tool traceroute telnet nc(路由相关) dig curl 监控: ps netstat pgrep 应用: mysql ab mongo php jstack(java) 第三方: nginxstatus nagios-libexec 服务器接口 nginx: `http_stub_status_module` nutracker 监控集群状态(redis, memcache) mongoDB mysql 主从复制状态: `show slave status` `slave_IO_Runing` `Seconds_Behind_Master` ``` # 获取网站返回的状态码, 来确定网站是否 ok curl -I -m 10 -o /dev/null -s -w %{http_code}"\n" https://daydago.top # mysql nc -z -w2 ip port # 判断 tcp 连接是否ok\ mysql -hxxx -uxxx -pxxx -e 'show slave status' ``` ``` # 获取访问 ip 统计 cat /var/log/nginx/access.log|awk '{print $1}'|sort|uniq -c|sort -nr|more # 获取 http 状态码 cat /var/log/nginx/access.log|grep -ioE 'HTTP/1.[0|1]" [0-9]{3}'|awk '{print $2}' ``` shell: os是不能识别我们输入的 ls 这样的命令的, 需要翻译成 机器码 os 才能识别, 翻译的过程就是 shell 来完成的 可以尝试效率更高的 shell: fish 2中主要类型: B(linux , 其中bash 是标准) / C(unix, 类 c 语法) shell 可以一层一层嵌套 echo $SHELL # 查看当前使用的 shell /etc/shells # 当前系统安装的 shell C-d # 退出当前shell, 比如 退出 redis-cli / mysql - echo -e: 开启转义, 需要使用 "" 常规转义字符 16进制 \x 颜色: \e[1;31m xxx \e[0m `#! /bin/bash`: 表示 使用 /bin/bash 来解析当前脚本