Shell和变量
一、编程语言
什么是编程
1.想清楚做事步骤
2.用一种计算机能听懂的语言(编程语言)
编程语言分类
机器语言:直接使用二进制指令去编写程序
问题:
1、二进制指令难以记忆
2、开发复杂:实现一个简单的操作都需要很多条指令才能完成
汇编语言:用英文标签替代机器语言的二进制指令编写程序
解决的问题:不用记忆二进制指令
存在的问题:开发仍然比较复杂
高级语言:用人类能理解的表达方式去编写程序
1、编译型(C语言,go语言):
2、解释型(shell、python):
执行效率:机器语言> 汇编语言>高级语言(编译型>解释型)
开发效率:机器语言<汇编语言《高级语言
什么是程序
就是一堆代码文件
什么是进程
进程是程序运行的过程,也可以说是操作干活的过程,因为是操作系统负责控制硬件来运行应用程序
ps:进程与进程之间的内存空间是互相隔离的
计算机体系的三层结构
应用程序
操作系统
计算机硬件
运行shell程序两种方式
方式一:交互式环境(登录用户之后默认就会进入用户的shell解释器交互式环境)
优点:输入命令立即拿到代码的运行结果,即时运行
缺点:无法永久保存代码,退出交互式环境,代码全部丢失
方式二:把代码写到文件中,然后运行
优点:可以永久保存代码,以便后期重复使用
缺点:无法即时运行
二、什么是元字符
元字符属于shell这门编程语言的语法,被shell解释器解释的特殊字符
ps:grep命令解释的特殊符号=》正则表达式,正则与元字符中的符号都是公用的,但是表示的意义截然不同
三、buffer和cache清理
系统会调用一部分空闲的内存当作buffer缓冲和cache缓存,如果发现内存不够用了,则会选择释放掉一部分。
并不是所有cache都可以释放,被用作ramfs的内存
buffer
当cpu运行时产生一部分数据的时候,不会立马写入到磁盘,而先会在内存里缓冲一部分产生的数据然后在写入到磁盘里。
cache
当cpu运行某条进程时,需要读取某条信息。然而这条信息在磁盘内,如果每次查看都需要往磁盘取数据时,会很慢。所以当第一次取完数据时,Linux操作系统会选择一些数据存放在cache中,以便下次再取。
7200转速的磁盘平均寻道时间是5毫秒,平均潜伏期的时间大约是4毫秒
平均访问时间等于平均寻道时间与平均潜伏期之和,有了cache大大减少了cpu重新读取时的时间
1.写入磁盘
sync
sync
2.查看内存使用
free -w
#总内存大小 使用的内存 空闲的内存 使用过的内存(公共的空间) 能启用进程的空间
total used free shared buffers cache available
Mem: 995896 204300 218716 7784 2076 570804 582752
Swap: 1048572 264 1048308
3.清空buffer和cahce
并不是所有cache都可以释放,被用作ramfs的内存
echo 3 > /proc/sys/vm/drop_caches
4.再次查看buffer和chashe
free -w
total used free shared buffers cache available
Mem: 995896 190400 655576 7784 0 149920 628560
Swap: 1048572 264 1048308
四、僵尸进程和孤儿进程
僵尸进程
每一个进程终止之后都会变成僵尸进程,变成僵尸进程之后会释放自己占用的空间,但是会留下他的pid等父进程回收
1.Linux内置的程序变成僵尸进程之后,系统的总进程(system/init)会调用wait或者waitpid将其回收它的pid。
2.如果开发写的进程没有写调用系统接口回收子进程的程序,然后运行起来,那么会出现僵尸进程。注意:没写的话只能杀主进程,但是!!!!!杀了主进程这个程序就会停止运行,那么。。就等着背锅把。
3.如果写了调用系统接口回收子进程了,但是写了需要等待一段时间,也可以写个提前通知回收子进程的命令“kill -CHLD pid”(通常没有用)
4.当主进程没了,所有的子进程都会变成孤儿进程,会被系统的1号进程(system/init)收养,然后被回收。
五、特殊符号
!$取上一条命令的参数
[]:代表匹配一个字符,该字符属于[]内规定的任意字符
[! ] [^ ]取反 [!1+-] [!-1+] 取不是-和数字,-不能放中间
*任意多个字符
()在子shell进程/子进程中运行命令
[root@Centos7 ~]# (x=1)
[root@Centos7 ~]# echo $x
[root@Centos7 ~]#
[root@Centos7 ~]# umask
0022
[root@Centos7 ~]# (umask 666;touch {a..c}.txt)
[root@Centos7 ~]# touch d.txt
[root@Centos7 ~]# ll
total 4
-rw-------. 1 root root 1523 Jun 29 23:38 anaconda-ks.cfg
---------- 1 root root 0 Aug 25 18:53 a.txt
---------- 1 root root 0 Aug 25 18:53 b.txt
---------- 1 root root 0 Aug 25 18:53 c.txt
-rw-r--r-- 1 root root 0 Aug 25 18:53 d.txt
=赋值,==判断是否相等
\ 转义
{}
: echo $? 正确输出
0
;、&&、||
?匹配任意一个字符,一个?代表一个字符
unset 取消变量
六、运行shell的四种方式
1.方式一:绝对路径,需要当前用户对脚本文件有rx权限
2. ./脚本文件.sh,需要当前用户对脚本文件有rx权限
3.指定解释器来解释执行脚本程序,需要当前用户对脚本文件有r权限
bash
sh
如果脚本里面有变量,在当前bash中是调用不出来的,
以上三种方式都是在子bash进程中运行,一般建议使用
4.在当前bash进程中运行
socrce
.
如果脚本里面有变量,在当前bash中可以调用,一般不使用
七、变量
1.变量赋值
Shell变量赋值
!/bin/bash
read -p "请给变量赋值:" Name
echo "你输入的值为:$Name"
-t 指定时间
-n 指定长度
2.位置参数
位置参数:$n
[root@Centos7 ~]# cat server.sh
!/bin/bash
echo $0
echo $1
echo $2
echo $3
echo $4
echo $5
echo $6
echo $7
echo $8
echo $9
echo ${10}
echo ${11}
[root@Centos7 ~]# ./server.sh 111 222 333 444 555 666 777 888 999 1000 2000
./server.sh
111
222
333
444
555
666
777
888
999
1000
2000
3.求变量长度
求长度
[root@Centos7 day02]# age=111
[root@Centos7 day02]# echo ${age}
111
[root@Centos7 day02]# echo ${#age}
3
[root@Centos7 day02]# echo $age | wc -L
3
[root@Centos7 day02]# echo $age | awk "{print length}"
3
4.切片
切片
[root@Centos7 day02]# msg="hello world"
[root@Centos7 day02]# echo ${msg}
hello world
[root@Centos7 day02]# echo ${msg:4}
o world
[root@Centos7 day02]# echo ${msg:4:3}
o w
[root@Centos7 day02]# echo ${msg::3}
hel
5.截断
1、删除左边的
[root@Centos7 day02]# url="www.sina.com.cn"
[root@Centos7 day02]# echo ${url#www.}
sina.com.cn
[root@Centos7 day02]# echo ${url#.}
sina.com.cn
[root@Centos7 day02]# echo ${url##.}
cn
[root@Centos7 day02]#
2、删除右边的
[root@Centos7 day02]# url="www.sina.com.cn"
[root@Centos7 day02]# echo ${url%.cn}
www.sina.com
[root@Centos7 day02]# echo ${url%.}
www.sina.com
[root@Centos7 day02]# echo ${url%%.}
www
[root@Centos7 day02]# echo ${url%%w}
[root@Centos7 day02]# echo ${url%w}
ww
[root@Centos7 day02]#
3、示例
[root@Centos7 ~]# hostname
www.oldboy.com
[root@Centos7 ~]# echo $HOSTNAME
www.oldboy.com
[root@Centos7 ~]# echo ${HOSTNAME%%.}
www
[root@Centos7 ~]# echo ${HOSTNAME#www.}
oldboy.com
6.预定义变量
预定义变量 系统的特殊变量
$0 # 脚本本身
$ # 获取命令行传入的所有的位置参数
$@ # 获取命令行传入的所有的位置参数(支持正则)
$# # 获取命令行传入的所有的位置参数的个数
$? # 获取上一条命令的执行状态,0代表成功,非0代表失败
$$ # 获取当前进程的pid # $PPID $UID
命令的嵌套使用 $($()) 将输出的结果交给变量进行赋值
示例1:$*与$@的区别
[root@Centos7 ~]# cat 5.sh
!/bin/bash
for i in "$*"
do
echo $i
done
echo "================"
for i in "$@"
do
echo $i
done
[root@Centos7 ~]# ./5.sh aaa bbb ccc "ddd eee"
aaa
bbb
ccc
ddd eee
示例2:
[root@Centos7 ~]# cat ping.sh
!/bin/bash
for ip in $*
do
ping -c1 $ip &>/dev/null
[ $? == 0 ] && echo "$ip:up" || echo "$ip:down"
done
[root@Centos7 ~]#
[root@Centos7 ~]# chmod +x ping.sh
[root@Centos7 ~]# ./ping.sh 127.0.0.1 10.10.0.10 10.10.0.11 172.168.11.12
127.0.0.1:up
10.10.0.10:down
10.10.0.11:down
172.168.11.12:down
示例3:
[root@Centos7 ~]# cat ping2.sh
!/bin/bash
for ip in $*
do
(ping -c1 $ip &>/dev/null ; [ $? == 0 ] && echo "$ip:up" >> ping.log || echo "$ip:down" >> ping.log) &
done
7.变量的替代
${#变量} #获取变量值的长度
${变量#匹配规则} #从头开始匹配,最短删除
${变量##匹配规则} #从头开始匹配,最长删除
${变量%匹配规则} #从尾开始匹配,最短删除
${变量%%匹配规则} #从尾开始匹配,最长删除
${变量/旧的字符串/新的字符串} #替换变量中旧的字符串为新的字符串,只替换第一个匹配到
${变量//旧的字符串/新的字符串} #替换变量中旧的字符串为新的字符串,全部替换
${变量:匹配规则:匹配规则} #索引及切片
变量值的替换
[root@Centos7 ~]# url="www.sina.com.cn"
[root@Centos7 ~]# echo ${url/./}
wwwsina.com.cn
[root@Centos7 ~]# echo ${url//./} # 全部替换
wwwsinacomcn
[root@Centos7 ~]# echo ${url//./|}
www|sina|com|cn
应用
[root@Centos7 test]# ls
e_2020_01_linux.txt e_2020_03_linux.txt e_2020_05_linux.txt
e_2020_02_linux.txt e_2020_04_linux.txt
[root@Centos7 test]#
[root@Centos7 test]# echo ls /test/
e_2020_01_linux.txt e_2020_02_linux.txt e_2020_03_linux.txt e_2020_04_linux.txt e_2020_05_linux.txt
[root@Centos7 test]# for fname in ls /test/
do
echo $fname
done
e_2020_01_linux.txt
e_2020_02_linux.txt
e_2020_03_linux.txt
e_2020_04_linux.txt
e_2020_05_linux.txt
[root@Centos7 test]# for fname inls /test/
; do mv $fname ${fname/_linux/}; done
[root@Centos7 test]# ls
e_2020_01.txt e_2020_02.txt e_2020_03.txt e_2020_04.txt e_2020_05.txt
[root@Centos7 test]#
1、${parameter-word}: 当调取变量没有定义过,就返回word字符串信息
[root@Centos7 ~]# unset x
[root@Centos7 ~]# echo ${x-111}
111
[root@Centos7 ~]#
[root@Centos7 ~]# x=333
[root@Centos7 ~]# echo ${x-111}
333
[root@Centos7 ~]# x=
[root@Centos7 ~]# echo ${x-111}
2、${parameter:-word}: 当调取变量没有定义过或者是定义过变量但是值为空, 就返回word字符串信息
[root@Centos7 ~]# unset x
[root@Centos7 ~]# echo ${x:-111} # 变量从未定义过
111
[root@Centos7 ~]#
[root@Centos7 ~]# x=333
[root@Centos7 ~]# echo ${x:-111} # 变量定义过,并且值为333
333
[root@Centos7 ~]# x=
[root@Centos7 ~]# echo ${x:-111} # 变量定义过,并且值为空
111
[root@Centos7 ~]#
3、{parameter:=word}:当调取变量信息值为空时或未定义,则设置指定字符串为新的变量值
[root@Centos7 ~]# unset x
[root@Centos7 ~]# echo ${x:=111}
111
[root@Centos7 ~]# echo $x
111
[root@Centos7 ~]#
[root@Centos7 ~]# x=
[root@Centos7 ~]# echo ${x:=111}
111
[root@Centos7 ~]# echo $x
111
[root@Centos7 ~]#
[root@Centos7 ~]# x=333
[root@Centos7 ~]# echo ${x:=111}
333
[root@Centos7 ~]# echo $x
333
[root@Centos7 ~]#
4、${parameter:?word}:当调取变量信息值为空时或未定义,指定为赋值的错误提示信息
[root@Centos7 ~]# unset x
[root@Centos7 ~]# echo ${x:?变量不存在傻叉}
-bash: x: 变量不存在傻叉
[root@Centos7 ~]#
[root@Centos7 ~]# x=
[root@Centos7 ~]# echo ${x:?变量不存在傻叉}
-bash: x: 变量不存在傻叉
[root@Centos7 ~]#
[root@Centos7 ~]#
[root@Centos7 ~]# x=123
[root@Centos7 ~]# echo ${x:?变量不存在傻叉}
123
[root@Centos7 ~]#
5、${parameter:+word}:当调取变量信息值为空时或未定义,不做任何处理,否则word字符串将替代变量值
[root@Centos7 ~]# unset x
[root@Centos7 ~]# echo ${x:+111} # 没有定义x,此时属于没有值的范畴
[root@Centos7 ~]# echo $x
[root@Centos7 ~]# x=
[root@Centos7 ~]# echo ${x:+111} # 定义了x但是x的值为空,此时也属于没有值的范畴
[root@Centos7 ~]# echo $x
[root@Centos7 ~]#
[root@Centos7 ~]#
[root@Centos7 ~]# x=333
[root@Centos7 ~]# echo ${x:+111} # x有值,有值则替代
111
[root@Centos7 ~]# echo $x # 替代不等于赋值
333
[root@Centos7 ~]#
8.变量只读
[root@Centos7 ~]# age=18
[root@Centos7 ~]# readonly age
[root@Centos7 ~]#
[root@Centos7 ~]# age=19
-bash: age: readonly variable
[root@Centos7 ~]# expr $age + 1
19
[root@Centos7 ~]# age=expr $age + 1
-bash: age: readonly variable
僵尸进程
每一个进程终止之后都会变成僵尸进程,变成僵尸进程之后会释放自己占用的空间,但是会留下他的pid等父进程回收
1.Linux内置的程序变成僵尸进程之后,系统的总进程(system/init)会调用wait或者waitpid将其回收它的pid。
2.如果开发写的进程没有写调用系统接口回收子进程的程序,然后运行起来,那么会出现僵尸进程。注意:没写的话只能杀主进程,但是!!!!!杀了主进程这个程序就会停止运行,那么。。就等着背锅把。使用还是跟开发商量去。
3.如果写了调用系统接口回收子进程了,但是写了需要等待一段时间,也可以写个提前通知回收子进程的命令“kill -CHLD pid”(通常没有用)