linux
一、常用命令-文件处理命令
命令格式: 命令 [-选项] [参数]
例: ls -la /etc
说明:
- 个别命令使用不遵循此格式
- 当有多个选项时,可以写在一起
- 简化选项与完整选项
目录处理命令
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– |
---|---|---|
u | g | o |
u代表所有者 | g代表所属组 | o代表其他人 |
r | w | x |
---|---|---|
读权限 | 写权限 | 执行权限 |
可以查看文件内容 | 可以修改文件内容 | 可以执行文件 |
数字表示: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. 其它关机命令
- halt
- poweroff
- init 0
3. 其它重启命令
- reboot
- init 6
4. 系统运行级别init
- 关机
- 单用户
- 不完全多用户,不含NFS服务
- 完全多用户
- 未分配
- 图形界面
- 重启
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个字符开始截取后面所有字符
课堂练习
用小工具列出你当前的系统运行级别
- 如何查看系统运行级别
- 命令runlevel
- 文件/etc/inittab
- 如何过滤运行级别
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脚本
- 尽可能记忆更多的命令
- 掌握脚本的标准格式(指定魔法字节、使用标准的执行方式运行脚本)
- 必须熟悉掌握脚本的基本语法(重点)
总结:
- 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
-
非标准的执行方法(不建议)
-
直接在命令行指定解释器执行
# bash first_shell.sh -x: 一般用于排错,查看脚本的执行过程 -n: 用来查看脚本的语法是否有问题 # souce first_shell.sh
-
㈣ 编写简单的shell脚本
编写一个没有灵魂的脚本:
- 删除//tmp/目录下的所有文件 rm -rf /tmp/*
- 然后在/tmp目录里创建3个目录,分别是dir1-dir3 mkdir /tmp/dir{1…3}
- 拷贝/etc/hosts文件到刚创建的dir1目录里 cp /etc/hosts /tmp/dir1
- 最后打印“任务已于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] |
expr | expr 10 / 5 |
let | n=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”
- read定义变量
- 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通
思路
-
使用哪个命令实现
ping -c次数
-
根据命令的执行结果状态来判断是否通
echo $?
-
根据逻辑和语法结构来编写脚本(条件判断或者流程控制)
落地实现
#!/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进程是否存在
思路
- 查看进程的相关命令 ps pgrep
- 根据命令的返回状态值来判断进程是否存在
- 根据逻辑用脚本语言实现
落地实现
#!/bin/env bash
# 判断一个程序(httpd)的进程是否存在
pgrep httpd &>/dev/null
if [ $? -ne 0 ];then
echo "当前httpd进程不存在"
else
echo "当前httpd进程存在"
fi
③判断一个服务是否正常
**需求:**判断门户网站是否能够正常访问
思路
- 可以判断进程是否存在,用/etc/init.d/httpd status判断状态等方法
- 最好的方法是直接访问一下,通过访问成功和失败的返回值来判断
- 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-100的奇数,保存到另一个变量里
- 从1-100中找出奇数后,再相加,然后将和赋值给变量
- 遍历完毕后,将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
①思路
- 让用户输入一个数,保存到一个变量里
- 如果能被其它整其它数整除就不是质数——> n u m num% numi是否等于0 i = 2 到 i=2到 i=2到num-1
- 如果输入的数是1或者2取模根据上面判断又不符合,所以排除1和2
- 测试序列从2开始,输入的数是4——>得出结果 n u m 不 能 和 num不能和 num不能和i相等,并且 n u m 不 能 小 于 num不能小于 num不能小于i
②落地实现
#!/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
①思路
- 添加用户的命令
- 判断class组是否存在
- 根据题意,判断该脚本循环5次来添加用户
- 给用户设置密码,应该放到循环体里面
②落地实现
#!/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"
㈡脚本同步系统时间
①具体需求
- 写一个脚本,30秒同步一次系统时间,时间同步服务器192.168.88.253
- 如果同步失败,则进行邮件报警,每次失败都报警
- 如果同步成功,也进行邮件通知,但是
成功100次
才通知
②思路
- 每个30s同步一次时间,该脚本是一个死循环 while
- 同步失败发送邮件
- 同步成功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. 应用案例
㈠具体需求
- 使用until语句批量创建10个用户,要求stu1-stu5用户的UID分别为1001—1005;
- stu6-stu10用户的家目录分别在/rhome/stu6—/rhome/stu10
㈡思路
- 创建用户语句
useradd -u |useradd -d
- 使用循环语句(until)批量创建用户
until循环语句结构
- 判断用户前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个,每个一行。
①思路
- 产生1000个电话号码,脚本需要循环1000次
- 139+8位,后8位随机产生,可以让每一位数字都随机产生
- 将随机产生的数字分别保存在变量里,然后加上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位幸运观众
具体需求
- 在上面的1000个手机里抽奖5个幸运观众,显示出5个幸运观众
- 但只显示头3个数和尾号的4个数,中间的都用*代替
①思路
- 确定幸运观众所在的行
0-1000 随机找出一个数字 $[$RANDOM%1000+1]
- 将电话号码提取出来
head -随机产生行号 phonenum.txt |tail -l
- 显示前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个用户,每个用户的密码为一个随机数
①思路
- 循环5次创建用户
- 产生一个密码文件来保存用户的随机密码
- 从密码文件中取出随机密码赋值给用户
②落地实现
#!/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
十四、嵌套循环
- 一个循环体内又包含另一个完整的循环结构,称为循环的嵌套
- 每次外部循环都会触发内部循环,直至内部循环完成,才接着执行下一次外部循环
- 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)