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 in ls /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”(通常没有用)

4.当主进程没了,所有的子进程都会变成孤儿进程,会被系统的1号进程(system/init)收养,然后被回收。

posted @ 2021-06-01 10:32  柯正  阅读(97)  评论(0编辑  收藏  举报