1.1 linux 结构介绍
在认识一个新的东西时,先了解其结构对于我们了解它还是很有 帮助的。Linux 文件系统是呈树形结构,/ 为 Linux 的根目录,其下主要目录为 :
目录 | 说明 |
---|---|
/ | Linux 文件系统的入口,也是处于最高一级的目录,所有的目录、文件、设备都在/之下 |
/bin | bin 就是二进制(binary)英文缩写。在一般的系统当中,都可以在这个目录下找到 linux 常用的命令。系统所需要的那些命令位于此目录。 |
/boot | 内核和加载内核所需要的文件。一般情况下,GRUB 系统引导管理器也位于这个目录 |
/dev | 设备文件存储目录,比如终端、磁盘等 |
/etc | 所有的系统配置文件 |
/home | 普通用户家目录的默认存放目录 |
/lib | 库文件和内核模块所存放的目录 |
/media | 即插即用型存储设备的挂载点自动在这个目录下创建,比如 u盘、CDROM/DVD 自动挂载后,也会在这个目录中创建一个目录。 |
/mnt | 临时文件系统的挂载点目录 |
/opt | 第三方软件的存放目录 |
/root | Linux 超级权限用户 root 的家目录 |
/sbin | 基本的系统维护命令,只能由超级用户使用 |
/srv | 该目录存放一些服务启动之后需要提取的数据 |
/tmp | 临时文件目录 |
/usr | 存放用户使用系统命令和应用程序等信息,比如命令、帮助文件等。 |
/var | 存放经常变动的数据,比如日志、邮件、安装好的 php 环境等。 |
注意:以上几个加粗的目录需要了解。
1.2 linux 常用命令介绍
1.2.1 目录命令
(1)ls - 显示指定工作目录下之内容
语法:
ls [选项]
常用选项:
-a 查看所有包括隐藏目录
-l 长显示,显示目录或者目录详细信息包括大小 修改时间
-d 显示目录
-h 更加人性化显示 比如字节转换为MB,GB 不用自己算
-i 查询目录inode号(inode存储目录的详细信息) 信息编号,类似于人的身份证号码
(2)mkdir - 创建目录
语法:
mkdir [-p] dirName # -p 可选,确保目录名称存在,不存在的就建一个
mkdir runoob # 在工作目录下,建立一个名为 runoob 的子目录
(3)pwd - 显示当前所在路径
语法:
pwd [选项]
(4)cd - 切换当前工作目录
语法:
cd [目标目录]
cd ../ # 代表上一级
cd / # 代表根目录
(5)cp - 复制目录
语法:
cp [选项] 源目录 目标目录 # 可以复制多个,多个之间用 空格 隔开
常用选项:
-r 若给出的源文件是一个目录文件,此时将复制该目录下所有的子目录和文件
-p 除复制目录的内容外,还把修改时间和访问权限也复制到新目录中
-rp 复制目录并且保留原目录属性
(6)mv - 剪切 / 重命名目录
语法:
mv [选项] 源目录 目标目录
常用选项:
-b 当目标目录或目录存在时,在执行覆盖前,会为其创建一个备份
-i 源目录和目标目录同名提示,输入 y 表示直接覆盖,输入 n 表示取消该操作
-f 不询问强制覆盖
注意:如果需要实现改名,则在确定的目录后面加入修改后的名称。
(7)rm - 删除
语法:
rm [选项] 目录名 # 可以删除多个
常用选项:
-f 强制删除,不询问
-r 将目录及以下之档案亦逐一删除
-rf 一起使用则会将目录及以下文档都删除
1.2.2 文件命令
1. 基本命令
(1)touch - 创建文件
语法:
touch 文件名
(2)cat - 显示文件内容
语法:
cat [选项] 文件名
常用选项:
-n 或 --number 由 1 开始对所有输出的行数编号
-A, --show-all 显示所有隐藏字符
注意:tac 可以倒序查看,但不支持以上命令。
(3)more - 分页显示
语法:
more 文件名
按 空格键 下一页显示;
按 b 键 上一页显示;
按 h 键 使用中的说明文件;
另搜寻字串的功能(与 vi 相似)。
文件的复制,移动,删除 同 目录操作。
2. 搜索命令
(1)find - 查找文件
语法:
find [范围] [-选项] 关键字
例:find *.html 范围不写默认为当前目录。如果不确定的可以使用 * 代替。
常用选项:
-name 文件名称符合 name 的文件
[iname 不区分大小写搜索]
例:find /etc/ -name passwd 或者 find /etc/ -name *.conf 。
-size 根据文件大小查找
-a 两个条件同时满足
-o 两个条件满足任意一个即可
例:find /etc -size +163840 -a -size -204800 查找大于 80m 小于 100m 的文件。
(2)locate - 文件资料库查找
语法:
locate 文件名
注意:不是默认的,无法直接使用,需要通过 yum install mlocate 安装后才能使用。
(3)grep - 在文件内查询字符串或者关键字
语法:
grep [选项] [指定字符串] [文件]
常用选项:
-i 不区分大小写
-v 排除指定字符串
-d 当指定要查找的是目录而非文件时,必须使用这项参数,否则grep指令将回报信息并停止动作
例:grep name *.html 在当前目录中,查找后缀为 html 文件中包含 name 字符串的文件并打印。
3. 文件编辑
所有的 Unix 系统都会内建 vi 文书编辑器,vim 不一定会存在。vim 是从 vi 发展出来的一个文本编辑器,相当于是 vi 的升级版。其区别主要体现在 :
1.对 vi 的完全兼容
根据设定可以和原始 vi 完全兼容。
2.多次撤销
例如 vi 里按 u 只能撤消上次命令,在 vim 里可以无限制的撤消。
3.远程文件编辑
vim 可以运行于 x window、 mac os、 windows。
4.语法加亮
vim 可以用不同的颜色来加亮你的代码。
......
(1)vi/vim 命令
# 操作类似,以下以 vi 演示,如果需要使用 vim 需要先安装
语法:
vi 文件
基本上 vi/vim 共分为三种模式:命令模式,输入模式 和 底线命令模式。
输入模式:
用户启动 vi/vim,便进入了命令模式。在这个模式下并非直接可以输入字符,而是执行了一个命令,常用命令 为:
i 在当前字符的左边插入
a 在当前字符的右边插入
o 在当前行下面插入一个新行
dd 删除整行
ndd n 为数字,删除光标所在向下 n 行。
yy 复制光标所在行
nyy n 为数字,复制光标所在向下 n 行
P 小 p 将复制的数据在光标下一行粘贴,大 P 将复制的数据在光标上一行粘贴
u 撤消前一个操作
输入模式:
在命令模式下通过命令可以插入字符时则可以进入到输入模式,此时在终端最下面显示的是 --INSERT-- 。在该模式下就可以对文件的内容进行编辑。
底线命令模式:
编辑完成后按 ESC 切换到底线模式。进入到底线模式后可以使用下面的命令来执行对应操作:
:w 保存数据[强制操作使用 :w!]
:wq 保存退出
:q 不保存退出[强制操作使用 :q!]
:w 文件名 相当于另存为
:set nu显示行号
:set nonu 取消行号
1.2.3 「用户」和 「组」 管理
Linux 系统是一个多用户多任务的分时操作系统,任何一个要使用系统资源的用户,都必须首先向系统管理员申请一个账号,然后以这个账号的身份进入系统。对于用户账号主要有添加、修改 与 删除 等操作。
1. 用户管理
(1)useradd - 添加用户
语法:
useradd [选项] 用户名
常用选项:
-d 目录 指定用户主目录
-m 联合 -d 当不存在时可以创建主目录
-g 指定用户所属的用户组
-s 指定用户的登录Shell
例:useradd –d /home/sam -m sam
(2)passwd - 添加密码
语法:
passwd [选项] 用户名
常用选项:
-d 删除用户密码
(3) 设置密码
# passwd user
更改用户 user 的密码 。
新的 密码: # 这里不会显示
重新输入新的 密码: # 这里不会显示
passwd:所有的身份验证令牌已经成功更新。
# 注意 设置密码不能过于简单
在创建了用户后,重新登录时通过新创建的用户名称和密码登录即可。
(4)usermod - 修改
语法:
usermod [选项] 用户名
选项可以参考添加,修改用户账号就是根据实际情况更改用户的有关属性,主目录、用户组、登录Shell等。
(5)userdel - 删除账号
语法:
userdel 选项 用户名
常用选项:
-r 把用户的主目录一起删除
2. 组管理
每个用户都有一个用户组,而不同的用户可以有相同的用户组也可以有不同的用户组 :
对于组的操作主要也是添加、修改与删除等操作。
(1)groupadd - 添加
语法:
groupadd [选项] 用户组
常用选项:
-g GID 指定新用户组的组标识号(GID)。 例:groupadd -g 101 group1
-o 一般与-g选项同时使用,表示新用户组的GID可以与系统已有用户组的GID相同
(2)groupmod - 修改
语法:
groupmod [选项] 用户组
常用选项:
-n 将用户组的名字改为新名字
-g 与 -o 与上相同
例:groupmod -og 100 -n user group1
(3)groupdel - 删除
语法:
groupdel 用户组
如果一个用户有多个组,可以通过 newgrp 组名来切换。
1.2.4 权限设置
1. 常用的权限操作
权限设置
即控制用户对文件的权限的管理。权限 主要分为 读=》r
、写=》w
和 执行=》x
权限。而 Linux 的文件 调用权限 分为三级 : 文件所有者(Owner=》o)、用户组(Group=》g)、其它用户(Other Users=》o)【如果要给所有用户添加可以使用 a 即 all】。
在 Linux 中想要修改权限可以使用 chmod
命令,而修改文件权限可以使用两种方式来实现,分别是: 符号模式
和 八进制数字模式
。
(1)符号模式 - 即 通过符号修改用户的权限
例如:添加权限使用 +
。
语法:
chmod 修改对象 操作 权限 文件/目录
修改对象:
u(user)文件所有者
g(group) 文件所有者所在组
o(others) 所有其他用户
a(all)所用用户, 相当于 ugo
操作:
+ 为指定的用户类型增加权限
- 为指定用户类型去除权限
= 设置指定用户权限的设置,即将用户类型的所有权限重新设置
例:chmod g+w hello # 用户组添加写权限
(2)八进制模式 - 即使用八进制数来指定权限。
语法:
chmod 八进制数 文件/目录
八进制数:
基础:
0 无
1 执行
2 写
4 读
组合:
3 写 + 执行
5 读 + 执行
6 读 + 写
7 读 + 写 + 执行
例:
chmod 777 hello # 给所有用户添加 读写执行 权限
chmod 755 hello # 给所有者 读写执行 权限,所属组和其他 读 与 执行 权限
注意:只有文件
所有者
和超级用户
可以修改文件或目录的权限。如果需要对目录递归操作则可以加上 -R 参数来实现。
(3)chown - 改变所有者
语法:
chown 用户 文件/目录
例:chown user hello # 改变 hello 的所有者为 user
(4)chgrp - 改变所属组
语法:
chgrp 组名 文件/目录
例:chown group1 hello # 改变 hello 的所属组为 group1
1.2.5 进程管理
1. 常用进程操作
(1)ps - 进程查看
进程是正在执行的一个程序或命令,每一个进程都是一个运行的实体,都有自己的地址空间,并占用一定的系统资源。在 Linux 中查看进程可以使用 ps 命令。
语法:
ps [选项]
常用选项:
-A 列出所有的进程 【-e 与之相同】
-w 显示加宽可以显示较多的资讯
-f显示UID,PPIP,C与STIME栏位
-au 显示较详细的资讯
-aux 显示所有包含其他使用者的行程
(2)top - 实时显示进程动态
语法:
top [选项]
常用选项:
-c 切换显示模式,只显示执行档的名称/显示完整的路径与名称
-d 改变显示的更新速度【秒】
在使用了 top 命令进入到交互模式之后,可以使用以下命令来修改查看:
P 以CPU使用率排序,默认就是此项
M 以内存的使用率排序
N 以PID排序
q 退出top
(3)kill - 杀死进程
语法:
kill [选项] [进程号]
常用选项:
-l 查看可用的进程信号
其中:
1 重新加载进程
9 杀死一个进程
15 正常停止一个进程
例:
kill -9 666666 # 彻底杀死 id 为 666666 的进程
注意:与之类似的还有 killall 和 pkill 命令:killall 与 pkill 会杀死指定名字的所有进程。
2. 进程管理
如果你发现运行的一个程序需要很长的时间,但是还需要干其他的事情,你可以把当前的程序放到后台执行。命令放入后台可以使用以下几种方式:
- command & :后台运行,你关掉终端会停止运行。
- nohup command & :后台运行,你关掉终端也会继续运行。
- Ctrl+Z 快捷键:命令执行过程中使用,使命令在后台暂停。
(1)&
例 - 查找文件并放入后台 :
find / -name hello&
[1] 92996
# 在 ‘find / -name hello’ 命令后面加上 & ,可以让命令在后台执行。其中 ‘ [1] ’ 是工作号,‘ 92996 ’ 是进程号。
(2)ctrl+z
例 - 实时显示进程动态,暂停放入后台 :
top # 回车执行,会实时显示
# 按 ctrl + z 显示以下内容
[1]+ 已停止 top
# top命令被放入后台,其中 '[1]' 是工作号, '+' 代表是最近放入后台。
(3)jobs
例 - 通过 jobs 命令可以查看当前运行的任务 :
jobs
# 结果......
[1] 完成 find / -name hello
[2]- 已停止 top
(4)fg
例 - 调度到前台
fg 2
# 结果,上面的任务会继续执行
(5)bg
例 - 继续执行
bg 3
# 结果,在后台暂停的命令,变成继续执行
注意:在后台运行的任务无法使用标准输入,也就是无法输入任何指令,相关信息则依然会显示。
使用 ctrl+c 则可以终止并退出前台命令的执行,回到 shell。
3. 守护进程
守护进程即 一直在后台运行的进程。在我们执行一个 shell 脚本时,多数都存在一个父进程 终端 shell
,而一旦父进程退出则会发送 SIGHUP 给所有子进程,子进程收到信号也会退出。如果我们要在退出 shell 的时候继续运行进程,则需要使用 nohup
忽略 SIGHUP 信号,或者 setsid
将父进程设为 init 进程(进程号为 1 )。
(1)nohup
在系统后台不挂断地运行命令,退出终端不会影响程序的运行
语法:
nohup 命令 [&]
例:
nohup /root/runoob.sh & # 在后台执行 runoob.sh 脚本
# 出现: nohup: 忽略输入并把输出追加到"nohup.out" 则表示成功
# 也可以使用以下方式实现:
1.nohup /root/runoob.sh &
2.(/root/runoob.sh &)
1.2.6 定时任务
(1)crontab - 定时任务
语法:
crontab [选项]
常用选项:
-e 编辑该用户的计时器设置
-l 列出该用户的计时器设置
-r 删除该用户的计时器设置
(2)定时任务的编写
语法: # 注意:这是一个格式而不是命令
* * * * * 任务
以上命令存在 5 个 * ,从左到右分别代表 几分、几时、几日、几月、周几【注意:最后面不是 年 而是 周几】。
例:
* * * * * echo hello >>/test/hello.log # 每分钟向 /test/hello.log 文件中追加 hello
# 注意:一个 * 并不代表只有一个时间,例如每天的 0时 与 12时 执行任务:
0 0,12 * * * 任务
总结:
不同单位时间用 「空格」 区分;
相同单位时间用「,」(多个时间点 - xx时间 和 xx时间 执行)
或 「-」(时间范围 - xx时间 到 xx时间 执行)
或 「/」(频率 - 每过多长时间执行)。
注意:当定时任务过多时,建议使用 shell 脚本。
1.2.7 管道
管道 是一种通信机制,通常用于进程间的通信(也可通过 socket 进行网络通信),它表现出来的形式将前面每一个进程的输出(stdout)直接作为下一个进程的输入(stdin);即 前者的输出是后者的输入。管道命令使用|
作为界定符号。
语法:
命令|命令...... # 可以使用多个
例如:
ps -ef|grep nginx # 找出进程中 nginx 相关的
注意:管道只能用于
具有亲缘关系
的进程间通信,即 前后命令不能毫无关系。更多更好的使用方式。
1.2.8 软件包管理
1. 压缩与解压
打包是指将一大堆文件或目录变成一个总的文件,压缩则是将一个大的文件通过一些压缩算法变成一个小文件。文件压缩后可以节约空间和方便网络传输。
(1)tar - 打包备份
在 Linux 系统里,tar
是将多个文件打包在一起,并且可以实现解压打包的文件的命令。是系统管理员最常用的命令之一, tar 命令不但可以实现对多个文件进行打包,还可以对多个文件打包后进行压缩。
语法:
tar [选项] 后文件名 原文件/目录
常用选项:
-c 打包
-v 显示详细信息
-f 指定文件名
-z 压缩或解压
-x 解包
例:
tar -zcf test.tar.gz test # 打包并压缩 test 目录为 test.tar.gz。注意:后缀为 .tar.gz ; 当打包压缩完毕后,源文件还会存在
tar -zxf test.tar.gz # 解压缩 test.tar.gz 文件,同样 源文件还在
(2)gzip - 压缩与解压文件
gzip
也能实现文件的压缩,但是只能压缩文件而不能压缩目录,并且会删除源文件。如果想要使用 gzip 压缩目录,需要先使用 tar 命令打包目录。
语法:
gzip [选项] 文件
例:
tar -cf test.tar dir # 打包 test 目录
gzip dir.tar# 压缩 dir.tar 文件
# 注意:如果需要解压可以使用 -d 选项或者使用 gunzip 命令。
(3)zip - 打包压缩
zip
压缩格式是 Window 与 Linux 等多平台通用的压缩格式。与 gzip 相比,zip 可以压缩目录并且不会删除源文件。
语法:
zip [选项] zip文件 源文件/目录
常用选项:
-r 递归处理,将指定目录下的所有文件和子目录一并处理
-x 压缩时排除符合条件的文件
-q 不显示指令执行过程
例:
zip -r test.zip test # 压缩 test 目录为 test.zip 文件
# 注意:与 gzip 类似,如果需要解压,可以使用 unzip 命令解压。
2. 软件安装
在 Linux 中安装软件主要有以下几种方式 :
-
源码包管理:Linux 的绝大多数开源软件都是直接以原码形式发布的,一般会被把源码打包成 .tar.gz 的归档压缩文件。我们使用这些软件前 需要将源代码编译成为二进制形式之后才能够运行使用。
-
RPM 包管理:RMP 是 LINUX 下的一种软件的可执行程序,你只要安装它就可以使用了。这种软件安装包通常是一个 RPM 包,后缀是
.rpm
,通过这种方式可以轻松实现软件的安装。 -
YUM 管理:RMP 软件包形式的管理虽然方便,但是需要手动解决软件包的依赖关系。YUM 是 RPM 的前端程序,其设计的目的是用来自动解决 rpm 包之间 的依赖关系。
(1)YUM使用
利用 yum 可以帮我们进行 查询、安装、升级 与 删除的功能。
语法:
yum [选项] [操作] 包
常用选项:
-y 安装过程中的选项全部为 yes
-q 不显示安装过程
常用操作:
查询:
list 查询所有可用软件包列表
search 关键字 搜索和关键字相关的包
安装:
install 安装
升级:
update 升级
卸载:
remove 卸载
接下来对于 yum 的几种操作尝试看看。
(2)查询
如果想要查询利用 yum 来查询原版 distribution 所提供的软件,或已知某软件的名称可以利用 查询 相关的参数来查找。
例:
yum list # 会列出 yum 服务器上提供的所有软件名称
# 列出 nginx 相关软件,最后的 installed 代表该软件已经安装
[root@VM-0-13-centos yum.repos.d]# yum list|grep nginx
bt-nginx118.x86_64 1.18.0-1.el7 installed
# 查看所有已经安装的软件 注意是 ed
[root@VM-0-13-centos yum.repos.d]# yum list installed
# 查看所有可以更新的软件 注意 有 s
[root@VM-0-13-centos yum.repos.d]# yum list updates
# 搜寻 nginx 相关软件
[root@VM-0-13-centos yum.repos.d]# yum search nginx
(3)安装
yum 安装软件需要使用 install 参数来实现安装。例:
yum install pam-devel # 安装 pam-devel,如果有相关软件需要安装或升级 yum 会自动帮你处理
# 可以使用以下命令在后续操作中全选择 yes
yum -y install pam-devel
更新、删除 与 安装 类似,把 install 替换成 update 即可。
1.3 linux 下构建 lnmp 环境
1.3.1 Nginx 安装
1 . 安装先决条件
sudo yum install yum-utils
如果已经存在,请忽略
2 . 创建 yum 库
vi /etc/yum.repos.d/nginx.repo
在其中添加以下内容:
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1
为了避免干扰可以先备份一下其他的库并删除。
3 . 安装 nginx
sudo yum install nginx
以上 nginx 安装成功,通过 nginx -v 可以查看 nginx 版本。
4 . 页面访问
如果需要通过浏览器访问到 nginx 的首页,需要 :
- 开启 web 端口:firewall-cmd --permanent --add-port=80/tcp
- 重启 firewall:firewall-cmd --reload
再通过 ip 地址即可访问到。
5 . php 支持
以上各个软件都已经安装完毕,但是当你通过服务器访问 php 文件时,则会提示 File not found
。这里需要我们修改一下 nginx 的配置文件 - nginx.conf :
location ~ \.php$ {
root /usr/share/nginx/html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include/etc/nginx/fastcgi_params;
}
可以在安装完 php 后再来测试。
1.3.2 MySQL 安装
1 . 下载 mysql 源安装包
wget http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm
如果知道源,也可以直接配置修改 源 配置文件。
2 . 安装 mysql 源
yum localinstall mysql57-community-release-el7-8.noarch.rpm
安装完成后可以在 /etc/yum.repos.d 目录中看到对应的 源 配置文件。查看该配置文件可以看到有几个源,其中 enabled=1 的即为允许使用的源。如果需要可以根据自己的需求修改配置文件。
3 . 安装 mysql
yum install mysql-community-server
安装完成后可以启动 mysql:
systemctl start mysqld
mysql 会帮我们生成初始密码,可以通过 以下命令查看 :
cat /var/log/mysqld.log | grep password
# A temporary password is generated for root@localhost: wM))4aqnwqHf # 4aqnwqHf 即为密码
如果需要可以修改一下密码。如下 :
补充 - 密码修改 :
1 . 跳过验证
如果忘记密码而无法登录,可以在 my.cnf 配置文件中添加 skip-grant-tables 来跳过验证 :
vim /etc/my.cnf
---------------------------------------------------------------------
[mysql]
# 在 mysql 的下面添加以下内容
skip-grant-tables
修改完成后要重启一下:service mysqld restart。
2 . 修改密码
输入 mysql -u root -p 然后直接敲回车,可以直接进入到 mysql :
# 选择 mysql 数据库
mysql> use mysql;
# 修改密码为 root ,authentication_string 是密码的字段
mysql> update user set authentication_string=password('root') where user='root';
修改完毕,去除 my.cnf 配置文件中添加的内容重新登录即可使用新增的密码登录。
1.3.3 PHP 安装
1 . 安装 epel-release 软件包
yum install epel-release
2 . 更新 rpm 源
rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
3 . 安装 php
在安装前,需要根据自己的需求使对应的源生效 :
vim /etc/yum.repos.d/remi-php70.repo
---------------------------------------------------------------------
[remi-php74]
name=Remi's PHP 7.4 RPM repository for Enterprise Linux 7 - $basearch
mirrorlist=http://cdn.remirepo.net/enterprise/7/php74/mirror
enabled=1
4 . 安装 php 相关软件包
yum --enablerepo=remi install php php-pdo php-mysql php-fpm php-cli php-common
以上 还可以根据自己的需求添加。安装完毕后可以通过 php -v
命令查看 php 版本。
1.4 shell 应用
1.4.1 Shell 简介
Shell 脚本(shell script)拆分为两部分为 shell
和 script
。 操作系统的核心是需要保护起来的,所以我们需要一个桥梁来跟核心沟通,让核心帮助我们完成想要达到的工作,而 shell 则是这样一个桥梁。script 即为脚本的意思,根据编辑的内容来执行。shell script 即为给 shell 所写的「剧本」。
Shell 脚本命令的工作方式有两种:交互式和批处理。
1. 交互式(Interactive)
用户每输入一条命令就立即执行。
echo 'Hello World'
2. 批处理(Batch)
由用户事先编写好一个完整的 Shell 脚本,Shell 会一次性执行脚。
(1)编写脚本
[root@localhost shell]# vi hello.sh
#!/bin/bash
#first shell
echo 'Hello World'
没错,编写 shell 脚本只需要创建一个文件,并在该文件中编写预先设定的 linux 命令即可。该文件可以是任意后缀,只不过为了区分建议加上 .sh
作为后缀。
脚本说明 :
第一行的(#!)是脚本声明,用来告诉系统使用哪种 Shell 解释器来执行该脚本。
第二行(#)是注释信息,是对脚本功能和某些命令的介绍信息。
第三行开始可以是自己的命令,例如平时执行的 linux 命令了 ls -l
。
(2)执行脚本
[root@localhost shell]# bash hello
Hello World
1.4.2 变量
1. 变量
是计算机内存的单元,其中存放的值可以改变。当 shell 脚本需要保存一些信息时,如一个文件名或是一个数字,就把它存放在一个变量中。
(1)变量命名
- 变量名称可以由字母、数字和下划线组成 ,但是不能以数字开头,不能使用关键字(可用 help 命令查看保留关键字)。
- 在 Bash 中,变量的默认类型都是字符串型。在赋值时等号两边不能存在空格,变量的值如果有空格,需要使用引号包括。
- 定义变量时不需要添加 $ ,但是在使用时,需要使用 $ 或者使用反引号。
- 环境变量名建议大写,便于区分。
(2)变量分类
- 局部变量:局部变量定义在脚本或命令中,仅在当前 shell 实例中有效,其他 shell 程序不能访问该局部变量。
- 环境变量:所有的程序都能访问环境变量,必要的时候 shell 脚本也可以定义环境变量。
- shell 变量:shell 变量是由 shell 程序设置的特殊变量。shell 变量中既有环境变量也包含局部变量,这些变量保证了shell的正常运行。
(3)第一个变量
#!/bin/bash
#first shell
name="hello" # 定义值为 hello 的变量,名称为 name
echo $name # 输出变量的值
以上就定义完成了自己的变量,如果想要「过河拆桥」可以使用 unset 变量名称
的方式删除变量(unset name)。
2. 数据类型
(1)字符串
字符串是 shell 中最常用最有用的数据类型,字符串可以用单引号、双引号也可以不用引号。
# 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的。双引号则可以输出变量值。
#!/bin/bash
name="hello"
echo 'i am $name' # 输出 i am $name
echo "I am $name" # 输出 I am hello
在 shell 中,想要拼接字符串不需要添加额外符号。例如 :
#!/bin/bash
name="hello"
echo 'my name is '$name'. who are you?' # 输出 my name ishello. who are you?
(2) 整数型
在 Shell 中所有的变量默认都是字符串型。也就是说,如果不手动指定变量的类型,那么所有的数值都是不能进行运算的。例 :
#!/bin/bash
echo 1+1 # 结果输出为 1+1 如果想要进行运算则需要如下
如果想要进行数学运算,可以使用以下几种方式运算 :
运算指令 | 作用 |
---|---|
(()) | ((a=1+2)) |
let | let b=6+13 |
expr | expr 2 + 8 |
$[] | echo $[1+2] |
bc | 可结合输入重定向使用 |
例 :
#!/bin/bash
echo $((1+1))
let a=1+1
echo $a
expr 1 + 1
echo $[1+1]
注意:expr 运算符左右需要有空格。
(3)数组
数组中可以存放多个值。bash 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小。数组元素的下标由 0 开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0。
创建数组有两种方式 :
#!/bin/bash
# 直接创建数组
array=(1,2,3,4,5,6)
echo $array
# 先创建数组,再通过下标赋值
array=()
array[0]=1
array[1]=2
echo $array
同样数组可以通过下标取值 :
echo ${array[1]}
echo ${array[@]}# 传递 @ 或者 * 都可以打印所有值。@ 是拆分的字符串,* 是一个字符串
1.4.3 运算符
shell 和其他编程语言一样,支持多种运算符。下面列出了一些常用运算符 :
优先级 | 运算符 | 说明 |
---|---|---|
13 | -, + | 单目负、单目正 |
12 | !, ~ | 逻辑非、按位取反或补码 |
11 | *,/, % | 乘、除、取模 |
10 | +, - | 加、减 |
9 | << , >> | 按位左移、按位右移 |
8 | < =, > =, < , > | 小于或等于、大于或等于、小于、大于 |
7 | == , != | 等于、不等于 |
6 | & | 按位与 |
5 | ^ | 按位异或 |
4 | | | 按位或 |
3 | && | 逻辑与 |
2 | || | 逻辑或 |
1 | =,+=,*=,… | 赋值相关 |
以上优先级数字越大,优先级越高。与其他语言类似的是,可以通过括号提升优先级。
实例 :
#!/bin/bash
a=1
b=5
c=$(( $a+$b ))
echo $c
c=$(( $a*$b ))
echo $c
c=$(( $a/$b ))
echo $c
c=$(( ($a+$b)/$a ))
echo $c
1.4.4 字符串
1. 字符串截取
(1)cut
改命令可以显示每行从开头算起 num1 到 num2 的字符串。
语法:
cut [选项] [文件]
常用选项:
-b 以字节为单位进行分割
-d 自定义分隔符,默认为制表符
-f 与-d一起使用,指定显示哪个区域
例:
cut -b 6 hello.txt # 提取第六列字符
cut -b 2,6 hello.txt # 提取第二和六列字符
cut -d ':' -f 2 hello.txt # 以 :为分隔符取第二列
(2)awk
文本分析工具。
awk 命令也叫 awk 编程,你没看错它就是一个编程语言,在这里我们主要介绍其使用方式。其特点为可以识别非制表符的空格,用来解决 cut 命令解决不了的提取列工作。
语法:
awk '条件1{动作1}条件2{动作2}...' 文件名
awk 后面需要接一对引号,并且在其中需要加上 {}
例:
ps -aux|awk '{print $2 "\t" $11}' # 查看进程的 PID 和 COMMAND 并以 [tab] 隔开
ps -aux|awk '0<1 {print $2 "\t" $11}' # 前面加入条件则会在条件成立后执行
补充:printf 是另一个输出命令不会自动换行,print 可以自动换行,但是只有 awk 中可以使用。
(3)sed
利用脚本来处理文本文件。
语法:
sed [选项] [动作] 文件名
常用选项:
-n 仅显示script处理后的结果
-e 以选项中指定的script来处理输入的文本文件
-i 用sed的修改结果直接修改读取数据的文件,而不由屏幕输出
常用动作:
a 追加,a 的后面接字串,这些字串会在新的一行出现
i 插入,i 的后面接字串,这些字串会在新的一行出现
c 替换行,c 的后面接字串,这些字串可以替换原数据行,替换多行时末位使用 \ 表示未完结
s 替换字符串,用一个字符串替换另外一个字符串
p 打印,输出指定的行
d 删除
例:
sed -e 2a\newmessage hello.txt # 在 hello.txt 文件中添加 newmessage
cat hello.txt | sed -n '2,3p' # 只显示 第 2,3 行的内容
cat hello.txt | sed '1,2d' # 删除 hello.txt 文件中的 1,2 行显示
2. 字符处理
(1)sort - 排序
语法:
sort [选项] 文件名
常用选项:
-f 忽略大小写
-n 依照数值的大小排序
-r 反向排序
-t 指定排序时所用的栏位分隔字符
例:
sort hello.txt # 排序查看 hello.txt 中的内容
sort -r hello.txt # 反向排序
(2)wc - 计算字数
语法:
wc [选项] 文件名
常用选项:
-l 只统计行数
-w 只统计单词数
-m 只统计字符数
例:
wc hello.txt # 结果 行数,单词 以及 字符数 都会显示
wc -l hello.txt # 统计 行数
1.4.5 条件判断
1. 检测
Shell 中的 test
命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的检测。
语法:
test 表达式
2. 数值判断
参数 | 说明 |
---|---|
-eq | 等于则为真 |
-ne | 不等于则为真 |
-gt | 大于则为真 |
-ge | 大于等于则为真 |
-lt | 小于则为真 |
-le | 小于等于则为真 |
例 :
[ 1 -le 2 ] && echo 'yes' || echo 'no' # 1是否小于2 小则为真
test 1 -le 2 && echo 'yes' || echo 'no' # 1是否小于2 小则为真
# 注意:中括号两边包含空格
以上两种方式可以得到结果,通过 echo 的方式来帮助我们查看结果,下面以第一种方式为主演示。
3. 字符串判断
参数 | 说明 |
---|---|
= | 等于则为真 |
!= | 不相等则为真 |
-z 字符串 | 字符串的长度为零则为真 |
-n 字符串 | 字符串的长度不为零则为真 |
例 :
name=hello
[ $name = 'hello' ] && echo 'yes' || echo 'no' # 判断变量是否为 hello
[ -z $name ] && echo 'yes' || echo 'no' # 判断字符串长度是否为 0
4. 文件判断
参数 | 说明 |
---|---|
-e 文件名 | 如果文件存在则为真 |
-r 文件名 | 如果文件存在且可读则为真 |
-w 文件名 | 如果文件存在且可写则为真 |
-x 文件名 | 如果文件存在且可执行则为真 |
-s 文件名 | 如果文件存在且至少有一个字符则为真 |
-d 文件名 | 如果文件存在且为目录则为真 |
-f 文件名 | 如果文件存在且为普通文件则为真 |
-c 文件名 | 如果文件存在且为字符型特殊文件则为真 |
-b 文件名 | 如果文件存在且为块特殊文件则为真 |
例 :
[ -e ./hello.txt ] && echo 'yes' || echo 'no' # 判断当前目录下是否存在 hello.txt 文件
[ -r ./hello.txt ] && echo 'yes' || echo 'no' # 判断当前目录下是否存在 hello.txt 文件并且是否可读
1.4.6 流程控制
if … elseif
语法:
1.
if [ 条件判断 ];then
成立的工作内容
fi
2.
if [ 条件判断1 ];then
1成立的工作内容
elif [ 条件判断2 ] ;then
2成立的工作内容
else
都不成立的工作内容
fi
例:
a=1
b=2
if [ $a == $b ];then
echo 'a和b相等';
fi
# 判断 a 和 b 是否相等,相等则输出
if [ $a == 1 ];then
echo 'a = 1'
elif [ $a == 2 ] ;then
echo 'a = 2'
else
echo '都不成立'
fi
# 判断 a 的值,并输出对应内容
case … esac
类似于 switch … case :
语法:
case 值 in
模式1)
程序段
;;
模式2)
程序段
;;
*)
程序段
;;
esac
例:
a=2
case $a in
1)
echo '值是1';
;;
2)
echo '值是2';
;;
*)
echo '未知值';
;;
esac
for … do … done
语法:
1.
for var in item1 item2 ...
do
程序段
done
2.
for (( 初始值;循环控制调节;变量变化 ))
do
程序段
done
例:
for a in 1 2 3 4 5 6
do
echo '我在:'$a
done
# 上面代码会将 in 后面的值依次给 a 使用
for (( i=0;i<6;i++ ))
do
echo 'i是'.$i
done
# 上述代码会根据条件重复执行 do 后面的代码
while 与 until
语法:
1.条件判断式成立则循环
while [ 条件判断式 ]
do
程序段
done
2.条件判断式不成立则循环
until [ 条件判断式 ]
do
程序段
done
例:
i=1
while [ $i -le 6 ]
do
i=$(( $i+1 ))
done
echo 'i的值是:'$i
# 如果变量 i 的值小于等于 100
until [ $i -gt 6 ]
do
i=$(( $i+1 ))
done
echo 'i的值是:'$i
# 如果 i 的值大于 6 则停止
输出重定向 ???
1.4.7 函数
1. 函数定义
shell 可以用户定义函数,在 shell 脚本中可以调用。shell 中函数的定义格式如下 :
语法:
[ function ] funname [()]
{
程序段
}
例:
first(){
echo '第一个函数'
}
first # 函数的调用
2. 函数参数
在调用函数的时候,同样可以给函数传递参数使用 :
first(){
echo "第一个参数: $1"
echo "第二个参数: $2"
echo "第三个参数: $3"
echo "第十个参数: ${10}"
echo "参数总数有 $# 个"
echo "作为一个字符串输出所有参数 $*"
}
first 1 2 3 4 5 6 7 8 9 10 11 12
说明 :
参数 | 说明 |
---|---|
$# | 传递到脚本或函数的参数个数 |
$* | 以一个单字符串显示所有向脚本传递的参数 |
$$ | 脚本运行的当前进程ID号 |
$! | 后台运行的最后一个进程的ID号 |
$@ | 与$*相同,但是使用时加引号,并在引号中返回每个参数。 |
$- | 显示Shell使用的当前选项,与set命令功能相同。 |
$? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。 |
3. 传递参数
我们可以在执行 Shell
脚本时,向脚本传递参数,脚本内获取参数的格式为:$n。n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数…,如下 :
例:
first(){
echo "第一个参数: $1" # 1
echo "第二个参数: $2" # 2
echo "第三个参数: $3" # 3
echo "参数总数有 $# 个" # 3
}
first $1 $2 $3
在运行脚本时需要传递参数 :
bash hello.sh 1 2 3
注意:并不是一定要传递给函数,只要定义了 $1,$2,… 等,就可以在执行脚本时传递参数使用。
4. 补充:输入输出重定向
我们在执行一个指令的时候,这个指令会经过处理将数据输出到屏幕上, 该数据可能是 标准输出
[正确执行的结果] 和 标准错误输出
[执行时产生的错误信息]。如果所有信息都输出到屏幕则会显得杂乱,我们可以通过重定向的功能分别写入其他文件中去。在使用该功能时,需要使用以下字符 :
字符 | 说明 |
---|---|
指令 > 文件 | 将输出重定向到文件 |
指令 < 文件 | 将输入重定向到文件 |
指令 >> 文件 | 将输出以追加的方式重定向到文件 |
例 :
# 输出重定向:改变数据从程序流向哪里。
echo '原神' > yuanshen.txt # 把 '原神' 写入到 yuanshen.txt 文件中,也可以是通过指令查询到的内容写入 如 who > users
echo 'www.yuanshen.com' >> yuanshen.txt # 追加网址到文件,注意是 >> 如果是 > 则会直接覆盖
# 输入重定向:改变数据从哪里流向程序。
wc -l < yuanshen.txt # 等价于 cat yuanshen.txt | wc -l