1 linux的用户与用户组
1.1 概述
Linux是一个真实的、完整的多用户多任务操作系统,多用户多任务就是可以在系统上建立多个用户,而多个用户可以在同一时间内登录同一个系统执行各自不同的任务,而互不影响。为了让系统更加安全,可以针对文件数据设置不同用户具有不同的权限,每个用户是在权限允许的范围内完成不同的任务,linux正是通过这种权限的划分与管理,实现了多用户多任务的运行机制。
用户组是具有相同特征用户的逻辑集合,有时我们需要让多个用户具有相同的权限。比如查看、修改某一个文件的权限,一种方法是分别对多个用户进行文件访问授权,如果有10个用户的话,就需要授权10次,显然这种方法不太合理.另一种方法是建立一个组,让这个组具有查看、修改此文件的权限,然后将所有需要访问此文件的用户放入这个组中,那么所有用户就具有了和组一样的权限。这就是用户组
说白了用户组就是对linux中同一类对象进行统一管理一种技术手段,将同一类用户放到一个组中去,封装成一个更大的整体;
就好比 同一类学生封装到一个班级里面,学生就是用户,班级就是组;对班级进行操作其实就是对这个班级的所有学生的操作;
1.2 用户与组的关系
用户和用户组的对应关系有:一对一、一对多、多对一和多对多;下图展示了这种关系:
一对一:即一个用户可以存在一个组中,也可以是组中的唯一成员。
一对多:即一个用户可以存在多个用户组中。那么此用户具有多个组的共同权限。
多对一:多个用户可以存在一个组中,这些用户具有和组相同的权限。
1.3 User, Group 及 Others
根据上面讲的用户与用户组的关系,可以将权限分为三种:
1)所有者权限(User)
2)所有者同组权限(Group)
3)所有者非同组权限(others)
下面举例说明:
其中:
天神:root 用户,无所不能。
王大毛家:某个用户组
王大毛:某个用户组中的用户
王大毛房间的所有者是王大毛,里面的东西,其他人不能乱动,表示为所有者权限 (User)。
王大毛家内公共区域三兄弟可以共享,表示为所有者同组权限(Group)。
对于王大毛来说,张小猪就不是他们家的人,表示为所有者非同组权限(others)。
1.4 linux的用户管理
创建一个用户的时候,默认情况下,会为其创建一个同名的用户组
执行 :
[root@localhost ~]# cat /etc/passwd
是的,没有错,不要怀疑,这个就是查看用户信息的文件 叫 passwd
内容如下
内容说明 :
/etc/passwd中一行记录对应着一个用户,每行记录又被冒号(:)分隔为7个字段,其格式和具体含义如下:
用户名:口令:用户标识号:组标识号:注释性描述:主目录:登录Shell
用户名:
是代表用户账号的字符串。通常长度不超过8个字符,并且由大小写字母和/或数字组成。
口令:
一些系统中,存放着加密后的用户口令字。虽然这个字段存放的只是用户口令的加密串,不是明文,但是由于/etc/passwd文件对所有用户都可读,所以这仍是一个安全隐患。因此,现在许多Linux系统都使用了shadow技术,把真正的加密后的用户口令字存放到/etc/shadow文件中,而在/etc/passwd文件的口令字段中只存放一个特殊的字符,例如“x”或者“*”。
用户标识号:UID
用户标识号(User ID),是一个整数,系统内部用它来标识用户。
0是系统管理员账号,1-999是系统保留账号,1000+即一般账号。useradd 命名默认生成UID=1000。
组标识号:GID
GID:用户组标识号(Group ID),是一个整数,系统内部用它来标识用户组。
注释性描述:
字段记录着用户的一些个人情况,例如用户的真实姓名、电话、地址等,这个字段并没有什么实际的用途。
主目录:
也就是用户的起始工作目录,它是用户在登录到系统之后所处的目录。在大多数系统中,各用户的主目录都被组织在同一个特定的目录下,而用户主目录的名称就是该用户的登录名。各用户对自己的主目录有读、写、执行(搜索)权限,其他用户对此目录的访问权限则根据具体情况设置。
登录Shell:
用户登录后,要启动一个进程,负责将用户的操作传给内核,这个进程是用户登录到系统后运行的命令解释器或某个特定的程序,即Shell。Shell是用户与Linux系统之间的接口。
1.4.1 创建用户:
语法:useradd [选项] {UserName}
选项:
-c | 指定一段注释性描述 |
---|---|
-d 目录 | 指定用户主目录,如果目录不存在,则同时使用-m选项,可以创建主目录。 |
-g 用户组 | 指定用户所属的主用户组。 |
-G 用户组,用户组 | 指定用户所属的附加组。 |
-s Shell程序 | 指定用户的登录Shell。有一个特殊的shell程序叫nologin,如果某帐号使用此shell,就表示用户不允许登录,该用户通常成为伪用户。 |
-u 用户ID | 指定用户的用户号 |
#添加用户tom
useradd tom
#添加用户jerry并指定家目录为/hainiu/jerry 主组为root,附加组为tom和adm
useradd -d /hainiu/jerry -g root -G tom,adm jerry
#添加用户test1指定shell程序为/bin/sh 用户id为80000
useradd -s /bin/sh -u 80000 test1
#添加用户test2 指定shell程序为/sbin/nologin
useradd -s /sbin/nologin test2
1.4.2 修改用户
语法:usermod [选项] {UserName}
选项:
-c | 指定一段注释性描述 |
---|---|
-d | 目录 指定用户主目录,如果目录不存在,则同时使用-m选项,可以创建主目录。 |
-g 用户组 | 指定用户所属的用户组。 |
-G 用户组,用户组 | 指定用户所属的附加组。如果想要在原有的基础上追加附加组,使用-aG的方式。 |
-s Shell文件 | 指定用户的登录Shell。有一个特殊的shell程序叫nologin,如果某帐号使用此shell,就表示用户不允许登录,该用户通常成为伪用户。 |
-u 用户号 | 指定用户的用户号 |
#修改test1的uid为9000
usermod -u 9000 test1
#修改jerry的附加组为test,和test1
usermod -G test,test1 jerry
#给jerry追加附加组
usermod -aG root,adm jerry
#修改test2的shell程序为/bin/bash
usermod -s /bin/bash test2
1.4.3 删除用户
语法:userdel [选项] {UserName}
选项:
-r | 删除账户的同时删除该账户的家目录 |
---|---|
1.4.4 密码管理
passwd 可以不跟选项、用户名,默认是修改自己的帐号密码。
修改他人密码,必须具备管理员权限(并不一定非要是root账户)
普通账户,只能修改自己的密码。
管理员修改他人的密码,不需要满足密码策略。
普通账户修改密码时,必须满足密码安全策略。
语法:passwd [选项] {UserName}
选项:
-l | 锁定账户 |
---|---|
-u | 解锁账户 |
-d | 删除密码 |
管理员修改他人密码:
passwd {UserName}
修改自己的密码
passwd
案例:
#锁定zhangsan账户
passwd -l zhangsan
#解锁zhangsan账户
passwd -u zhangsan
#删除zhangsan账户密码
passwd -d zhangsan
案例中,锁定账户和删除账户密码都是可以达到不允许账户远程登录的效果。
1.4.5 用户身份切换
su {UserName} | 表示切换用户之后,依然停留在当前目录 不切换环境变量 |
---|---|
su - {UserName} | 表示切换用户之后,去到该用户的家目录 并切换环境变量 |
2 linux用户组操作
因为用户组与用户是一对多的关系,用户肯定是要从属于某个组的,所以我们先从用户组操作起来
2.1 查询用户组
2.1.1 用户组信息的查询
执行 :
#cat 命令,查看某个文件的内容 /etc(配置文件目录)/group(配置文件)
[root@localhost ~]# cat /etc/group
用户组的所有信息都存放在/etc/group文件中。
此文件的格式是由冒号(:)隔开若干个字段,这些字段具体如下:
组名:口令:组标识号:组内用户列表
具体解释:
组名:
组名是用户组的名称,由字母或数字构成。与/etc/passwd中的登录名一样,组名不应重复。
口令:
口令字段存放的是用户组加密后的口令字。一般Linux系统的用户组都没有口令,即这个字段一般为空,或者是*,有口令默认是x。
因为涉及到对组的管理所以linux的组也是有自己的密码的
组标识号 主键ID(可以重复的):
组标识号与用户标识号类似,也是一个整数,被系统内部用来标识组。别称GID.
组内用户列表:
是属于这个组的所有用户的列表,不同用户之间用逗号(,)分隔。这个用户组可能是用户的主组,也可能是附加组。
2.2 添加、删除用户组
# 添加用户组
groupadd group1
groupadd group2
# 查看用户组文件,能看到这两个组
cat /etc/group
# 删除用户组
groupdel group1
# 注意:删除用户组时,用户组必须存在,如果有组中的任一用户在使用中的话,则不能删除。
# 查看用户组文件,只能看到group2
cat /etc/group
3 权限 权限
在Linux系统对于权限的设定非常的敏感,如果某个用户执行一个操作时,提示权限不足,那么根据Linux系统的权限设定的思想(没有权限绝对不会睁一只眼闭一只眼),就能够判断出该用户不具备此文件的执行权限。
在Linux系统中,有以下的权限表示。业内人士称之为:
逻辑权限
物理权限
普通用户的root的权限。
逻辑权限:
在Linux系统中不管是文件还是目录。(在Linux系统中,将所有的东西都视为文件。)都有固定权限表示。
例:
drwxr-xr-x. 2 root root 4096 5月 13 15:27 home
-rw-r--r--. 1 root root 45537 5月 13 11:15 install.log
两个文件分别是:第一个是目录,第二个是普通文件
根据信息的第一个字母**(文件类型)**来查看,d表示该文件是一个目录文件,-表示该文件是一个普通文件。
后面每三个权限成为一组,每组中分别有三个权限:
字符 | 权限 | 数字 |
---|---|---|
r | 读 | 4 |
w | 写 | 2 |
x | 执行 | 1 |
除了第一个字母不参与权限的表示,其他的都为权限标识符。
每三个为一组,共有三组:
第一组 | 用户 | user |
---|---|---|
第二组 | 用户组 | group |
第三组 | 其他人 | other |
说明:Linux系统中,不管是什么系统,权限的标识符号的位置是不会发生任何的改变,也就是说,
第1个永远是文件类型,
第2-4(第一组)永远是读、写、执行,用户的权限,
第5-7(第二组)永远是读、写、执行,用户组的权限,
第8-10(第三组)永远是读、写、执行,其他人的权限。
如果某个文件权限标识为----------,那么则说明此文件不允许任何的读取、写入、执行
修改文件/夹的权限:
chmod命令可以用来修改某个文件或文件夹的权限。
选项
-R | 递归处理 |
---|---|
修改文件**/**夹的权限时,可以使用字符权限,也可以使用数字权限。
案例:
touch test_1 # 当前文件的权限是-rw-r--r--
将此文件的权限修改为----------
chmod 000 test_1
为此文件,每组都增加一个读的权限
chmod 444 test_1
or
chmod +r test_1
# a=all,u=user,g=group,o=other
为此文件的用户增加一个rw-,组增加一个r-x,其他人---。
chmod u+rw,g+rx test_1
or
chmod 650 test_1
0表示没有权限
chmod在修改文件权限的时候,哪个便捷用哪个方法。
比如:
如果要是给三组增加执行权限的时候,+x就数字计算要快。字符权限就比数字要便捷(不需要计算)
如果是为每组增加不同权限的时候,用数字比较便捷(书写便捷)。
物理权限:
修饰某个文件/夹不允许被修改。注意:不能给/ /tmp /dev /var 加保护
即便是root权限也不一定所有的文件都可以删
chattr [选项] file/dir
选项:
i | 表示不能以任何方式进行文件/夹的修改,增加,删除 |
---|---|
a | 表示文件/夹只能追加,不能修改,删除 |
+ <属性> | 表示开启某文件/夹的权限 |
- <属性> | 表示关闭某文件/夹的权限 |
R | 表示递归处理。 |
案例:
touch big1902
chattr +i big1902 # 表示该文件不允许修改,删除,增加。
touch big 1902_1
chattr +a big1902_1 # 表示该文件只允许追加内容,不允许删除和修改。
a、i的使用场景:
通常情况,log文件用a的属性。如果是cfg(配置文件)文件用i的属性。
lsattr 查看文件的物理权限(属性)
lsattr [选项] 文件/夹
选项:
R | 表示递归处理 |
---|---|
a | 表示查看所有文件的属性,包括隐藏 |
d | 显示目录的属性,而不是目录下的文件的属性 |
修改用户的所有者和属组:
用法:chown 所有者:属组 文件名
普通用户的超级权限:
sudo(SuperUser Do),它可以让普通用户执行root的权限。sudo可以限制用户执行部分root的权限。
sudo会记录用户执行过的每一条命令,便于查阅服务起出事之前的状态。
好处:
使用自己配置好的用户环境
不需要知道root密码,保证root的密码安全
可以限制用户执行有限的root权限
sudo执行的每条命令都会被记录,便于日后的日志审计,例如用户执行过高危操作命令。
4 压缩与解压缩
压缩:
指通过某些算法,将文件尺寸进行相应的缩小,同时不损失文件的内容。
将多个文件(或目录)合并成一个文件,方便传递或部署。
在Linux系统中,文件的后缀名不重要,但是针对于压缩文件的后缀名是必须的,因为可以让其他的程序员根据文件的后缀名使用对应的算法进行解压。
Linux常见的压缩文件后缀名:
*.gz | gzip程序压缩的文件 |
---|---|
*.tar | tar命令打包的数据,并没有压缩过 |
*.tar.gz | tar程序打包的文件,并且经过 gzip 的压缩 |
4.1 gzip文件压缩与解压缩
语法:
# 不保留源文件的压缩
gzip 文件名
# 保留源文件的压缩
gzip -c 文件名 > 压缩文件名(.gz)
# 不保留压缩文件的解压缩
gzip -d 压缩文件名(.gz)
# 保留压缩文件的解压缩
gzip -cd 压缩文件名(.gz) > 解压后文件名
示例:
4.2 tar 文件压缩与解压缩
语法:
# 压缩文件
tar -cvf 压缩文件名(.tar) 要压缩的文件名
# 查看压缩文件
tar -tvf 压缩文件名(.tar)
# 解压缩到指定目录
tar -xvf 压缩文件名(.tar) -C 要解压的目录
示例:
4.3 tar.gz文件压缩与解压缩
语法:
# 压缩文件
tar -czvf 压缩文件名(.tar) 要压缩的文件名
# 查看压缩文件
tar -tzvf 压缩文件名(.tar)
# 解压缩到指定目录
tar -xzvf 压缩文件名(.tar) -C 要解压的目录
示例:
5 软件管理员 之 RPM
RPM 的全称为Redhat Package Manager ,是由Redhat 公司提出的,用于管理Linux 下软件包的软件。
RPM 是以一种数据库记录的方式(/var/lib/rpm/ 目录下)来将你所需要的软件安装到你的 Linux 系统的一套管理机制。目前 Fedora, CentOS, SuSE 等等知名的开发商都是用RPM。
优点:
1)RPM 内含已经编译过的程序与配置文件等数据,可以让使用者免除重新编译的困扰;
2)RPM 在被安装之前,会先检查系统的硬盘容量、操作系统版本等,可避免文件被错误安装;
3)RPM 文件本身提供软件版本信息、相依属性软件名称、软件用途说明、软件所含文件等信息,便于了解软件;
4)由于软件的信息都已经记录在 Linux 主机的数据库上,很方便查询、升级与卸载;
缺点:
1) 软件文件安装的环境必须与打包时的环境需求一致或相当;
2) 需要满足软件的相依属性需求;
3)卸载时需要特别小心,最底层的软件不可先移除,否则可能造成整个系统的问题!
由于RPM只是记录依赖关系信息,但不是自动安装依赖软件的YUM 可以自动安装依赖软件。
6 用yum安装常用软件
6.1 yum 简介
yum 是一个在Fedora 和RedHat 以及SUSE 中的Shell 前端软件包管理器。
基于RPM 包管理,能够从指定的服务器自动下载RPM包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖的软体包,无须繁琐地一次次下载、安装。
yum提供了查找、安装、删除某一个、一组甚至全部软件包的命令,而且命令简洁而又好记。
RPM 的全称为Redhat Package Manager ,是由Redhat 公司提出的,用于管理Linux 下软件包的软件。
机制:
1)yum有自己的仓库,也叫源;将RPM 里面的软件都下载到yum库里。
2)RPM提供了每个软件的信息及依赖关系, yum分析每个软件的信息及依赖关系,生成一个安装软件的清单。
3)当你要装某个软件的时候,它会根据清单,来先安装依赖,再安装自己。
所有的yum源都存放在/etc/yum.repos.d/目录下
默认的yum源是国外源,网速慢,需要修改yum源为国内的源。
yum命令格式:
yum [options] [command] [package ...]
options:可选,选项包括-h(帮助),-y(当安装过程提示选择全部为"yes"),-q(不显示安装的过程)等等。
command:要进行的操作。
package操作的对象。
yum 常用命令:
1)列出所有可更新的软件清单命令:yum check-update
2)更新所有软件命令:yum update
3)仅安装指定的软件命令:yum install
4)仅更新指定的软件命令:yum update
5)列出所有可安裝的软件清单命令:yum list
6)删除软件包命令:yum remove
7)查找软件包 命令:yum search
8)清除缓存,并生成新的缓存命令:
yum clean all
yum makecache
6.2 配置阿里云 yum 源
1)安装sz rz工具,用于以后用rz sz上传下载文件
yum install -y lrzsz
2)下载 repo 文件
文件下载地址: http://mirrors.aliyun.com/repo/Centos-7.repo
3)用 rz 将下载的 Centos-7.repo 文件上传到Linux系统的某个目录下
第一种上传方式,通过SFTP,突破了4G文件大小的限制。
第二种上传方式:
用rz命令,限制文件最大4G
4)备份并替换系统的repo文件
cp Centos-7.repo /etc/yum.repos.d/
cd /etc/yum.repos.d/
mv CentOS-Base.repo CentOS-Base.repo.bak
mv Centos-7.repo CentOS-Base.repo
5)执行yum源更新命令
yum clean all
yum makecache
yum update -y
配置完毕。
7 Vim 编辑器
7.1 安装vim
# root 用户执行
yum install -y vim
7.2 vim 常用命令
模式切换:
按Esc 键进入命令模式:
执行光标移动
执行复制和粘贴
# 复制光标所在行数据,粘贴到光标所在行的下一行
yy + p
# 复制光标所在行数据,粘贴到光标所在行的上一行
yy + P
# 复制包含光标所在行的3行数据, 粘贴到光标所在行的下一行
3yy + p
执行删除
# 删除光标所在行数据
dd
# 删除包含光标所在的3行数据
3dd
: 进入行命令模式
搜索和替换:
# 替换当前行,你的光标要定位到要替换的行
:s/目标/替换/g
#替换全文,光标不需要定位到要替换的行
:%s/目标/替换/g
保存和退出:
set nu 开启显示行号
set nonu 关闭显示行号
8 第一个程序:HelloWorld
在root家目录下创建shell目录,在shell目录下创建一个hello.sh 文件,文件内容如下:
#! /bin/bash
# 输出hello world
echo "hello world!"
其中:
第一行:#! 开头,指定脚本的运行环境。
第二行:#开头,养成良好的注释习惯,这里一般说明脚本功能、作者、修改历史等等
echo ,把其参数传递给标准输出。
执行脚本需要 hello.sh 文件有执行权限,设置hello.sh 文件的执行权限
chmod a+x hello.sh
执行hello.sh文件脚本
# sh :即使没有执行权也可以执行
sh hello.sh
#路径方式:可以采用绝对路径或相对路径
#注意:拥有执行权才可以执行
./hello.sh
/root/shell/hello.sh
示例:
[root@localhost ~]# mkdir shell
[root@localhost ~]# cd shell
[root@localhost shell]# vim hello.sh
#! /bin/bash
# 输出hello world
echo "hello world!"
~
"hello.sh" [新] 3L, 52C 已写入
[root@localhost shell]# ll
总用量 4
-rw-r--r--. 1 root root 52 8月 13 19:53 hello.sh
# 不加执行权也能运行
[root@localhost shell]# sh hello.sh
hello world!
# 目录方式必须加执行权
[root@localhost shell]# ./hello.sh
-bash: ./hello.sh: 权限不够
# 给所有用户组都加了执行权
[root@localhost shell]# chmod a+x hello.sh
# 相对路径运行
[root@localhost shell]# ./hello.sh
hello world!
[root@localhost shell]# pwd
/root/shell
# 绝对路径运行
[root@localhost shell]# /root/shell/hello.sh
hello world!
9 变量和运算符
9.1 变量赋值和使用
#! /bin/bash
# 将一个变量赋给str
str="monday"
echo "today is: $str"
echo ${str}
其中:
1)变量名首字符必须为字母,名字只能用字母、数字、下滑线,不要用bash关键字。非法的名字:8var、var-8
2)变量定义或赋值时,变量名与值之间用等号连接:变量名=值,等号两边不能有空格,值中有空格或特殊字符需要用双引号或单引号引起来。
3)使用 $变量名 或 ${变量名} 形式获取变量值,这两种方式没有什么区别,但推荐用${}方式。
如何调试 shell 脚本?
命令格式:sh -x shell脚本名称
功能:将脚本的每个步骤都执行一遍并输出到屏幕,利于调试代码。
[root@localhost shell]# vim s1.sh
#! /bin/bash
#将一个变量赋给str
str="monday"
echo "today is: $str"
echo ${str}
~
"s1.sh" [新] 6L, 87C 已写入
# 调试脚本:正常执行
[root@localhost shell]# sh -x s1.sh
+ str=monday
+ echo 'today is: monday'
today is: monday
+ echo monday
monday
[root@localhost shell]#
# 故意把脚本修改错 echo --> eho
[root@localhost shell]# vim s1.sh
#! /bin/bash
#将一个变量赋给str
str="monday"
eho "today is: $str"
echo ${str}
~
"s1.sh" 6L, 86C 已写入
# 调试脚本报错,根据报错定位脚本错误位置
[root@localhost shell]# sh -x s1.sh
+ str=monday
+ eho 'today is: monday'
s1.sh:行5: eho: 未找到命令
+ echo monday
monday
[root@localhost shell]#
9.2 变量替换
美元符号$ ,如果想输出$ 符号,则要用“\” 进行转义。
示例:
s2.sh 文件内容如下
#! /bin/bash
str="100"
echo "人民币: ¥${str}"
echo "美元: \$ ${str}"
9.3 位置变量
示例:
[root@localhost shell]# vim s3.sh
#! /bin/bash
# $0:脚本的名称
echo \$0: $0
# $1:第1个入参
echo \$1: $1
# $4:第4个入参
echo \$4: $4
# $#:脚本入参个数
echo \$#: $#
# $*:所有参数组成一个字符串
echo \$*: $*
# $@:每个位置参数是一个字符串
echo \$@: $@
# $?:上个命令的返回值,0:执行成功;非0:执行失败
echo \$?: $?
# $$:当前进程id
echo \$$: $$
# 命令执行失败
cho "hehe"
# 返回非0
echo \$?: $?
执行结果:
9.4 bush 引号规则
1)单引号'':单引号里面的所有字符都是普通字符。
2)双引号"":双引号会保留变量特性,用值替换。
3)倒引号``:位于Esc 键下方,用倒引号括起一个命令时,这个命令将会被执行,执行后的结果作为这个表达式的值。
示例:
[root@localhost shell]# vim s4.sh
#! /bin/bash
name=hehe
# 全是普通字符串
echo '$name'
# name可替换
echo "$name"
# 将date命令的结果输出
echo `date`
运行结果:
9.5 数组
9.5.1 定义数组
1)常量列表的方式
# 括号内的元素用空格分隔
arr1=("a1" "b1" "c1")
2)declare 命令定义数组
# 定义数据arr2,并初始化元素
declare -a arr2=("a2" "b2" "c2")
# 先定义,后给元素赋值
declare -a arr3
arr3[0]="a3"
arr3[1]="b3"
arr3[2]="c3"
9.5.2 使用数组
1)获取数组长度:
用${#数组名[@或*]} 可以得到数组长度
${#arr[*]} 或 ${#arr[@]}
2)读取数组元素:
读取下标为1的元素:${arr[1]}
读取数组整个元素:${arr[*]}
3)给数组元素赋值:
arr[1]=1
4)删除数组元素:
删除后,数组长度改变
unset arr[1]
${#arr[*]}
示例:
[root@localhost shell]# arr1=("a1" "b1" "c1")
[root@localhost shell]# echo ${arr1[*]}
a1 b1 c1
[root@localhost shell]# declare -a arr2=("a2" "b2" "c2")
[root@localhost shell]# echo ${arr2[*]}
a2 b2 c2
[root@localhost shell]# declare -a arr3
[root@localhost shell]# arr3[0]="a3"
[root@localhost shell]# arr3[1]="b3"
[root@localhost shell]# arr3[2]="c3"
[root@localhost shell]# echo ${arr3[*]}
a3 b3 c3
[root@localhost shell]#
# 查看数组长度
[root@localhost shell]# echo ${#arr3[*]}
3
# 获取数组第一个元素
[root@localhost shell]# echo ${arr3[0]}
a3
# 删除数组第一个元素,数组长度-1
[root@localhost shell]# unset arr3[0]
[root@localhost shell]# echo ${#arr3[*]}
2
[root@localhost shell]# echo ${arr3[*]}
b3 c3
9.6 运算符
9.6.1 比较运算符
9.6.1.1 数字比较
运算符 | 说明 | 示例 |
---|---|---|
-eq | 等于 | [ 1 -eq 1 ] && echo 'ok' |
-ne | 不等于 | [ 1 -ne 2 ] && echo 'ok' |
-lt | 小于 | [ 1 -lt 2 ] && echo 'ok' |
-gt | 大于 | [ 1 -gt 0 ] && echo 'ok' |
-le | 小于等于 | [ 1 -le 1 ] && echo 'ok' |
-ge | 大于等于 | [ 1 -ge 1 ] && echo 'ok' |
注意:
[]内部写的时候,要用空格隔开。
[root@localhost shell]# [ 1 -eq 1 ] && echo 'ok'
ok
[root@localhost shell]# [ 1 -lt 0 ] && echo 'ok'
[root@localhost shell]# [ 1 -lt 2 ] && echo 'ok'
ok
# 没有空格隔开,报错
[root@localhost shell]# [ 1 -lt 2] && echo 'ok'
-bash: [: 缺少 ]
# 变量替换也可以
[root@localhost shell]# a=1
[root@localhost shell]# [ $a -lt 2 ] && echo 'ok'
ok
[root@localhost shell]#
9.6.1.2 字符串比较
运算符 | 说明 | 示例 |
---|---|---|
== | 比较两个字符串是否相等,相等返回true | [ "aaa" == "aaa" ] && echo 'ok' |
!= | 比较两个字符串是否不相等,不相等返回true | [ "aaa" != "bbb" ] && echo 'ok' |
注意:
[]内部写的时候,要用空格隔开。
示例:
[root@localhost shell]# [ "aaa" == "aaa" ] && echo 'ok'
ok
[root@localhost shell]#
[root@localhost shell]# [ "aaa" != "bbb" ] && echo 'ok'
ok
# 字符串判空
[root@localhost shell]# s=aaa
# 字符串非空
[root@localhost shell]# [ "${s}x" == "x" ] && echo 'ok'
[root@localhost shell]#
# 字符串为空
[root@localhost shell]# s=""
[root@localhost shell]# [ "${s}x" == "x" ] && echo 'ok'
ok
9.6.2 逻辑运算符
运算符 | 说明 | 示例 |
---|---|---|
! | 非运算 | [ ! 2 -lt 1 ] && echo 'ok' |
-o | 或运算 | [ 1 -eq 1 -o 1 -eq 2 ] && echo 'ok' |
-a | 与运算 | [ 1 -eq 1 -a 2 -eq 2 ] && echo 'ok' |
&& | 短路与运算,在[]表达式内不能用,在[]表达式间可用 | [ 1 -eq 1 -a 2 -eq 2 ] && echo 'ok' |
|| | 短路或运算,在[]表达式内不能用,在[]表达式间可用 | [ 1 -ne 1 ] || echo 'ok' |
注意:
[]内部写的时候,要用空格隔开。
示例:
[root@localhost shell]# [ ! 2 -lt 1 ] && echo 'ok'
ok
[root@localhost shell]# [ 1 -eq 1 -o 1 -eq 2 ] && echo 'ok'
ok
[root@localhost shell]# [ 1 -eq 1 -a 2 -eq 2 ] && echo 'ok'
ok
[root@localhost shell]# [ 1 -eq 1 -a 2 -ne 2 ] && echo 'ok'
[root@localhost shell]# [ 1 -ne 1 ] || echo 'ok'
ok
9.6.3 文件运算符
示例:
[root@localhost shell]# [ -e hello.sh ] && echo 'ok'
ok
[root@localhost shell]# [ -f hello.sh ] && echo 'ok'
ok
[root@localhost shell]# [ -d hello.sh ] && echo 'ok'
[root@localhost shell]#
10 分支语句
10.1 if语句
语法:
if 条件表达式一 ; then
表达式一true时执行这里
#[
elif 条件判断式二 ; then
表达式二true时执行这里
elif 条件判断式三 ; then
表达式三true时执行这里
else
都不成立时,执行这里
#]
fi
其中:
[] 内的是可选。
示例:
需求:实现根据脚本入参判断是start、stop、restart,然后输出相应操作;否则输出Other操作
[root@localhost shell]# vim s5.sh
#! /bin/bash
cmd=$1
if [ $cmd == "start" ]; then
echo "start operation"
elif [ $cmd == "stop" ]; then
echo "stop operation"
elif [ $cmd == "restart" ]; then
echo "restart operation"
else
echo "other operation"
fi
10.2 多分支:case
case $var in
模式1)
代码块1
;;
模式2)
代码块2
;;
模式3)
代码块3
;;
*)
代码块4
;;
esac
示例:
需求:把上面if需求的代码用case实现
[root@localhost shell]# vim s6.sh
#! /bin/bash
cmd=$1
case $cmd in
"start") echo "start operation"
;;
"stop") echo "stop operation"
;;
"restart") echo "restart operation"
;;
*) echo "other operation"
;;
esac
11 for循环语句
11.1 for 循环变量 in 数据列表
语法:
for 循环变量 in 数据列表
do
循环体代码段
done
其中:
这里的数据列表 是一系列以空格分隔的值,shell每次从这个列表中取出一个值,然后运行do/done 之间的命令。
如:
示例:
需求:输出指定目录(脚本入参)下文档是文件类型的文档
[root@localhost shell]# vim s7.sh
#! /bin/bash
# 获取输入参数
base_path=$*
# 将目录下的列表用括号括起来变成数组
arr=(`ls $base_path`)
# 遍历数组的每个元素(文档)
for f in ${arr[*]}
do
# 判断是否是文件
if [ -f $f ]; then
echo "$f is file"
fi
done
运行结果:
11.2 for (( 控制变量的初始化; 循环的条件; 循环控制变量的更新 ))
语法:
#满足条件则循环否则退出
for (( 控制变量的初始化; 循环的条件; 循环控制变量的更新 ))
do
循环体代码段
done
示例:
1)计算从1加到10的结果;统计偶数的个数
[root@localhost shell]$ vim s8.sh
#! /bin/bash
sum=0
count=0
for((i=1;i<=10;i++))
do
# 求和
sum=$((sum+i))
# 统计偶数的个数
if [ $((i%2)) -eq 0 ]; then
((count++))
fi
done
echo sum:${sum}, count:${count}
12 字符串操作
读取、截取、长度、替换
示例: