linux学习总结

linux

一、常用命令-文件处理命令

命令格式: 命令 [-选项] [参数]

​ 例: ls -la /etc

说明:

  1. 个别命令使用不遵循此格式
  2. 当有多个选项时,可以写在一起
  3. 简化选项与完整选项

目录处理命令

1. ls(list) 显示目录文件

语法: ls [选项]

​ -a 显示所有文件,包括隐藏文件

​ -l 显示详细信息,可简化为ll

​ -d 查看目录属性

​ -i 查看目录节点

​ 例: ls -a

2. mkdir(make directories) 创建新目录

语法:mkdir [选项] [目录名]

​ -p 递归创建 (创建多重目录,如果目录不存在时,自动创建目录)

​ 例: mkdir -p /tmp/test/linux

​ mkdir /tmp/test/linux (如果test不存在是会报错)

3. cd(change directory) 切换目录

语法:cd [目录]

​ 例:cd /tmp/test/linux 切换到指定目录

​ cd … 回到上一级目录

4. pwd(Print Working Directory) 显示当前目录位置

5. rmdir(remove empty directories) 删除空目录

语法: rmdir [目录名]

​ 例:rmdir /tmp/test/linux

6. cp(copy) 复制文件或目录

语法:cp [选项] [原文件目录] [目标目录]

​ -r 复制目录

​ -p 保留文件属性

​ 例:cp -r /tmp/test/linux /root 将目录/tmp/test/linux复制到目录/root下

​ cp -rp /tmp/test/linux /root 将目录/tmp/test/linux复制到目录/root下,保持目录属性

7. mv(move) 剪切文件、改名

语法:mv [原文件或目录] [目标目录]

​ 例:mv /tmp/test/linux /root 将/tmp/test/linux剪切到/root

​ mv /tmp/test/linux /root/unix 将/tmp/test/linux剪切到/root,并改名unix

8. rm(remove) 删除文件

语法:rm [选项] [文件或目录]

​ -r 删除目录

​ -f 强制执行

​ 例: rm /tmp/test/test.sh 删除文件test.sh,系统会询问是否删除

​ rm -r /tmp/test/linux 删除目录

​ rm -rf /tmp/test/linux 强制删除目录,不用询问

​ rm -rf / 跑路

文件处理命令

1. touch 创建空文件

语法:touch [文件名]

​ 例: touch linux.list 可同时创建多个文件

2. cat 显示文件内容

语法:cat [选项] 文件

​ -p 显示行号

​ 例:cat /etc/issue

​ cat -n /etc/service

3. more 分页显示文件内容

语法:more [文件名]

​ (空格) 或f 翻页

​ (Enter) 换行

​ q或Q 退出

​ 例:more /etc/services

4. vi/vim 创建文件

语法:vi/vim 文件

​ 例:vim test.sh

5. ln(link) 生成链接文件

语法:ln -s [原文件] [目标文件]

​ -s 创建软链接文件

软链接特征:类似Window快捷方式,文件大小只是符号大小,箭头指向原文件

硬链接特征:除了文件路径,其它都一样

​ 例:ln -s /etc/issue /tmp/issue.soft 创建文件/etc/issue的软链接/tmp/issue.soft

​ ln /etc/issue /tmp/issue.hard 创建文件/etc/issue的硬链接/tmp/issue.hard

权限管理命令

文件权限:-rw-r–r--

第一个字符:‘-’ 文件类型 (- 二进制文件,d 目录, l 软链接文件)

rw-r–r–
ugo
u代表所有者g代表所属组o代表其他人
rwx
读权限写权限执行权限
可以查看文件内容可以修改文件内容可以执行文件
数字表示:4数字表示:2数字表示:1

rwxrw-r–

764

1. chomd 改变文件或目录权限

语法: chmod [{ugoa} {±=} {rwx}] [文件或目录]

​ [mode=421] [文件目录]

​ -R 递归修改

​ 例:chmod u+x 文件名 给所有者添加执行的权限

​ chmod g+w,o-r 文件名 给所属组添加写的权限,去掉其他人读的权限

​ chmod g=rwx 文件名 给所有者添加读写执行的权限

​ chmod 640 文件名 依照数字来赋予权限

说明:对目录有写权限才可删除文件

2. chown 改变文件或目录的所有者

语法:chown [用户] [文件或目录]

​ 例:chown king test.sh 改变文件test.sh的所有者为king

说明:只有root可操作,所有者不可操作

3. chgrp 改变文件或目录的所属组

语法:chgrp [用户组] [文件或目录]

​ 例:chgrp lampbrother test.sh 改变tesh.sh的所属组为lampbrother

4. umask 显示、设置文件的缺省权限

语法:umask [-S]

​ -S 以rwx的形式显示新建文件缺省权限

​ 例:umask -S

文件搜索命令

1. find 文件搜索

语法:find [搜索范围] [匹配条件] (配合通配符使用)

​ 例: find /etc -name init 在目录/etc中查找文件init -iname不区分大小写

​ find / -size +204800 在根目录下查找大于100MB的文件 +n大于 -n小于 n等于

​ find /home -user king 在根目录下查找所有者为king的文件 -group 根据所属组查找

​ find /etc -cmin -5 在/etc下查找5分钟内被修改过属性的文件和目录

​ (-amin 访问时间access,-cmin 文件属性change,-mmin 文件内容modify)

​ find /etc -size +163840 -a -size -204800 在/etc下查找大于80MB小于100MB的文件

​ (-a 两个条件同时满足,-o 两个条件满足任意一个即可)

​ find /etc -name inittab -exec ls -l {} \ 在/etc下查找inittab文件并显示其详细信息

​ (-exex/-ok 命令{}; 对搜索结果执行操作)

-type 根据文件类型查找

-inum 根据i节点查找

2. locate 在文件资料库中查找文件

语法:locate 文件名

​ 例: locate inittab 新建文件要先更新资料库updatedb才可查找

3. which 搜索命令所在目录及别名信息

语法:which [命令名称]

​ 例:which ls

4. grep 在文件中搜寻字符串匹配的行并输出

语法:grep -iv [指定字串] [文件]

​ -i 不区分大小写

​ -v 排除指定字串

​ 例:grep mysql /root/install.log

5. man 获得帮助信息

语法:man [命令或配置文件]

​ 例:man ls 查看ls命令的帮助信息

​ man services 查看配置文件services的帮助信息

6. help 获得Shell内置命令的帮助信息

语法:help 命令

​ 例:help umask 查看umask命令的帮助信息

用户管理命令

1. useradd 添加新用户

语法:useradd 用户名

例:useradd  jjj

2. passwd 设置用户密码

语法:passwd 用户名

​ 例:passwd jjj

3. who 查看登录用户信息

语法:who

(tty:本地终端,pts:远程终端)

4. w 查看用户详细登录信息

压缩解压命令

1. gzip 压缩文件

语法:gzip [文件]

压缩后文件格式:.gz

2. gunzip 解压缩.gz的压缩文件

语法:gunzip [压缩文件]

​ 例:gunzip test.gz

3. tar 打包目录

语法:tar [选项] [压缩后文件名] [目录]

​ -c 打包

​ -v 显示详细信息

​ -f 指定文件名

​ -z 打包同时压缩

压缩后文件格式:.tar.gz

tar命令解压缩语法:

​ -x 解包

​ -v 显示详细信息

​ -f 指定解压文件

​ -z 解压缩

​ 例:tar -zxvf test.tar.gz

4. zip 压缩文件或目录

语法:zip 选项[-r] [压缩后文件名] [文件或目录]

​ -r 压缩目录

压缩后文件格式:.zip

5. unzip 解压.zip的压缩文件

解压:unzip [压缩文件]

​ 例:unzip test.zip

6. bzip2 压缩文件

语法:bzip2 选项[-k] [文件]

​ -k 产生压缩文件后保留原文件

压缩后文件格式:.bz2

​ 例:bzip2 -k test

​ tar -cjf Test.tar.bz2 Test

7. bunzip2 解压缩

语法:bunzip2 选项[-k] [压缩文件]

​ -k 解压缩后保留原文件

​ 例:bunzip2 -k test.bz2

​ tar -xjf Test.tar.bz2

二、常用命令-网络命令

网络命令

1. write 给用户发信息,以Ctrl+D保存结束

语法:write <用户名>

​ 例:write king

2. wall 发广播信息

语法:wall [message]

​ 例:wall ni shi bu shi sha

3. ping 测试网络连通性

语法:ping 选项 IP地址

​ -c 指定发送次数

​ 例:ping 192.168.1.156

关机重启命令

1. shutdown 关机

语法:shutdown [选项] 时间

​ -c 取消前一个关机命令

​ -h 关机

​ -r 重启

​ 例:shutdown -h now 立即关机

2. 其它关机命令

  1. halt
  2. poweroff
  3. init 0

3. 其它重启命令

  1. reboot
  2. init 6

4. 系统运行级别init

  1. 关机
  2. 单用户
  3. 不完全多用户,不含NFS服务
  4. 完全多用户
  5. 未分配
  6. 图形界面
  7. 重启

5. logot 退出登录命令

三、文本编辑器Vim

Vim简介

Vim是一个功能强大的全屏幕文本编辑器,

是Linux/UNIX上最常用的文本编辑器,

它的作用是建立、编辑、显示文本文件

Vim没有菜单,只有命令。

命令作用
a在光标所在字符后插入
A在光标所在行尾插入
i在光标所在字符前插入
I在光标所在行行首插入
o在光标下插入新行
O在光标上插入新行
:set nu设置行号
:set nonu取消行号
gg到第一行
G到最后一行
nG到第n行
:n到第n行
$移至行尾
0移至行首
x删除光标所在处字符
nx删除光标所在处后n个字符
dd删除光标所在行,ndd删除n行
dG删除光标所在行到文件末尾内容
D删除光标所在处到行尾内容
:n1,n2d删除指定范围的行
/string搜索指定字符串 搜索时忽略大小写:set ic
n搜索指定字符串的下一个出现位置
:%s/old/new/g全文替换指定字符串
:n1,n2s/old/new/g在一定范围内替换指定字符串
:w保存修改
:w new_filename另存为指定文件
:wq保存修改并退出
ZZ快捷键,保存修改并退出
:q!不保存修改退出
:wq!保存修改并退出(文件所有者及root可使用)

使用技巧

导入名令执行结果:r !命令

定义快捷键:map 快捷键 触发命令

​ 例: :map ^p I#

​ :map ^B 0x

四、文本处理工具

1. grep工具

grep是行过滤工具;用于根据关键字进行过滤

语法和选项

语法:

# grep [选项] '关键字' 文件名

常见选项:

OPTIONS:
	-i:	不区分大小写
	-v:查找不包含指定内容的行,反向选择
	-w:按单词搜索
	-o:打印匹配到的次数
	-c:统计匹配到的次数
	-n:显示行号
	-r:逐层遍历目录查找
	-A:显示匹配行及后面多少行
	-B:显示匹配行及前面多少行
	-C:显示匹配行前后多少行
	-l:只列出匹配的文件名
	-L:列出不匹配的文件名
	-e:使用正则匹配
	-E:使用扩展正则匹配
	^key:以关键字开头
	key$:以关键字结尾
	^$:匹配空行
	--color=auto: 可以将找到的关键字部分加上颜色显示

2. cut工具

cut是列截取工具,用于列的截取

语法和选项

语法:

# cut [选项] 文件名

常见选项:

-c:		以字符为单位进行分割,截取
-d:		自定义分隔符,默认为制表符\t
-f:		与-d一起使用,指定截取哪个区域

举例说明:

# cut -d: -f1 1.txt			以:冒号分割,截取第一列内容
# cut -d: -f1,6,7 1.txt		以:冒号分割,截取第1,6,7列内容
# cut -c4 1.txt				截取文件中每行第4个字符
# cut -c1-4 1.txt			截取文件中每行的1-4个字符
# cut -c4-10 1.txt 			截取文件中每行的4-10个字符
# cut -c5-  1.txt			从第5个字符开始截取后面所有字符

课堂练习

用小工具列出你当前的系统运行级别

  1. 如何查看系统运行级别
    • 命令runlevel
    • 文件/etc/inittab
  2. 如何过滤运行级别
runlevel |cut -c3
runlevel |cut -d ' ' -f2
grep -v '^#' /etc/inittab | cut -d: -f2
grep '^id' inittab | cut -d: -f2
grep 'initdefault:$' /etc/inittab | cut -c4
grep -v ^# /etc/inittab |cut -c4
grep id: /etc/inittab | cut -d: -f2
cut -d':' -f2 /etc/inittab |grep -v ^#
cat /etc/inittab | grep -v '^#' | cut -d: -f2
cut -d: -f2 /etc/inittab |tail -i

3. sort工具

sort工具用于排序;它将文件的每一行作为一个单位,从首字符向后,依次按ASCII码

进行比较,最后将他们按升序输出。

语法和选项

-u	:	去除重复行
-r	:	降序排列,默认是升序
-o	:	将排序结果输出到文件中,类似重定向符号>
-n	:	以数字排序,默认是按字符排序
-t	:	分割符
-k	:	第N列
-b	:	忽略前导空格。
-R	:	随机排序,每次运行的结果均不同
举例说明
# sort -n -t: -k3 1.txt			按照用户的uid进行升序排列
# sort -nr -t: -k3 1.txt		按照用户的uid进行降序排列
# sort -n 2.txt					按照数字排序
# sort -nu 2.txt				按照数字排序并且去重
# sort -nr 2.txt		
# sort -nru 2.txt
# sort -n 2.txt -o 3.txt		按照数字排序并将结果重定向到文件
# sort -R 2.txt
# sort -u 2.txt

4. uniq工具

uniq用于去除连续的重复行

常见选项:

-i: 忽略大小写
-c: 统计重复行次数
-d: 只显示重复行


举例说明:
# uniq 2.txt
# uniq -d 2.txt
# uniq -dc 2.txt

五、 bash的特性

1. 命令和文件自动补全

Tab只能补全命令和文件 (RHEL6/Centos6)

2. 常见的快捷键

Ctrl+c				终止前台运行的程序
Ctrl+z				将前台运行的程序挂起到后台
Ctrl+d				退出 等价exit
Ctrl+l				清屏
Ctrl+a |home		光标移到命令行的最前端
Ctrl+e |end			光标移到命令行的后端
Ctrl+u				删除光标前所有字符
Ctrl+k				删除光标后所有字符
Ctrl+r				搜索历史命令

3. 常用的通配符 (重点)

*:	匹配0或多个任意字符
?:	匹配任意单个字符
[list]:	匹配[list]中的任意单个字符
[!list]:	匹配除list中的任意单个字符
{string1,string2,...}:	匹配string1,string2或更多字符串
{1..13}		

4. bash中的引号 (重点)

  • 双引号" " : 会把引号的内容当成整体来看待,允许通过$符号引用其它变量值
  • 单引号’ ’ : 会把引号的内容当成整体来看待,禁止引用其它变量值,shell中特殊符号都被视为普通字符
  • 反撇号`` : 反撇号和$()一样,引号或括号里的命令会优先执行,如果存在嵌套,反撇号不能用
# echo "$(hostname)"
  server
  
# echo '$(hostname)'
  $(hostname)
  
# echo "hello world"
  hello world
  
# echo 'hello world'
  hello world

SHELL编程模块

  • ① Shell的基本语法结构

    如:变量的定义、条件判断、循环语句(for、until、while)、分支语句、函数和数组等;

    ② 基本的正则表达式的运用;

    ③ 文件处理三剑客: grep、sed、awk工具的使用

    ④ 使用shell脚本完成一些复杂的任务,如:服务器搭建、批量处理等。

  • 目标

    • 熟练掌握shell变量的定义和获取(重点)
    • 能够进行shell简单的四则运算

六、 shell脚本

㈠简介

shell介于内核与用户之间,负责命令的解释

1. 什么是shell脚本?

​ 简单来说就是将需要执行的命令保存到文本中,按照顺序执行。

​ 它是解释型的,意味着不需要编译。

若干命令 + 脚本的基本格式 + 脚本的特定语法 + 思想 = shell脚本

2. 什么时候用到脚本?

重复化、复杂化的工作,通过把工作的命令写成脚本,

​ 以后仅仅需要执行脚本就能完成这些工作。

3. shell脚本能干啥?

自动化软件部署LAMP/LNMP/Tomcat
自动化管理系统初始化脚本,批量更改主机密码…
自动化分析处理统计网站访问量
自动化备份数据库备份,日志转储…

4. 如何学习shell脚本

  1. 尽可能记忆更多的命令
  2. 掌握脚本的标准格式(指定魔法字节、使用标准的执行方式运行脚本)
  3. 必须熟悉掌握脚本的基本语法(重点)

总结:

  • shell就是人机交互的一个桥梁
  • shell的种类
# cat /etc/shells
/bin/sh					#是bash的一个快捷方式
/bin/bash				#bash是大多数Linux默认的shell,包含的功能几乎可以涵盖shell所有的功能
/bin/nologin			#表示非交互,不能登录操作系统
/bin/dash				#小巧,高效,功能相比少一些

/bin/csh				#具有c语言风格的一种shell,具有许多特性,但也有一些缺陷
/bin/tcsh				#是csh的增强版,完全兼容csh

思考:终端和shell有什么关系?

打开终端默认打开一个shell,终端是一个程序,shell解析命令。

㈡shell脚本的基本写法

脚本第一行,魔法字符#!指定解释器【必写】

#!/bin/bash 表示以下内容使用bash解释器解析

注意:

如果直接将解释器路径写死在脚本里,可能在某些系统就会存在找不到解释器的兼容性问题,

所以可以使用:#!/bin/env 解释器

脚本的第二部分,注释(#号)说明,对脚本的基本信息进行描述【可选】

#!/bin/env bash
# 以下内容是对脚本的基本信息的描述
# Name: 名字
# Desc: 描述describe
# Path: 存放路径

脚本的第三部分,脚本要实现的具体代码内容

㈢脚本的执行方式

  • 标准脚本执行方法 (建议)

    # vim firsh_shell.sh			新建firsh_shell.sh文件
    
    
    # 编写脚本
    #!/bin/env bash
    #
    #
    #
    
    echo "hello world"
    
    
    # chmod +x firsh_shell.sh 		给脚本添加执行权限
    # /test/first_shell.sh			绝对路径执行
    #或 ./first_shell.sh			   相对路径执行(必须在文件目录内)
    
    hello world
    
  • 非标准的执行方法(不建议)

    1. 直接在命令行指定解释器执行

      # bash first_shell.sh
      
      -x: 一般用于排错,查看脚本的执行过程
      -n: 用来查看脚本的语法是否有问题
      
      
      # souce first_shell.sh
      

㈣ 编写简单的shell脚本

编写一个没有灵魂的脚本:

  1. 删除//tmp/目录下的所有文件 rm -rf /tmp/*
  2. 然后在/tmp目录里创建3个目录,分别是dir1-dir3 mkdir /tmp/dir{1…3}
  3. 拷贝/etc/hosts文件到刚创建的dir1目录里 cp /etc/hosts /tmp/dir1
  4. 最后打印“任务已于2020-09-16 时间完成”内容
#!/bin/env bash
# xxx
# xxx

rm -rf /tmp/*
mkdir /tmp/dir{1..3}
cp /etc/hosts /tmp/dir1
echo "任务已于$(date +'%F %T')完成"

七、变量的简单定义

1. 变量是什么?

变量是用来临时保存数据的,该数据是可以变化的数据。

2. 什么时候需要定义变量?

  • 如果某个内容需要多次使用,并且在代码中重复出现,那么可以用变量代表该内容。

    这样在修改内容的时候,仅仅需要改变变量的值。

  • 在代码运作的过程中,可能会把某些命令的执行结果保存起来,后续代码需要使用这些结果,

    就可以直接使用这个变量。

3. 变量如何定义?

变量名=变量值

变量名:用来临时保存数据的

变量值:就是临时的可变化的数据

# A=hello			定义变量
# echo $A			调用变量A
hello

4. 变量定义规则

  • 变量名区分大小写

    # A=hello
    # a=world
    # echo A
    hello
    # echo a
    world
    
  • 变量名不能有特殊符号

    # *A=hello
    -bash: command not found
    # ?A=hello
    -bash: command not found
    特别说明: 对于有空格色字符串给变量赋值时,要用引号引起来
    
  • 变量名不能以数字开头

    # 1A=hello
    -bash: command not found
    
  • 等号两边不能有任何空格

    # A = hello
    -bash: command not found
    # A =hello
    -bash: command not found
    # A= hello
    -bash: command not found
    
  • 变量尽量做到见名知意

    
    

5. 变量的定义方式有哪些

㈠ 基本方式

直接赋值给一个变量

# A=1234567
# echo $A
1234567
# echo ${A:2:4}		表示从A变量中第3个字符开始截取,截取4个字符
3456


说明:
$变量名 和 ${变量名}的异同
相同点:都可以调用变量

㈡ 命令行结果赋值给变量

# B=`date +%F`
# echo $B
2019-04-16

㈢ 交互式定义变量(read)

目的:让用户自己给变量赋值,比较灵活

语法read [选项] 变量名

常见选项

选项释意
-p定义用户的信息
-n定义字符数(限制变量的长度)
-s不显示(不显示用户输入的内容)
-t定义超时时间,默认单位为秒(限制用户输入变量的超时时间)

举例说明:

用法1:用户自己定义变量值

# read name
harry
# echo $name
harry

# read -p "Input your name:" name
Input your name:jack
# echo $name
jack

# read -s -p "Input your password:" pass


用法2:变量值来自文件

# read -p "请输入IP地址:" IP < ip.txt
# echo $ip
10.1.1.1

㈣ 定义有类型的变量(declare)

**目的:**给变量一些限制,比如整数、只读。

用法:declare 选项 变量名=变量值

常用选项:

选项释意举例
-i将变量看成整数declare -i A=123
-r定义只读变量declare -r B=hello
-a定义普通数组;查看普通数组
-A定义关联数组;查看关联数组
-x将变量通过环境到处declare -x AAA=123456等于export AAA=123456

6. 变量分类

㈠ 本地变量

  • 本地变量:当前用户自定义的变量。当前进程中有效,其他进程及当前进程的子进程无效。

㈡ 环境变量

  • 环境变量:当前进程有效,并且能够被子进程调用,
    • env查看当前用户的环境变量
    • set查询当前用户的所有变量(临时变量与环境变量)
    • export 变量名=变量值 或者 变量名=变量值;export 变量名
# export A=hello
# env|grep A
A=hello

㈢ 全局变量

  • 全局变量:全局所有的用户和程序都能调用,且继承,新建的用户也默认能调用

  • 解读相关配置文件

文件名说明备注
$HOME/.bashrc当前用户的bash信息,用户登录时读取定义别名、umask、函数等
$HOME/.bash_profile当前用户的环境变量,用户登录时读取
$HOME/.bash_logout当前用户退出当前shell时最后读取定义用户退出时执行的程序等
/etc/bashrc全局的bash信息,所有用户都生效
/etc/profile全局环境变量信息系统和所有用户都生效

说明:以上文件修改后,都需要重新source让其生效或者退出重新登录。

㈣ 系统变量【重要】

  • 系统变量(内置bash中变量):shell本身已经固定好了它的名字和作用。
内置变量含义
$?上一条命令执行后返回的状态;状态值为0表示执行正常,非0表示执行异常或错误
$0当前执行的程序或脚本名
$#脚本后面接的参数的个数
$*脚本后面所有参数,参数当成一个整体输出,每一个变量参数之间以空格隔开
$@脚本后面所有参数,参数是独立的,也是全部输出
$1-$9脚本后面的位置参数,$1表示第一个位置参数,依次类推
10 − {10}- 10{n}扩展位置参数,第10个位置变量必须用{}大括号括起来(2位数字以上括起来)
$$当前所在进程的进程号,如echo $$
$!后台运行的最后一个进程号(当前终端)
!$调用左后一条命令历史中的参数
  • 进一步了解位置参数 1   1~ 1 {n}
#!/bin/bash
#了解shell内置变量中的位置参数含义

echo "\$0 = $0"
echo "\$# = $#"
echo "\$* = $*"
echo "\$@ = $@"
echo "\$1 = $1"
echo "\$2 = $2"

八、简单四则运算

算数运算:默认情况下,shell就只能支持简单的整数运算

运算内容:加(+)、减(-)、乘(*)、除(/)、求余数(%)

1. 四则运算符号

表达式举例
$(( ))echo $((1+1))
$[ ]echo $[10-5]
exprexpr 10 / 5
letn=1;let n+=1 等价于 let n=n+1

2. 了解i++ 和 ++i

  • 对变量的值的影响
# i=1
# let i++
# echo $i
2
# j=1
# let ++j
# echo $j
2
  • 对表达式的值的影响
# i=1;j=1
# let x=i++			先赋值,再运算
# let y=++j			先运算,再赋值
# echo $i
2
# echo $j
2
# echo $x
1
# echo $y
2

九、条件判断

  • 熟悉条件判断语句,如判断整数、判断字符串等
  • 熟悉流程控制语句基本语法,如if…else…

1. 条件判断语法结构

㈠条件判断语法格式

  • 格式1:test条件表达式
  • 格式2:[ 条件表达式 ]
  • 格式3:[[ 条件表达式 ]] 支持正则 =-

特别说明:

1)[ 两边都有空格 ]

2)[[ 两边都有空格 ]]

3)更多判断,man test去查看,很多的参数都用来进行条件判断

㈡条件判断相关参数

问:你要判断什么?

答:我要判断文件类型,判断文件新旧,判断字符串是否相等,判断权限等等…

①判断文件类型
判断参数含义
-e判断文件是否存在(任何类型文件)
-f判断文件是否存在并且是一个普通文件
-d判断文件是否存在并且是一个目录
-L判断文件是否存在并且是一个软链接文件
-b判断文件是否存在并且是一个块设备文件
-S判断文件是否存在并且是一个套接字文件
-c判断文件是否存在并且是一个字符设备文件
-p判断文件是否存在并且是一个命名管道文件

举例说明:

test -e file					只要文件存在条件为真
[ -d /shell01/dir1 ]			判断目录是否存在,存在条件为真
[ ! -d /shell01/dir1 ]			判断目录是否存在,不存在条件为真
[[ -f /shell01/1.sh ]]			判断文件是否存在,并且是一个普通的文件
②判断文件权限
判断参数含义
-r当前用户对其是否可读
-w当前用户对其是否可写
-x当前用户对其是否可执行
-u是否有suid,高级权限冒险位
-g是否sgid,高级权限强制位
-k是否有t位,高级权限粘滞位
③判断文件新旧

说明:这里的新旧是指文件修改时间

判断参数含义
file1 -nt file2判断file1是否比file2新
file1 -ot file2判断file1是否比file2旧
file1 -ef file2比较是否为同一个文件,或者用于判断硬链接,是否指向同一个inode
④判断整数
判断参数含义
-eq相等
-ne不等
-gt大于
-lt小于
-ge大于等于
-le小于等于
⑤判断字符串
判断参数含义
-z判断是否为空字符串,字符串长度为0则成立
-n判断是否为非空字符串,字符串长度不为0则成立
string = string判断字符串是否相等
string != string判断字符串是否不相等
⑥多重条件判断
判断符号含义举例
-a 和 &&逻辑与[ 1 -eq 1 -a 1-ne 0 ] [ 1 -eq 1 ] && [ 1 -ne 0 ]
-o 和 ||逻辑或[ 1 -eq 1 -o 1 -ne 1 ] [ 1 -eq 1 ]

特别说明:

&& 前面的表达式为真,才会执行后面的代码

|| 前面的表达式为假,才会执行后面的代码

; 只用于分割命令或表达式

举例说明:

  • 数值比较
# [ $(id -u) -eq 0 ] && echo "the user is admin" || echo "the user is not admin"
  • 类C风格的数值比较
注意:在(( ))中,=表示赋值;==表示判断

# ((1==2));echo $?
# ((1<2));echo $?
# ((2>=1));echo $?
# ((2!=1));echo $?

2. 流程控制语句

关键词:选择

㈠基本语法结构

①if结构

F:表示false,为假

T:表示true,为真

if [ condition ];then
		command
		command
fi

[ 条件 ] && command
		
②if…else结构
 if [ condition ];then
 		command1
 	else
 		command2
 fi
 
 [ 条件 ] && command1 || command2

随堂练习

让用户自己输入字符串,如果用户输入的还hello,请打印world,否则打印“请输入hello”

  1. read定义变量
  2. if…else…
#!/bin/env bash


read -p '请输入一个字符串:' str
if [ "$str" = 'hello' ];then
	echo 'world'
else
	echo '请输入hello!'
fi
③if…elif…else结构
if [ condition1 ];then
		command1		结束
	elif [ condition2 ];then
		command2		结束
	else
		command3
fi

注释:
如果条件1满足,执行命令1后结束;如果条件1不满足,再看条件2,如果条件2满足执行命令2后结束;
如果条件1和条件2都不满足执行命令3结束。
④层层嵌套结构
if [ condition1 ];then
		command1
		if [ conditon2 ];then
			command2
		fi
	else
		if [ condition3 ];then
			command3
		elif [ condition4 ];then
			command4
		else
			command5
		fi
fi

㈡应用案例

①判断两台主机是否ping通

需求:判断当前主机是否和远程主机ping通

思路

  1. 使用哪个命令实现 ping -c次数

  2. 根据命令的执行结果状态来判断是否通 echo $?

  3. 根据逻辑和语法结构来编写脚本(条件判断或者流程控制)

落地实现

#!/bin/env bash
# 该脚本用于判断当前主机是否和远程指定主机互通

# 交互式定义变量,让用户自己决定ping哪个主机
read -p "请输入你要ping的主机的IP:" ip
# 使用ping程序判断主机是否互通
ping -c1 $ip &>/dev/null		扔掉屏幕上的结果输出
if [ $? -eq 0 ];then
	echo "当前主机和远程主机$ip是互通"
  else
  	echo "当前主机和远程主机$ip不通的"
fi

②判断一个进程是否存在

**需求:**判断web服务器中httpd进程是否存在

思路

  1. 查看进程的相关命令 ps pgrep
  2. 根据命令的返回状态值来判断进程是否存在
  3. 根据逻辑用脚本语言实现

落地实现

#!/bin/env bash
# 判断一个程序(httpd)的进程是否存在

pgrep httpd &>/dev/null
if [ $? -ne 0 ];then
	echo "当前httpd进程不存在"
  else
  	echo "当前httpd进程存在"
fi
③判断一个服务是否正常

**需求:**判断门户网站是否能够正常访问

思路

  1. 可以判断进程是否存在,用/etc/init.d/httpd status判断状态等方法
  2. 最好的方法是直接访问一下,通过访问成功和失败的返回值来判断
    • Linux环境,wget,curl ,elinks -dump

落地实现

#!/bin/env bash
# 判断门户网站是否能够正常提供服务

# 定义变量
web_server=www.itcast.cn
wget $web_server &>/dev/null
[ $? -eq 0 ] && echo "当前网站服务是ok" || echo "当前网站服务不ok,请立即处理"

㈢课堂练习

①判断用户是否存在

**需求1:**输入一个用户,用脚本判断该用户是否存在

#!/bin/env bash

read -p "请输入一个用户:" name

id $name &>/dev/null

if [ $? -eq 0 ];then
	echo "该用户存在"
  else
  	echo "该用户不存在"
fi
	

十、for循环语句

1. for循环语法结构

㈠列表循环

列表for循环:用于将一组命令执行已知的次数

  • 基本语法格式
for variable in {list}
	do
		command
		command
		...
	done
或者
for variable in a b c
	do
		command
		command
	done
  • 举例说明
# for var in {1..10};do echo $var;done
# for var in a b c;do echo $var;done
# for var in {10..1};do echo $var;done

㈡不带列表循环

不带列表的for循环执行时由用户指定参数和参数的个数

  • 基本语法格式
for variable
	do
		command
		command
		...
	done
  • 举例说明
#!/bin/bash

for var 
	do
		echo "hello"
	done
	
./tesh.sh a b c

㈢类C风格的for循环

  • 基本语法结构
for (( expr1;expr2;expr3 ))
	do
		command
		command
		...
	done
	
for (( i=1;i<=5;i++ ))
	do
		echo $i
	done
	
expr1: 定义变量并赋初值
expr2: 决定是否进行循环(条件)
expe3: 决定循环变量如何改变,决定循环什么时候退出

2. 应用案例

㈠脚本计算1-100奇数和

①思路

  1. 定义一个变量来保存奇数的和
  2. 找出1-100的奇数,保存到另一个变量里
  3. 从1-100中找出奇数后,再相加,然后将和赋值给变量
  4. 遍历完毕后,将sum的值打印出来

②落地实现

#!/bin/env bash
# 计算1-100的奇数和
# 定义变量来保存奇数和

sum=0

# for循环遍历1-100的奇数,并且相加,把结果重新赋值给sum

for i in {1..100..2}
	do
		let sum=$sum+$i	
	done

# 打印所有奇数和
echo "1-100的奇数和是:$sum"


方法2:
#!/bin/bash
sum=0
for ((i=1;i<=100;i+=2))
do
	let sum=$i+$sum
done
echo "1-100的奇数和是:$sum"

方法3:
#!/bin/bash
sum=0
for ((i=1;i<=100;i++))
do
	if [ $[$i%2] -ne 0 ];then
		let sum=$sum+$i
	fi
或者
test $[$i%2] -ne 0 && let sum=$sum+$i
done
echo "1-100的奇数和是:$sum"

方法4:
sum=0
for ((i=1;i<=100;i++))
do
	if [ $[$i%2] -eq 0 ];then
		continue
	else
		let sum=$sum+$i
	fi
done
echo "1-100的奇数和是:$sum"

#!/bin/bash
for ((i=1;i<=100;i++))
do
	test $[$i%2] -eq 0 && continue || let sum=sum+$i
done
echo "1-100的奇数和是:$sum"

③循环控制语句

循环体:do...done之间的内容

  • continue:继续;表示循环体内下面的代码不执行,重新开始下一次循环
  • break:打断;马上停止执行本次循环,执行循环体后面的代码
  • exit:表示直接跳出程序
#!/bin/bash
for i in {1..5}
do
	test $i -eq 2 && break || touch /tmp/file$i
done
echo hello world

㈡判断所输整数是否为质数

**质数(素数):**只能被1和它本身整除的数叫质数。

2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

①思路

  1. 让用户输入一个数,保存到一个变量里
  2. 如果能被其它整其它数整除就不是质数——> n u m num% numi是否等于0 i = 2 到 i=2到 i=2num-1
  3. 如果输入的数是1或者2取模根据上面判断又不符合,所以排除1和2
  4. 测试序列从2开始,输入的数是4——>得出结果 n u m 不 能 和 num不能和 numi相等,并且 n u m 不 能 小 于 num不能小于 numi

②落地实现

#!/bin/bash
read -p "请输入一个正整数:" number

[ $number -eq 1 ] && echo "$number不是质数" && exit
[ $number -eq 2 ] && echo "$number是质数" && exit

for i in `seq 2 $[$number-1]`
	do
	[ $[$number%$1] -eq 0 ] && echo "$number不是质数" && exit
	done
echo "$number是质数" && exit

㈢批量创建用户

需求:批量加5个新用户,从u1到u5命名,并统一加一个新组,组名为class,统一改密码为123

①思路

  1. 添加用户的命令
  2. 判断class组是否存在
  3. 根据题意,判断该脚本循环5次来添加用户
  4. 给用户设置密码,应该放到循环体里面

②落地实现

#!/bin/env bash
# 判断class组是否存在

grep -w ^class /etc/group &>/dev/null
test $? -ne 0 && groupadd class

# 循环创建用户
for ((i=i;i<=5;i++))
do
	useradd -G class u$i
	echo 123|passwd --stdin u$i
done

3. 课堂练习

㈠批量创建用户

**需求1:**批量新建5个用户stu1-stu5,要求这几个用户的家目录都在/rhome.

#!/bin/bash
# 判断/rhome是否存在

[ -f /rhome ] && mv /rhome /rhome.bak
test ! -f /rhome -a ! -d /rhome && mkdir /rhome
或者
[ -f /rhome ] && mv /rhome /rhome.bak || [ ! -d /rhome ] && mkdir /rhome
# 创建用户,循环5次
for ((i=1;i<=5;i++))
do
	useradd -d /rhome/stu$i stu$i
	echo 123|passwd --stdin stu$i
done

㈡局域网内脚本检查主机网络通讯

需求2:写一个脚本,局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里。

#!/bin/bash

# 定义变量
ip=192.168.183
# 循环去ping主机的IP
for ((i=1;i<=200;i++))
do
	ping -c1 $ip.$i &>/dev/null
	if [ $? -eq 0 ];then
		echo "$ip.$i is ok" >> /tmp/ip_up.txt
	else
		echo "$ip.$i is down" >> /tmp/ip_down.txt
	fi
done

{}& wait  并发执行

#!/bin/bash

# 定义变量
ip=192.168.183
# 循环去ping主机的IP
for ((i=1;i<=200;i++))
do
{
	ping -c1 $ip.$i &>/dev/null
	if [ $? -eq 0 ];then
		echo "$ip.$i is ok" >> /tmp/ip_up.txt
	else
		echo "$ip.$i is down" >> /tmp/ip_down.txt
	fi
}&	
done
wait
echo "ip is ok..."

# time ./ping.sh
ip is ok...

real	3.091s

十一、while循环语句

**特点:**条件为真就进入循环;条件为假就退出循环

1. while循环语法结构

while 表达式
	do
		command...
	done
	
	
while [ 1 -eq 1 ] 或者 (( 1 > 2 ))
	do
		command
		command
		...
	done

2. 应用案例

㈠脚本计算1-50偶数和

#!/bin/env bash
sum=0
for ((i=0;i<=50;i+=2))
do
	let sum=$sum+$i
done
echo "1-50的偶数和为:$sum"


#!/bin/bash
# 定义变量
sum=0
i=2
# 循环打印1-50的偶数和并且计算后重新赋值给sum
while [ $i -le 50 ]
do
	let sum=$sum+$i
	let i+=2
done
# 打印sum的值
echo "1-50的偶数和为:$sum"

㈡脚本同步系统时间

①具体需求

  1. 写一个脚本,30秒同步一次系统时间,时间同步服务器192.168.88.253
  2. 如果同步失败,则进行邮件报警,每次失败都报警
  3. 如果同步成功,也进行邮件通知,但是成功100次才通知

②思路

  1. 每个30s同步一次时间,该脚本是一个死循环 while
    1. 同步失败发送邮件
  2. 同步成功100次发送邮件

③落地实现

#!/bin/env bash
# 该脚本用于时间同步
NTP=192.168.88.253
count=0
while true
do
	ntpdate $NTP &>/dev/null
	if [ $? -ne 0 ];then
		echo "system date failed" |mail -s "check system date" root@localhost
	else
		let count++
		if [ $count -eq 100 ];then
			echo "system date success" |mail -s "check sysytem date" root@localhost && count=0
		fi
	fi
sleep 30
done

十二、until循环

**特点:**条件为假就进入循环;条件为真就退出循环

1. until语法结构

until expression     [ 1 -eq 1 ] ((1>=1))
	do
		command
		command
		...
	done

打印1-5数字

i=1
while [ $i -le 5 ]
do
	echo $i
done

2. 应用案例

㈠具体需求

  1. 使用until语句批量创建10个用户,要求stu1-stu5用户的UID分别为1001—1005;
  2. stu6-stu10用户的家目录分别在/rhome/stu6—/rhome/stu10

㈡思路

  1. 创建用户语句 useradd -u |useradd -d
  2. 使用循环语句(until)批量创建用户 until循环语句结构
  3. 判断用户前5个和后5个

㈢落地实现

#!/bin/env bash
#

if [ -d /rhome ];then
	echo "/rhome目录已存在"
else
	mkdir /rhome
	echo "/rhome不存在,已完成创建"
fi

i=1
until [ $i -gt 10 ]
do
	if [ $i -le 5 ];then
		useradd -u $[1000+$i] stu$i && echo 123 |passwd --stdin stu$i
	else
		[ ! -d /rhome ] && mkdir /rhome
		useradd -d /rhome/stu$i stu$i && echo 123|passwd --stdin stu$i
	fi
	let i++
done

十三、随机数

1. 如何生成随机数?

系统变量: RANDOM,默认会产生0—32767的随机整数

**前言:**要想调用变量,不管你是什么变量都要给钱,而且是美元$

打印一个随机数
echo $RANDOM
查看系统上一次生成的随机数
# set|grep RANDOM
RANDOM=28325

产生0~1之间的随机数
echo $[ $RANDOM%2 ]

产生0~2之间的随机数
echo $[ $RANDOM%3 ]

产生0~3之间的随机数
echo $[ $RANDOM%4 ]

。。。。
产生0~9内的随机数
echo $[ $RANDOM%10 ]

产生0~100内的随机数
echo $[ $RANDOM%101 ]

产生50~100之内的随机数
echo $[ $RANDOM%51+50 ]

产生三位数的随机数
echo $[$RANDOM%900+100]

2. 实战案例

㈠随机产生以139开头的电话号码

具体需求1:

写一个脚本,产生一个phonenum.txt,随机产生以139开头的手机号100个,每个一行。

①思路

  1. 产生1000个电话号码,脚本需要循环1000次
  2. 139+8位,后8位随机产生,可以让每一位数字都随机产生
  3. 将随机产生的数字分别保存在变量里,然后加上139保存到文件里

②落地实现

#!/bin/bash
# random random
# 产生1000个以139开头的电话号码并保存文件phonenum.txt

file=./phonenum.txt
for ((i=1;i<=1000;i++))
do
	n1=$[$RANDOM%10]
	n2=$[$RANDOM%10]
	n3=$[$RANDOM%10]
	n4=$[$RANDOM%10]
	n5=$[$RANDOM%10]
	n6=$[$RANDOM%10]
	n7=$[$RANDOM%10]
	n8=$[$RANDOM%10]
	echo "139$n1$n2$n3$n4$n5$n6$n7$n8" >> $file
done

㈡随机抽取5位幸运观众

具体需求

  1. 在上面的1000个手机里抽奖5个幸运观众,显示出5个幸运观众
  2. 但只显示头3个数和尾号的4个数,中间的都用*代替

①思路

  1. 确定幸运观众所在的行 0-1000 随机找出一个数字 $[$RANDOM%1000+1]
  2. 将电话号码提取出来 head -随机产生行号 phonenum.txt |tail -l
  3. 显示前3个和后4个数到屏幕 echo 139****

②落地实现

#!/bin/bash
# 定义变量
phone=./phonenum.txt
# 循环抽出5位幸运观众
for ((i=1;i<=5;i++))
do
	# 定位幸运观众所在行号
	line=`wc -l $phone |cut -d' ' -f1`
	luck_line=$[RANDOM%$line+1]
	#取出幸运观众所在行的电话号码
	luck_num=`head -$luck_line $phone|tail -1`
	#显示到屏幕
	echo "139****${luck_num:7:4}"
	echo $luck_num >> luck.txt
	#删除已经被抽取的幸运观众号码
	sed -i "/$lick_num/d" $phone
done

㈢批量创建用户(密码随机产生)

**需求:**批量创建5个用户,每个用户的密码为一个随机数

①思路

  1. 循环5次创建用户
  2. 产生一个密码文件来保存用户的随机密码
  3. 从密码文件中取出随机密码赋值给用户

②落地实现

#!/bin/bash
#产生一个保存用户名和密码的文件
echo user0{1..5}:itcast$[$RANDOM%9000+1000]#@~|tr ' ' '\n'>> user_pass.file

#循环创建5个用户
for ((i=1;i<=5;i++))
do
	user=`head -$i user_pass.file|tail -1|cut -d: -f1`
	pass=`head -$i user_pass.file|tail -1|cut -d: -f2`
	echo $pass|passwd --stdin $user
done

十四、嵌套循环

  1. 一个循环体内又包含另一个完整的循环结构,称为循环的嵌套
  2. 每次外部循环都会触发内部循环,直至内部循环完成,才接着执行下一次外部循环
  3. for循环、while循环和until循环可以相互嵌套。

1. 应用案例

㈠打印指定图案

1
12
123
1234
12345
#!/bin/env bash
for ((y=1;y<=5;y++))
do
	for ((x=1;x=$y;x++))
	do
		echo -n $x
	done
done


#!/bin/env bash
for ((y=1;y<=5;y++))
do
	x=1
	while (($x<=$y))
	do
		echo -n $x
		let x++
	done
	
	echo
done


#!/bin/env bash
y=1
while (( $y<=5 ))
do
	for ((x=1;x<=6;x++))
	do
		echo -n $x
	done
	echo
	let y++
done



补充总结

1. 影响shell程序的内置命令

exit			退出整个程序
break			结束当前循环,或跳出本层循环
continue		忽略本次循环剩余的代码,直接进入下一次循环
shift			使位置参数向左移动,默认移动一位,可以使用shift 2


2. 补充扩展expect (跳过,待定)

expect 自动应答 tcl语言

需求1:A远程登录到server上什么都不做

#!/user/bin/expect

十五、数组

1. 数组定义

㈠ 数组分类

  • 普通数组:只能使用整数作为数组索引(元素的下标)
  • 关联数组:可以使用字符串作为数组索引(元素的下标)

㈡ 普通数组定义

  • 一次赋予一个值
数组名[索引下标]=值
array[0]=v1
array[1]=v2
array[3]=v3
  • 一次赋予多个值
数组名=(值1 值2 值3 ...)
array=(var1 var2 var3 var4)


array1=(`cat /etc/passwd`)			将文件中每一行赋值给array1数组
array2=(`ls /root`)
array3=(harry amy jack "Miss Hou")
array4=(1 2 3 4 "hello world" [10]=linux)

㈢ 数组的获取

${数组名[元素下标]}

echo ${array[0]}			获取数组里第一个元素
echo ${array[*]}			获取数组里所有元素
echo ${#array[*]}			获取数组里所有元素个数
echo ${!array[@]}			获取数组元素的索引下标
echo ${array[@]:1:2}		访问指定的元素;1代表从下标为1的元素开始获取;2代表获取后面几个元素

查看普通数组信息
# declare -a

㈣ 关联数组定义

① 首先声明关联数组

declare -A asso_array1
declare -A asso_array2
declare -A asso_array3

② 数组赋值

  • 一次赋一个值
数组名[索引or下标]=变量值
# asso_array1[linux]=one
# asso_array2[java]=two
# asso_array3[php]=three
  • 一次赋多个值
# asso_array2=([name1]=one [name2]=two [name3]=three)
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值