Linux系统与Shell环境准备
Linux基础
Linux都是借助Unix的工具软件,应用程序和网络协议而发明的。
常见的Linux版本
Linux与Windows的区别
###Linux的目录结构
Linux的基本命令
ls 列出目录
cd 切换目录
pwd 显示当前目录
mkdir 创建一个新的目录
rmdir 删除一个空的目录
cp 复制文件或目录
rm 移除文件或目录
mv 移动文件与目录,或修改文件与目录的名称
Shell基础
Shell相当于一个桥梁,打通了用户与Linux的关系。Shell是可以与Linux内核进行交互的。
市面上常用的Shell有如下几种:
- Bourne Shell (/usr/bin/sh或/bin/sh)
- Bourne Again Shell (/bin/bash) 最常用的,功能强大易用且免费
- C Shell (/usr/bin/csh)
- K Shell (/usr/bin/ksh)
- Shell for Root (/sbin/sh)
运行Shell
有两种方式可以运行shell。
方式一:
新建test.sh文件 (指定的是:Bourne Again Shell )
chmod + x ./test.sh # 使脚本具有执行权限
./test.sh
方式二:
/bin/sh test.sh # 指定的是:Bourne Shell
实战演练
- 使用何种方式执行Linux命令
如果操作系统是Windows,建议下载git工具,自带git bash,可以直接执行Linux上的命令。
如果操作系统是macOS,可以用mac自带的terminal,可以直接执行Linux上的命令。
如果操作系统是Linux,可以直接用Linux自带的terminal执行Linux上的命令。
- 我们来试一试
-
使用命令:
vim test.sh
进入tesh.sh编辑页面,按住“INSERT”键进行编辑操作,输入如下命令
-
按“ESC”键,输入“:wq”保存并退出。使用
cat test.sh
查看文件内容
-
方式一:执行test.sh
chmod + x ./test.sh # 使脚本具有执行权限
./test.sh
方式二:执行test.sh
/bin/sh test.sh # 指定的是:Bourne Shell
Linux常用命令
Linux常用命令包括如下3个方面:
文件
ls 列出目录
cd 切换目录
pwd 显示当前目录
mkdir 创建一个新的目录
rmdir 删除一个空的目录
cp 复制文件或目录
rm 移除文件或目录
mv 移动文件与目录,或修改文件与目录的名称
练习: 创建一个目录,将其他目录的文件移到新目录下,再删除新目录的文件及新目录。
mkdir tmp # 创建一个名为tmp的目录
mv test.sh ~/tmp # 移动test.sh文件到tmp目录
rm -rf test.sh # 强制删除test.sh文件
rmdir tmp # 删除tmp目录
文件属性可查看下图所示:
- r 表示读read 4
- w 表示写 read 2
- x 表示操作 execute 1
- 777 表示所有组可读可写可执行
练习:查看和修改文件的属性
ls -l # 查看文件属性
ls -ld # 查看指定文件的属性
chmod 777 test # 修改test目录的属性
网络
测试网络连接情况
格式:ping 参数 目标主机
参数如下:
ping -c 2 www.baidu.com # ping地址www.baidu.com 2次
ping -c 2 -i 2 www.baidu.com # ping地址www.baidu.com 2次 每次间隔2秒
打印Linux网络系统的状态信息
netstat命令用于显示与IP、TCP、UDP和ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况。netstat是在内核中访问网络及相关信息的程序,它能提供TCP连接,TCP和UDP监听,进程内存管理的相关报告。
TCP连接状态详解
LISTEN: 侦听来自远方的TCP端口的连接请求
SYN-SENT: 再发送连接请求后等待匹配的连接请求
SYN-RECEIVED:再收到和发送一个连接请求后等待对方对连接请求的确认
ESTABLISHED: 代表一个打开的连接
FIN-WAIT-1: 等待远程TCP连接中断请求,或先前的连接中断请求的确认
FIN-WAIT-2: 从远程TCP等待连接中断请求
CLOSE-WAIT: 等待从本地用户发来的连接中断请求
CLOSING: 等待远程TCP对连接中断的确认
LAST-ACK: 等待原来的发向远程TCP的连接中断请求的确认
TIME-WAIT: 等待足够的时间以确保远程TCP接收到连接中断请求的确认
CLOSED: 没有任何连接状态
命令格式
netstat(选项)
命令选项
-a或–all:显示所有连线中的Socket;
-A<网络类型>或–<网络类型>:列出该网络类型连线中的相关地址;
-c或–continuous:持续列出网络状态;
-C或–cache:显示路由器配置的快取信息;
-e或–extend:显示网络其他相关信息;
-F或–fib:显示FIB;
-g或–groups:显示多重广播功能群组组员名单;
-h或–help:在线帮助;
-i或–interfaces:显示网络界面信息表单;
-l或–listening:显示监控中的服务器的Socket;
-M或–masquerade:显示伪装的网络连线;
-n或–numeric:直接使用ip地址,而不通过域名服务器;
-N或–netlink或–symbolic:显示网络硬件外围设备的符号连接名称;
-o或–timers:显示计时器;
-p或–programs:显示正在使用Socket的程序识别码和程序名称;
-r或–route:显示Routing Table;
-s或–statistice:显示网络工作信息统计表;
-t或–tcp:显示TCP传输协议的连线状况;
-u或–udp:显示UDP传输协议的连线状况;
-v或–verbose:显示指令执行过程;
-V或–version:显示版本信息;
-w或–raw:显示RAW传输协议的连线状况;
-x或–unix:此参数的效果和指定"-A unix"参数相同;
–ip或–inet:此参数的效果和指定"-A inet"参数相同。
netstat # 打印linux网络系统的状态信息
netstat -t # 列出所有的tcp
netstat -l # 只显示监听端口
netstat -lnpt # 以数字形式列出所有得tcp和pid和监听端口
性能
top和ps的区别:top是实时监控的,ps相当于一个快照。
top # 持续监视系统性能
ps # 查看进程信息
ps -aux # 显示所有进程,包括用户,分组情况
man ps # 查看ps的帮助文档
Linux三剑客与管道使用
Linux常用工具
管道
Linux提供管道符“|”将两个命令隔开,管道符左边命令的输出就会作为管道符右边命令的输入。
练习
echo "heelo1234" | grep "heelo" # 输出“heelo1234”并使用grep在输出中查找“heelo”
正则表达式
正则表达式就是记录文本规则的代码。
常用元字符
代码/语法 | 说明 |
---|---|
. | 匹配除换行符以外的任意字符 |
\w | 匹配字母或数字或下划线或汉字 |
\s | 匹配任意的空白符 |
\d | 匹配数字 |
\b | 匹配单词的开始或结束 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
常用限定符
代码/语法 | 说明 |
---|---|
* | 重复零次或多次 |
+ | 重复一次或多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或多次 |
{n,m} | 重复n次到m次 |
练习
待匹配字符:https://tool.oschina.net111/regex;https://tool.oschina.net/regex.222;987;98076;789098765;987567895433;8989765432123;a124477b
# 匹配以o开头的单词
正则:\bo\w*\b
# 匹配刚好5个字符的单词
正则:\b\w{5}\b
# 匹配1个或更多连续的数字
正则:\d+
# 匹配5位到12位QQ号码
正则:\d{5,12}
如果需要匹配必须是数字开头结尾的字符可用:^\d{5,12}$
grep
grep:根据用户指定得模式(pattern)对目标文本进行过滤,显示被模式匹配到的行。
常用选项:
- -v 显示不被pattern匹配到的行
- -i 忽略字符大小写
- -n 显示匹配的行号
- -c 统计匹配的行数
- -o 仅显示匹配到的字符串
- -E 使用ERE,相当于egrep
练习
test.txt文件内容如下:
# 查找文件内容包含oschina的行数
grep -n oschina test.txt
# 查找文件内容不包括oschina的行
grep -nv oschina test.txt
# 查找以https开头的行
grep ^https test.txt
# 查找以regex;结尾的行
grep regex\;$ test.txt # 注意这里;需要转译
# 匹配以数字开头数字结尾的行
grep -P '^\d.+\d$' test.txt
sed
sed是流编辑器,一次处理一行内容。
注意:sed是对模式空间进行处理,不会修改原文件。
命令格式:sed [-hn…][-e
- -h 显示帮助
- -n 静默模式,仅显示script处理后的结果
- -e
常用动作
- a 新增
bash sed -e "4 a newline" # sed指定了一个脚本,内容是:在第4行后面新增一行,内容为newline
- c 取代
bash sed -e "2,5c No 2-5 number" # sed指定了一个脚本,内容是:使用No 2-5 number取代2行~5行的内容
- d 删除
bash sed -e "2,5d" # sed指定了一个脚本,内容是:删除2~5行内容
- i 插入
bash sed -e "2i newline" # sed指定了一个脚本,内容是:在第2行前面插入一个新行,内容是newline
- p 打印
bash sed -e "/root/p" # sed指定了一个脚本,内容是:打印匹配到root的内容
- s 取代
bash sed -e "s/old/new/g" # sed指定了一个脚本,内容是:用new替代old, g代表全局
练习
man sed # 查看帮助文档
sed -h # 查看帮助文档
# 在第4行后面添加新的字符串
sed -e '4a thisistest' test.txt # 注意:test.txt的文件内容不会被修改
# 在第2行前添加新的字符串
sed -e '2i test' test.txt
# 全局替换
sed -e 's/https/http/g' test.txt
# 直接修改文件内容
sed -i 's/https/http/g' test.txt
awk
awk:将文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行后续处理。
命令格式:awk ‘pattern + action’ [FILE]
- pattern 正则表达式
- action 对匹配到得内容执行的命令(默认为输出每行内容)
常用参数
- FILENAME awk浏览的文件名
- BEGIN 处理文本之前要执行的操作
- END 处理文本之后要执行的操作
- FS 设置输入域分隔符,等价于命令行-F选项
- NF 浏览记录的域的个数(列数)
- NR 已读的记录数(行数)
- OFS 输出域分隔符
- ORS 输出记录分隔符
- RS 控制记录分隔符
- $0 整条记录
- $1 表示当前行的第一个域…以此类推
练习
# 搜索/etc/password有root关键字的所有行,并显示第7个域对应的shell
# -F: 表示指定冒号作为分隔符
awk -F: '/root/{print $1}' /etc/passwd # 注意冒号后面的空格不能省略
# 打印/etc/password的第二行信息
awk -F: 'NR==2{print $2}' /etc/passwd
# 使用begin加入标题
awk 'BEGIN {print "title1", "title2"}{print $1,$2}' /etc/passwd
# 自定义分隔符
echo "111 222|333 444|555 666" | awk 'BEGIN{RS="|"}{print $0}'
Bash编程语法
变量
变量命令规则
- 命名只能使用英文字母,数字和下划线,不能以数字开头
- 中间不能有空格,可以使用下划线(_)
- 不能使用标点符号
- 不能使用bash里的关键字(可以使用help命令查看保留关键字)
定义和使用变量
- 新建test.sh文件
- 在test.sh输入如下内容
#!/bin/bash
a=100
echo "$a"
- 执行test.sh文件
只读变量
格式:readonly 变量名
可以使用readonly设置变量只读,设置为只读后就不能进行修改,删除操作。
删除变量
格式:unset 变量名
注意:不能删除只读变量
变量类型
- 字符串
your_name="flora"
- 拼接字符串
greeting="hello, "$your_name"!"
- 数组
array_name=(value0 value1 value2 value3)
- 取数组
valuen=${array_name[n]}
- 单独赋值
array_name[0]=value0
- 取数组
控制语句
if
格式:
if [ condition ];then command 1;command 2;...;command N;else command 1;command 2;...;command N;elif [condition ]; command 1;command 2;...;command N;fi
# 或者如下写法
if [ condition ]
then
{
command 1
command 2
……
command N
}
else
{
command
}
elif [condition ]
{
command
}
fi
注意事项
1、[ ]表示条件测试。注意这里的空格很重要。要注意在’[‘后面和’]'前面都必须要有空格
2、在shell中,then和fi是分开的语句。如果要在同一行里面输入,则需要用分号将他们隔开。
3、注意if判断中对于变量的处理,需要加引号,以免一些不必要的错误。没有加双引号会在一些含空格等的字符串变量判断的时候产生错误。比如[ -n “$var” ]如果var为空会出错
4、判断是不支持浮点值的
5、如果只单独使用>或者<号,系统会认为是输出或者输入重定向,虽然结果显示正确,但是其实是错误的,因此要对这些符号进行转译
6、在默认中,运行if语句中的命令所产生的错误信息仍然出现在脚本的输出结果中
7、使用-z或者-n来检查长度的时候,没有定义的变量也为0
8、空变量和没有初始化的变量可能会对shell脚本测试产生灾难性的影响,因此在不确定变量的内容的时候,在测试号前使用-n或者-z测试一下
9、? 变量包含了之前执行命令的退出状态(最近完成的前台进程)(可以用于检测退出状态)
10、如果使用< >符号,需要使用两个[[]],如[[a > b]]。如果使用-gt, -lt, -eq来替代的话,就可以只使用一个[]。
for
格式:
for var in item1 item2 ... itemN;do command 1;command 2;...;command N;done
# 或者如下写法
for var in item1 item2 ... itemN
do
{
command 1
command 2
...
command N
}
done
while
格式:
while condition;do command 1;command2;done
# 或者如下写法
while condition
do
{
command 1
command 2
}
done
循环读取文件内容并输出
for与while的区别
while循环默认以行读取文件,而for循环以空格读取文件切分文件。
从以下示例可以很明显看出区别。
Bash脚本编写
Bash脚本的基本使用
- read命令是用于从终端或者文件中读取输入的内部命令
- 读取整行输入
- 每行末尾的换行符不被读入
read命令使用
- 从标准输入读取输入并赋值给变量
read var
- 从标砖输入读取多个内容
read var1 var2 var3
- 不指定变量(默认赋值给REPLY)
read
脚本参数传递
- $0 脚本名称
- 1 1~ 1 n 获取参数
- $# 传递到脚本得参数个数
- $$ 脚本运行的当前进程ID号
- $* 以一个单字符串显示所有向脚本传递的参数
- $? 显示最后命令的退出状态。0表示没有错误,其他任何值表示有错误
基本运算
- 加法 +
`expr $a + $b`
- 减法 -
`expr $a - $b`
- 乘法 * (需要用到转译字符)
`expr $a \* $b`
- 除以 /
`expr $a / $b`
- 取余 %
`expr $a % $b`
- 赋值 =
a=$b
- 相等 == (相等返回true,否则返回false)
# 注意空格[空格$a空格==空格$b空格]
[ $a == $b ]
- 不相等 != (不相等返回true,否则返回false)
# 注意空格[空格$a空格!=空格$b空格]
[ $a != $b ]
- -eq 检测相等
# 注意空格[空格$a空格-eq空格$b空格]
[ $a -eq $b ]
- -ne 检测不相等
# 注意空格[空格$a空格-ne空格$b空格]
[ $a -ne $b ]
- -gt 检测左边是否大于右边
# 注意空格[空格$a空格-gt空格$b空格]
[ $a -gt $b ]
- -lt 检测左边是否小于右边
# 注意空格[空格$a空格-lt空格$b空格]
[ $a -lt $b ]
- -ge 检测左边是否大于等于右边
# 注意空格[空格$a空格-ge空格$b空格]
[ $a -ge $b ]
- -le 检测左边是否小于等于右边
# 注意空格[空格$a空格-le空格$b空格]
[ $a -le $b ]
bash与linux命令组合
对目录进行操作
# 创建目录并生成文件
mkdir test
cd test
echo "hello">test.txt
ls
bash与内存
# 统计内存使用
#!/bin/bash
for i in `ps aux | awk '{print $6}' | grep -v 'RSS'`
{
count=$[$count+$i]
}
echo "$count/kb"
文件参数传递的基本操作
Linux进阶命令
推荐抓包工具:Charles
Curl
curl 是一个工具,用于传输来自服务器或者到服务器的数据。「向服务器传输数据或者获取来自服务器的数据」
可支持的协议有(DICT、FILE、FTP、FTPS、GOPHER、HTTP、HTTPS、IMAP、IMAPS、LDAP、LDAPS、POP3、POP3S、RTMP、RTSP、SCP、SFTP、SMTP、SMTPS、TELNET和TFTP)。
curl提供了大量有用的技巧,比如代理支持、用户身份验证、FTP上传、HTTP post、SSL连接、cookie、文件断点续传、Metalink等等。
注意:curl命令执行中是不可进行交互的。
curl https://www.baidu.com # 默认是使用-G
常用选项
- -x, --proxy <[protocol://][user:password@]proxyhost[:port]>
使用指定的HTTP代理。如果没有指定端口号,则假定它位于端口1080。
curl -x 127.0.0.1:8888 https:www.baidu.com
- -G, --get
使用此选项时,将使所有使用 -d, --data 或 --data-binary 指定的数据在HTTP GET请求中使用,而不是在POST请求中使用。
数据将被追加到URL的一个 ‘?’ 的分隔符后。
如果与 -I 结合使用,POST数据将被替换追加到带有HEAD请求的URL中。
如果多次使用此选项,则只使用第一个选项。
curl -G https://www.baidu.com
- -X, --request
(HTTP)指定与HTTP服务器通信时的请求方式。默认GET
curl -X GET https://www.baidu.com
- -d, --data
使用该选项,那么默认请求方式为 POST。
(HTTP)在POST请求中向HTTP服务器发送指定的数据,与浏览器在用户填写HTML表单并按下submit按钮时所做的相同。这将导致curl使用content-type application/x-www-form-urlencoded将数据传递给服务器。
curl -d "login=1234" https://www.baidu.com # 默认发送POST请求
curl -X POST https://www.baidu.com
- -o, --output
输出到一个文件,而不是标准输出。
如果使用 {} 或 [] 来获取多个documents。可以使用 ‘#’ 后跟说明符中的一个数字。该变量将替换为正在获取URL的当前字符串。
curl -o tmp.html https://www.baidu.com
- -s, --silent
静默或静音模式。不显示进度表/条或错误消息。
curl -s https://www.baidu.com
- -v, --verbose
显示详细操作信息。主要用于调试。
以 > 开头的行表示curl发送的”header data”;< 表示curl接收到的通常情况下隐藏的”header data”;而以 * 开头的行表示curl提供的附加信息。
curl -v https://www.baidu.com
jq
jq 是 stedolan 开发的一个轻量级的和灵活的命令行JSON处理器。
jq 用于处理JSON输入,将给定过滤器应用于其JSON文本输入并在标准输出上将过滤器的结果生成为JSON。
最简单的过滤器是.,它将jq的输入未经修改地复制到其输出中(格式设置除外)。
请注意,jq 当前仅支持64位双精度浮点数(IEEE754)。
官网:https://stedolan.github.io/jq/manual/#Basicfilters
安装jq
# centos
yum install epel-release # 安装EPEL源
yum list jq # 安装完EPEL源后,可以查看下jq包是否存在
yum install jq 安装jq
常用方法
- 内容美化,增加缩进和高亮
echo '{"a":11, "b":12}' | jq '.'
注意:jq . 与jq ‘.’ 都可以。但是强烈建议加上单引号,防止触发bash语法。
- 内容提取
# 从数组中提取指定值
echo '{"foo": 42, "bar": "less interesting data"}' | jq .foo
# 从数组中提取单个数据
echo '[{"a":1, "b":2}, {"c":3, "d":4}]' | jq .[0]
# 从数组中提取所有数据
echo '[{"a":1, "b":2}, {"c":3, "d":4}]' | jq .[]
# 过滤多个值
echo '[{"a":1, "b":2}, {"c":3, "d":4}]' | jq .[0,1]
- 重组
# 数组重组成数组
echo '{"a":1, "b":2, "c":3, "d":4}' | jq '[.a,.b]'
# 数组重组成对象
echo '{"a":1, "b":2, "c":3, "d":4}' | jq '{"tmp":.b}'