Linux CentOS笔记(听的尚硅谷的课)

VI/VIM 编辑器==(重要)==

网络配置==(重点)==

系统管理

service服务管理(了解,现在7已经不用了)

基本语法

service 服务名 start | stop | restart | status

守护进程 daemon

经验技巧

查看服务的方法:/etc/init.d/服务名 ,发现只有两个服务保留在service

image-20230525084943896

systemctl

基本语法

systemctl start | stop | restart | status 服务名

经验技巧

查看服务的方法:/usr/lib/systemd/system

image-20230525085042766

systemctl 设置后台服务的自启配置

系统运行级别

image-20230525090453236

CentOS7的运行级别简化为:

multi-user.target 等价于原运行级别 3(多用户有网,无图形界面)

graphical.target 等价于原运行级别 5(多用户有网,有图形界面)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KQrxnd5l-1686570839702)(img\image-20230525091142263.png)]

image-20230525091217058
init 5
init 3

老版本

chkconfig --list          # 查看开机自启动的情况
chkconfig network off     # 设置network的开机自启动
chkconfig --list 
chkconfig network on
chkconfig --level 3 network off   # 关闭network的运行级别3
chkconfig --list
chkconfig --level 3 network on    # 打开network的运行级别3

新版本

systemctl status NetworkManager
systemctl disable NetworkManager
systemctl status NetworkManager
systemctl enable NetworkManager
systemctl list-unit-files

防火墙

systemctl status firewalld
systemctl stop firewalld.service # 关掉防火墙
systemctl status firewalld
systemctl disable firewalld.service # 关掉防火墙的开机自启动
systemctl status firewalld
systemctl enable firewalld.service
systemctl start firewalld.service # 可以没有.service
systemctl start firewalld

关机重启命令

在 linux 领域内大多用在服务器上,很少遇到关机的操作。毕竟服务器上跑一个服务是永无止境的,除非特殊情况下,不得已才会关机。

7* 24小时都启动

shutdown           # 关机,默认一分钟后关机
shutdown -c        # 取消关机
shutdown now       # 立马关机
shutdown 3         # 3分钟后关机
shutdown 15:28     # 15:28关机

预读和延迟的写入

基本语法
sync # 功能描述:将数据由内存同步到硬盘中
halt # 功能描述:停机,关闭系统,但不断电
poweroff # 功能描述:关机,断电
reboot # 功能描述:就是重启,等同于shutdown -r now
shutdown[选项] 时间
image-20230525095201060
经验技巧

Linux 系统中为了提高磁盘的读写效率,对磁盘采取了 “预读迟写”操作方式。当用户保存文件时,Linux 核心并不一定立即将保存数据写入物理磁盘中,而是将数据保存在缓冲区中,等缓冲区满时再写入磁盘,这种方式可以极大的提高磁盘写入数据的效率。但是,也带来了安全隐患,如果数据还未写入磁盘时,系统掉电或者其他严重问题出现,则将导致数据丢失。使用 sync 指令可以立即将缓冲区的数据写入磁盘。

常用基本命令==(重要)==

Shell 可以看作是一个命令解释器,为我们提供了交互式的文本控制台界面。我们可以通过终端控制台来输入命令,由 shell 进行解释并最终交给内核执行。 本章就将分类介绍常用的基本 shell 命令。

ls -l /bin/ | grep sh

帮助命令

man获得帮助信息

基本语法

manual 手册

man[命令或配置文件]  # 功能描述:获得帮助信息
man ls # 按q退出
man cd # 进入的却是bash,cd是shell中的内置命令,一般都是比较基础的命令,exit也是,写在bash内部的
type cd # 判断命令类型
type ls
type useradd
type exit
type history # history 是显示所有之前执行的命令的记录
man -f cd 
man 1p cd
man 3 cd
man man
image-20230525105114618

显示说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zbQnGj0B-1686570839703)(img\image-20230525104027940.png)]

案例实操

查看 ls 命令的帮助信息

[root@hadoop101 ~]# man ls

help 获得 shell 内置命令的帮助信息

一部分基础功能的系统命令是直接内嵌在 shell 中的,系统加载启动之后会随着 shell 一起加载,常驻系统内存中。这部分命令被称为“内置(built-in)命令”;相应的其它命令被称为“外部命令”。

help cd
help ls # 这个不匹配,ls是外部命令
ls --help

常用快捷键

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wmmB1eAu-1686570839704)(img\image-20230525145042752.png)]

文件目录类

pwd显示当前工作目录的绝对路径

pwd:print working directory 打印工作目录

基本语法

pwd # 功能描述: 显示当前工作目录的绝对路径
pwd 
cd /etc/sysconfig
pwd
type pwd               # pwd 是内置命令
help pwd 
cd /root/桌面/         # 绝对路径
pwd
cd /root/视频/         # 绝对路径
cd ../视频/            # 相对路径
cd ../桌面/            # 相对路径
cd /root               
cd 桌面/               # 从/root 用相对路径的方式  cd   到桌面
cd -                  # 返回上次的文件夹
cd                    # 回到主目录 , root回到的是主目录 , atguigu用户 则是回到 /home/atguigu/
cd /home/atguigu/
su atguigu            # 切换用户为atguigu
pwd                   # 显示的是 /home/atguigu
exit                  # 退出,回到root

ls列出目录的内容

ls:list 列出目录内容

基本语法

ls[选项][目标或是文件]
ls
ls -a       # -a   all 表示所有的 , 这个显示出来的..是上一级目录的意思 , .是所在目录 
cd ..
cd .
cd ./桌面/
cd -
ls -l
ll             # ll 就是 ls -l 的缩写
type ll
ls -al         # ls -al 将所有(包括隐藏文件都将属性权限等数据全部展示)

image-20230525153658379

显示说明

每行列出的信息依次是: 文件类型与权限 链接数 文件属主 文件属组 文件大小用byte来表示 建立或最近修改的时间 名字

image-20230525154418003

cd 切换目录

cd:Change Directory 切换路径

基本语法

cd [参数]

参数说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P1gjpuMj-1686570839704)(img\image-20230525154617913.png)]

mkdir 创建一个新的目录

mkdir:Make directory 建立目录

基本语法

mkdir [选项] 要创建的目录
mkdir a
ls
mkdir /a
mkdir /b
ls               # 没有b,因为是在 / 目录下创建的
ls /
mkdir b c         # 创建目录b, c
ls
mkdir d/e/f       # mkdir: 无法创建目录"d/e/f": 没有那个文件或目录
mkdir d d/e d/e/f
ls d/
ls d/e
mkdir -p g/h/i      # 使用选项 -p 创建多层目录
ls
ls d
ls g/h/
rmdir a            # 删除目录
ls
rmdir b c          # 删除目录b, c
rmdir d g          # rmdir: 删除 "d" 失败: 目录非空; rmdir: 删除 "g" 失败: 目录非空
rmdir d/e/f/ d/e d/
ls
rmdir -p g/h/i/
ls

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b87PgmKV-1686570839705)(img\image-20230525155014791.png)]

rmdir 删除一个空的目录

rmdir:Remove directory 移除目录

基本语法

rmdir 要删除的空目录

touch 创建空文件

基本语法

touch 文件名称
ls 
touch hello
ls
cd /home/atguigu
touch hello2
ls
cd -
ls
touch /home/atguigu/hello3
ls
ls /home/atguigu/
vim hello4                     # vim和touch的区别是touch可以直接创建一个空的文件,但是vim不行,如果没有编辑,退出之后就还是什么都没有。
ls 
vim hello4                     # 但是如果我们退出 :wq! ,在退出之后就会有这个文件
ls

cp 复制文件或目录

基本语法

cp[选项] source dest              # 功能描述:复制source文件到dest
ls
cp initial-setup-ks.cfg ../home/atguigu/                 # 这里也可以用绝对路径   /home/atguigu/
ls /home/atguigu/
cp initial-setup-ks.cfg /home/atguigu/hello2             # 这里会问  cp:是否覆盖"/home/atguigu/hello2"? 回答y,hello2 的内容就被覆盖了。
ls /home/atguigu/
vim /home/atguigu/hello2
cp initial-setup-ks.cfg /home/atguigu/
\cp initial-setup-ks.cfg /home/atguigu/                 # 用  \cp 强制覆盖不提示,因为这个是直接使用的 \cp 是原生命令
\cp initial-setup-ks.cfg /home/atguigu/hello2           
type cp
cp --help                                               # cp 不是bash内置命令,要用 cp --help
type ls
ls
\ls                                                     # \ls也是ls的原生命令,ls是别名
alias                                                   # 别名的意思
ls
mkdir a
cp initial-setup-ks.cfg a/
ls
cp -r a/ /home/atguigu/                                # 递归的复制 a 整个文件夹到 /home/atguigu/ 目录下
cd /home/atguigu/a                                  
ls

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M73sC7cT-1686570839705)(img\image-20230525163615068.png)]

参数说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P0O2hICd-1686570839705)(img\image-20230525163638090.png)]

经验技巧

强制覆盖不提示的方法:\cp

这个是直接使用的 \cp 是原生命令

rm 删除文件或目录

基本语法

rm [选项] deleteFile                  # 功能描述:递归删除目录中所有内容
rm hello     # 会问:是否删除普通空文件“hello”?
ls 
type rm       # rm 是 'rm -i' 的别名
rm -f hello4   # 强制删除hello4,没有交互,直接删除
ls
rm a           # 无法删除"a" : 是一个目录
rm -r a        # 递归的删除a以及其中的所有 且有交互,会问是否删除
ls
cd /home/atguigu/
ls
rm -rf a/       # 直接递归删除a以及其中的所有 ,没有交互
ls 
rm -f ./*       # 删除当前目录中的所有但是没有删除当前目录
ls

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D19g1hdc-1686570839705)(img\image-20230531175558648.png)]

mv 移动文件与目录或重命名

基本语法

mv oldNameFile newNameFile                 # 功能描述:重命名
mv /temp/movefile /targetFolder            # 功能描述:移动文件
mv initial-setup-ks.cfg /home/atguigu/            # 移动initial-setup-ks.cfg 到 /home/atguigu/ 文件夹中
ls
cd /home/atguigu/ 
ls 
mv initial-setup-ks.cfg /root/                    # 把initial-setup-ks.cfg 移回到 /root/ 原来的位置
cd -
ls
mv initial-setup-ks.cfg /home/atguigu/1.cfg       # 把initial-setup-ks.cfg 移动到 /home/atguigu/ 并且重命名为 1.cfg
ls
ls /home/atguigu/
mv /home/atguigu/1.cfg initial-setup-ks.cfg       # 把 1.cfg 移回来且恢复名字为 initial-setup-ks.cfg
ls
mv anaconda-ks.cfg 2.cfg                          # 重命名anaconda-ks.cfg 为 2.cfg
ls
mv 2.cfg anaconda-ks.cfg                          # 恢复 anaconda-ks.cfg 的文件名
ls

cat 查看文件内容

查看文件内容,从第一行开始显示。

基本语法

cat [选项] 要查看的文件
ls
cat initial-setup-ks.cfg        # 查看initial-setup-ks.cfg 文件内容
cat -n initial-setup-ks.cfg     # 显示所有行的行号查看initial-setup-ks.cfg 文件内容

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K3xUFzTK-1686570839706)(img\image-20230531181041395.png)]

经验技巧

一般查看比较小的文件,一屏幕能显示全的。

more 文件内容分屏查看器

more 指令是一个基于 VI 编辑器的文本过滤器,它以全屏幕的方式按页显示文本文件的内容。more 指令中内置了若干快捷键,详见操作说明。

基本语法

more 要查看的文件
more initial-setup-ks.cfg       # 分页显示initial-setup-ks.cfg 文件内容

操作说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CQB4BhtI-1686570839706)(img\image-20230531181439900.png)]

less 分屏显示文件内容

less 指令用来分屏查看文件内容,它的功能与 more 指令类似,但是比 more 指令更加强大,支持各种显示终端。less 指令在显示文件内容时,并不是一次将整个文件加载之后才显示,而是根据显示需要加载内容,对于显示大型文件具有较高的效率。

基本语法

less 要查看的文件
ls
less xzhdx.txt          # less打开xzhdx.txt 动态加载

操作说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H3yrQ0og-1686570839706)(img\image-20230531181633304.png)]

经验技巧

用 SecureCRT 时 [pagedown] 和 [pageup] 可能会出现无法识别的问题。

echo

echo 输出内容到控制台

基本语法

echo [选项] [输出内容]
echo hello,world          # 控制台打印hello,world
echo hello world          # 控制台打印hello world
echo hello      world     # 控制台打印的还是hello world
echo "hello       world"    # 控制台打印的是hello       world
echo "hello \ world"        # 控制台打印hello \ world
echo "hello\nworld"         # 控制台打印hello\nworld
echo -e "hello\nworld"      
# 控制台打印的是:
# hello
# world

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lwm9ApHu-1686570839706)(img\image-20230531181911880.png)]

> 输出重定向 >> 追加

基本语法

ls -l > 文件                         # 功能描述:列表的内容写入文件 a.txt 中(覆盖写)
ls -al >> 文件                       # 功能描述:列表的内容追加到文件 aa.txt 的末尾
cat 文件 1 > 文件 2                   # 功能描述:将文件 1 的内容覆盖到文件 2
echo “内容” >> 文件
ls
ll
ll > info                        # 将ll的内容写入到info文件(且新建info)中
ls
cat info
ls > info                        # 将ls的内容写入到info文件中,是覆盖写入
cat info
echo "hello, linux" >> info      # 将hello, linux追加写入到info中
cat info
echo $                           # $+名字 表示环境变量, 按Tab显示所有的环境变量
echo $USER                       # 显示用户名
echo $PATH                       # 显示环境变量
echo $HOSTNAME                   # 显示主机名
echo $HOSTNAME >> info           # 将主机名追加写入到info中  

head 显示文件头部内容

head 用于显示文件的开头部分内容,默认情况下 head 指令显示文件的前 10 行内容。

基本语法

head 文件                   # 功能描述:查看文件头10行内容
head -n 5 文件              # 功能描述:查看文件头5行内容,5可以是任意行数
head xzhdx.txt               # 显示xzhdx.txt的前10行
head -n 20 xzhdx.txt         # 显示xzhdx.txt的前20行内容

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0jLvYL4U-1686570839706)(img\image-20230601144948275.png)]

tail 输出文件尾部内容

tail 用于输出文件中尾部的内容,默认情况下 tail 指令显示文件的后 10 行内容。

基本语法

tail 文件                                       # 功能描述:查看文件尾部10行内容
tail -n 5 文件                                  # 功能描述:查看文件尾部5行内容,5可以是任意行数
tail -f 文件                                    # 功能描述:实时追踪该文档的所有更新
tail xzhdx.txt                # 显示xzhdx.txt的尾部10行
tail -n 5 xzhdx.txt           # 显示xzhdx.txt的尾部5行
tail -f info                  # 实时追踪info文档的更新内容

# 在另一个连接中执行(观察tail -f 中的实时更行):
echo hello >> info            # 不用>,用>>因为用>是覆盖,会发生类似报错的。
echo welcomee >> info 
echo 1 >> info
echo 2 >> info
echo 3 >> info
vim info                      # 用vim不会让tail -f 的结果发生改变,因为tail是用文件索引号追踪的,vim会改变文件的索引号(inode),tail追踪的还是之前的那个索引号。本质上不是原来的文件了。
ls -i info                   # 可以显示info的索引号
vim info
ls -i info

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9IlQRb3U-1686570839707)(img\image-20230601151545457.png)]

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cfhvtBDp-1686570839707)(img\image-20230601145303644.png)]

ln 软链接

软链接也称为符号链接,类似于 windows 里的快捷方式,有自己的数据块,主要存放

了链接其他文件的路径。

基本语法

ln -s [原文件或目录] [软链接名]                         # 功能描述:给原文件创建一个软链接
ls 
cd /home/atguigu/
ln -s /root/info myInfo                        # 当前目录创建一个软链接myInfo链接到/root/info 
ls -l                                          # 前面是l就是一个链接
cd -
ll
cat info
cd -
cat myInfo
cd -
vim myInfo                                     # 在myInfo中修改,之后在root目录中cat info发现已修改
cd -
cat info
ls
mkdir folder
touch folder/file
ls folder/
cd -
ln -s /root/folder/ /home/atguigu/myFolder      # 在atguigu中创建软链接myFolder链接到/root/folder
ls
ll
cd -
cd folder/
ls
pwd
cd /home/atguigu/
ls
cd myFolder/
ls
pwd                                               # 这个显示的是/home/atguigu/myFolder   
pwd -P                                            # 用-p选项显示的是物理路径 /root/folder
cd /root/
cd -P /home/atguigu/myFolder/                     # cd也可以用-P换到物理路径的folder下
cd -
rm myInfo                                         # 链接文件也是文件,也是用rm删除
ls
cd -
ls                                                 # 发现只是把链接文件删除掉了,链接到的文件info还在,并没有被删掉
cd -
ls  
rm -rf myFolder                                   # -rf没有交互,且递归
ls
cd -
ls                                                 #发现这个也只是删除了链接文件,实际文件还在
cd -
ls
cd -
ln -s /root/folder/ myFolder                       # 恢复这个链接文件
ls
rm -rf myFolder/     
        # 发现这个是把myFolder(folder)里的文件递归删除,且没有交互,但是folder里的文件全部被删除了。
ls
cd -
ls 
cd folder/
ls
cd /home/atguigu/myFolder/
ls 
pwd -P
cd -
ls 
cd ..
ls 
rm -rf folder/                                      # 递归的删除了folder以及folder中的文件
cd /home/atguigu/myFolder/
cd /home/atguigu/
ls                                                  # 这里的myFolder标为了红的
ll                                                  # 显示myFolder的链接目标被删除的特殊标识
rm myFolder
ls

经验技巧

删除软链接: rm -rf 软链接名,而不是 rm -rf 软链接名/

如果使用 rm -rf 软链接名/ 删除,会把软链接对应的真实目录下内容删掉

查询:通过 ll 就可以查看,列表属性第 1 位是 l,尾部会有位置指向

硬链接(去掉-s)

ln [原文件或目录] [软链接名]

history 查看已经执行过历史命令

基本语法

history                                                # 功能描述:查看已经执行过历史命令
history                # 所有历史命令
history 10             # 过去刚刚输入过的10条命令
!1156                 # 显示第1156条命令并且重新调用
history -c             # 清空命令

时间日期类

基本语法

date [OPTION]... [+FORMAT]

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5phXfTmZ-1686570839707)(img\image-20230601162342297.png)]

参数说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EiXdJUKT-1686570839707)(img\image-20230601162429307.png)]

date 显示当前时间

基本语法

date                                       # 功能描述:显示当前时间
date +%Y                                   # 功能描述:显示当前年份
date +%m                                   # 功能描述:显示当前月份
date +%d                                   # 功能描述:显示当前是哪一天
date "+%Y-%m-%d %H:%M:%S"                  # 功能描述:显示年月日时分秒
date                        # 获取当前的使时间日期
date +%Y                    # 获取当前的年
date +%y                    # 当前年的后两位
date +%m                    # 当前的月份
date +%d                    # 当前的日
date +%Y-%m-%d-%H:%M:%S     # 按格式输出2023-06-01-16:53:37
date +%Y-%m-%d %H:%M:%S     # 用空格就不行了:date: 额外的操作数 "%H:%M:%S",要加""
date "+%Y-%m-%d %H:%M:%S"    # 输出2023-06-01 16:55:34
date +%S                     # 获取秒
date +%s                     # 获取时间戳

date 显示非当前时间

基本语法

date -d '1 days ago'                              # 功能描述:显示前一天时间
date -d '-1 days ago'                             # 功能描述:显示明天时间
date -d "1 days ago"                 # 一天前的时间日期
date -d "-1 days ago"                # 一天后的时间日期
date -d "-1 hours ago"               # 一小时后的时间日期

date 设置系统时间

基本语法

date -s 字符串时间
date -s "2017-06-19 20:52:18"             # 修改当前时间为2017-06-19 20:52:18
date
date -s "2027-06-19 20:52:18"             # 修改当前时间也可以是未来时间
date
ntpdate 210.72.145.44                     # 修改当前是时间为ntpdate服务器时间,210.72.145.44是中国国家授时中心

cal 查看日历

基本语法

cal [选项]                                # 功能描述:不加选项,显示本月日历
cal                                  # 显示当前所在月份的日历
cal -3                               # 显示当前所在月及前一月和后一月的日历
cal -m                               # 把周一放在第一列显示日历
cal 2023                             # 显示2023年的全年的日历
cal -y                               # 显示当前年的全年的日历

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SjuDc5ap-1686570839708)(img\image-20230601163146856.png)]

用户管理命令

Linux是多用户多任务的分时管理系统

useradd 添加新用户

基本语法

useradd 用户名                                  # 功能描述:添加新用户
useradd -g 组名 用户名                           # 功能描述:添加新用户到某个组
cd /home/
ls
useradd tony                              # 添加用户tony
ls
useradd -d /home/dave david               # -d就是用户主目录叫dave,但是用户名字还是david,登录时还是显示的david   也可以用修改文件夹名的方式修改这个
ls

passwd设置用户密码

基本语法

passwd 用户名                                 # 功能描述:设置用户密码
passwd tony                               # 用户没有密码时不安全的,为tony设置密码
passwd david

id查看用户是否存在

基本语法

id 用户名
id tony                                   # 查看tony这个用户存不存在
id david
id dave                                   # 没有这个用户

cat /etc/passwd 查看创建了哪些用户

cat /etc/passwd                            # 查看所有创建了的用户
less /etc/passwd                            # 分页查看所有创建了的用户

su切换用户

su: swith user 切换用户

基本语法

su 用户名称                       # 功能描述:切换用户,只能获得用户的执行权限,不能获得环境变量
su - 用户名称                     # 功能描述:切换到用户并获得该用户的环境变量及执行权限
su atguigu                      # 切换用户为atguigu
ls 
cd ~
pwd
su tony                         # 切换用户为tony
ls                              # 这里没有权限,因为tony和atguigu是同级用户。
cd ~
pwd
su root
exit
ls
pwd
ls ../tony/
exit                             # 返回到了root用户,root用户可以查看其他用户的目录
ls
ls tony/
ls atguigu/

who 查看登录用户信息

基本语法

whoami                                               # 功能描述:显示自身用户名称
who am i                                             # 功能描述:显示登录用户的用户名以及登陆时间
who am i                                  # 显示登录用户的用户名及登录时间
whoami                                    # 只显示用户名
su david                                  # 切换到david用户下
whoami                                    # 只显示用户名 david
who am i                                  # 显示的是当前的登录用户  root    pts/0    2023-06-1 19:27...
su tony 
who am i
whoami

sudo 设置普通用户具有 root 权限

添加 atguigu 用户,并对其设置密码。

useradd atguigu
passwd atguigu

修改配置文件

vi /etc/sudoers

修改 /etc/sudoers 文件,找到下面一行(91 行),在 root 下面添加一行,如下所示:

## Allow root to run any commands anywhere
root ALL=(ALL) ALL
atguigu ALL=(ALL) ALL

或者配置成采用 sudo 命令时,不需要输入密码

## Allow root to run any commands anywhere
root ALL=(ALL) ALL
atguigu ALL=(ALL) NOPASSWD:ALL

修改完毕,现在可以用 atguigu 帐号登录,然后用命令 sudo ,即可获得 root 权限进行操作。

su tony
ls
sudo ls                                   # 临时普通用户sudo的权限,但是显示:  tony 不在 sudoers 文件中。此事将被报告。
exit
vim /etc/sudoers                          # sudoers 是root才能修改且要强制修改才能修改
su tony
ls
sudo ls
exit

userdel 删除用户

基本语法

userdel 用户名                     # 功能描述:删除用户但保存用户主目录
userdel -r 用户名                  # 功能描述:用户和用户主目录,都删除
userdel tony                              # 删除tony用户
cd /home
ls
id tony
cat /etc/passwd
ls
rm -rf tony/
userdel -r david
ls
id david
cat /etc/passwd
useradd tony
useradd -d /home/dave david
ls

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WdSl6ins-1686570839708)(img\image-20230601175357618.png)]

usermod 修改用户

基本语法

usermod -g 用户组 用户名

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jOg29USx-1686570839708)(img\image-20230601180155783.png)]

用户组管理命令

每个用户都有一个用户组,系统可以对一个用户组中的所有用户进行集中管理。不同Linux 系统对用户组的规定有所不同,

如Linux下的用户属于与它同名的用户组,这个用户组在创建用户时同时创建。

用户组的管理涉及用户组的添加、删除和修改。组的增加、删除和修改实际上就是对/etc/group文件的更新。

vim /etc/sudoers
su atguigu
ls
sudo ls                                   # sudoers里没有atguigu,没有给atguigu权限,但是atguigu可以看root的ls(引入组)
vim /etc/sudoers                          # 里面确实没有atguigu
sudo vim /etc/sudoers
id atguigu
id root
id tony
id david
sudo cat /etc/group
exit
groupadd meifa                              # 新增meifa组
cat /etc/group                              # 查看组
usermod -g meifa tony                       # 将tony修改,将他改到meifa组中
usermod -g meifa david                      # 将david修改,将他改到meifa组中。
id tony                                     # 查看该tony信息
id david
groupmod -n haircut meifa                   # 修改组meifa的组名该为haircut
id tony
id david
cat /etc/group
groupdel tony                                # 删除tony组(tony组是tony用户的默认组)
groupdel david                               
cat /etc/group                               # wheel组中添加了atguigu用户,wheel拥有ALL权限

groupadd 新增组

基本语法

groupadd 组名

groupdel 删除组

基本语法

groupdel 组名

groupmod 修改组

基本语法

groupmod -n 新组名 老组名

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-phlkj4mM-1686570839708)(img\image-20230601203143103.png)]

cat /etc/group 查看创建了哪些组

基本操作

cat /etc/group

文件权限类

ls
ls /
ls /etc
ll                                                    # d开头就是目录 , c字符设别 , b块设备文件
ll /dev
ls -l
cd ..
ll
cd -
ls -al
cp ./anaconda-ks.cfg /home/atguigu/
cp ./initial-setup-ks.cfg /home/atguigu/
su atguigu
cd ~
ls
ll
cat initial-setup-ks.cfg
cat anaconda-ks.cfg                                  # 权限不够
ll                                                   # 第二个字段是硬链接数

文件属性

Linux系统是一种典型的多用户系统,不同的用户处于不同的地位,拥有不同的权限。为了保护系统的安全性,Linux系统对不同的用户访问同一文件(包括目录文件)的权限做了不同的规定。在Linux中我们可以使用 ll 或者 ls -l 命令来显示一个文件的属性以及文件所属的用户和组。

从左到右的 10 个字符表示,如图 7-1 所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kEwrzeWo-1686570839708)(img\image-20230607171848165.png)]

如果没有权限,就会出现减号[ - ]而已。从左至右用0-9这些数字来表示:

  1. 0 首位表示类型

    在Linux中第一个字符代表这个文件是目录、文件或链接文件等等

    - 代表文件

    d 代表目录

    l 链接文档(link file);

  2. 第1-3位确定属主(该文件的所有者)拥有该文件的权限。—User

  3. 第4-6位确定属组(所有者的同组用户)拥有该文件的权限,—Group

  4. 第7-9位确定其他用户拥有该文件的权限 —Other

rwx 作用文件和目录的不同解释

  1. 作用到文件:

    [ r ]代表可读(read): 可以读取,查看

    [ w ]代表可写(write): 可以修改,但是不代表可以删除该文件,删除一个文件的前提条件是对该文件所在的目录有写权限(因为删除文件相当于修改目录),才能删除该文件.

    [ x ]代表可执行(execute):可以被系统执行

  2. 作用到目录:

    [ r ]代表可读(read): 可以读取,ls查看目录内容

    [ w ]代表可写(write): 可以修改,目录内创建+删除+重命名目录

    [ x ]代表可执行(execute):可以进入该目录

文件基本属性介绍,如图7-2所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mfTOrqB1-1686570839709)(img\image-20230607172846476.png)]

  1. 如果查看到是文件:链接数指的是硬链接个数。

  2. 如果查看的是文件夹:链接数指的是子文件夹个数。

chmod 改变权限

基本语法

如图 7-3 所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cQcUccju-1686570839709)(img\image-20230607173119690.png)]

# 第一种方式变更权限

chmod [{ugoa}{+-=}{rwx}] 文件或目录

# 第二种方式变更权限

chmod [mode=421] [文件或目录]
cd /home/atguigu/                                  # root用户下
ls
ll
chmod u+x initial-setup-ks.cfg                       # 修改initial-setup-ks.cfg的属主的权限增加可执行
ll 
chmod g+w initial-setup-ks.cfg                       # 修改initial-setup-ks.cfg的属组的权限增加可写权限
ll
chmod a=rw initial-setup-ks.cfg                      # 修改initial-setup-ks.cfg的所有的权限为可读可写不可执行的权限
ll
chmod 777 initial-setup-ks.cfg
ll
chmod 644 anaconda-ks.cfg
ll
su atguigu
cat anaconda-ks.cfg
chmod -R 777 xiyou/                                  # -R 修改整个文件夹里面的所有文件的所有者、所属组、其他用户都具有可读可写可执行权限。
exit

经验技巧

u:所有者 g:所有组 o:其他人 a:所有人(u、g、o 的总和)

r=4 w=2 x=1 rwx=4+2+1=7

实则就是采用了二进制表示 用一个3位的二进制数表示这3个权限的拥有情况,例如:rwx对应111=7,r-x对应101=5, rw-对应110=6。

chown 改变所有者

基本语法

chown [选项] [最终用户] [文件或目录]                       # 功能描述:改变文件或者目录的所有者
ll
chown atguigu initial-setup-ks.cfg                    # 修改initial-setup-ks.cfg文件属主为atguigu。
ll
chmod 700 initial-setup-ks.cfg
ll
cat initial-setup-ks.cfg
su atguigu
cat initial-setup-ks.cfg                 # root 和 atguigu 都可以查看,root是超级管理员,atguigu是所有者
ll

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UjMjq61w-1686570839709)(img\image-20230607173527674.png)]

chgrp 改变所属组

基本语法

chgrp [最终用户组] [文件或目录]                 # 功能描述:改变文件或者目录的所属组
chgrp haircat initial-setup-ks.cfg                   # 不允许,因为是在改所属组,需要超级管理员权限。
exit
chgrp haircat initial-setup-ks.cfg                   # 修改成功

综合应用案例

groupadd bigdata
groupadd testing
cat /etc/group
useradd -g bigdata xiaoming
id xiaoming
useradd -g bigdata xiaoliang
id xiaoliang
useradd -g testing xiaohong
useradd -g testing xiaolan
id xiaohong
id xiaolan
cd /home/
ls
su xiaoming
cd ~
ls
pwd
vim import_code
ll
exit
su xiaoliang
cd ~
cd ../xiaoming/                           # 权限不够
exit
ls
ll
chmod g+x xiaoming/
ll
su xiaoliang
cd xiaoming/
ll                                         # 权限不够
exit
chmod g+r xiaoming/
ll
su xiaoliang
cd xiaoming
ll
cat import_code
vim import_code
vim import_code
exit
su xiaoming
cd ~
ll
chmod g+w import_code
exit
su xiaoliang
cd xiaoming/
vim import_code
ll
exit
su xiaohong
ll
cd xiaoming                           # 没有权限
exit
chmod 755 xiaoming
ll
su xiaohong
cd xiaoming      
ll
cat import_code
vim import_code
exit
usermod -g bigdata xiaolan
id xiaolan
su xiaolan
cd xiaoming
ls
vim import_code
cat import_code

搜索查找类

find 查找文件或者目录

find 指令将从指定目录向下递归地遍历其各个子目录,将满足条件的文件显示在终端。

基本语法

find [搜索范围] [选项]
ls 
find -name info                           # 找所有的info文件
touch 公共/info                          
find -name info                           # 找所有的info文件,发现touch创建的也被find到了
find /root -name info                     # 找 /root 目录下的所有的info文件
find /root/公共 -name info
find /root -name "*.cfg"
find /home -user tony                     # 找 /home 目录下的所有tony的文件
ls
ll
ls -lh                                     # 更加人性化的展示文件的大小
find /root -size +10M                     # 找 /root 目录下的size超过10M的文件
find /root -size + 2M   

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FEj3ayCl-1686570839709)(img\image-20230607184829726.png)]

locate 快速定位文件路径

locate 指令利用事先建立的系统中所有文件名称及路径的 locate 数据库实现快速定位给定的文件。Locate 指令无需遍历整个文件系统,查询速度较快。为了保证查询结果的准确度,管理员必须定期更新 locate 时刻(默认一天一更)。

(find是在硬盘中找)

基本语法

locate 搜索文件
updatedb                                   # 更新locate数据库
locate tmp                                 # 查找所有含有tmp的文件
locate xzhdx
which ls                                   # 查找命令
which locate
which which 
whereis locate

经验技巧

由于 locate 指令基于数据库进行查询,所以第一次运行前,必须使用 updatedb 指令创建 locate 数据库。

grep 过滤查找及“|”管道符

管道符,“|”,表示将前一个命令的处理结果输出传递给后面的命令处理

基本语法

grep 选项 查找内容 源文件
ls
grep -n boot initial-setup-ks.cfg          # 查找内容有boot的所有位置
ls
ls | grep .cfg
cat info
wc info                                    # word count单词统计

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lf4hDL9O-1686570839709)(img\image-20230607185233428.png)]

压缩和解压类

gzip/gunzip 压缩

基本语法

gzip 文件                                          # 功能描述:压缩文件,只能将文件压缩为*.gz 文件

gunzip 文件.gz                                     # 功能描述:解压缩文件命令
ls
gzip xzhdz.txt                           # 压缩xzhdz.txt文件
ls
ls -lh                                   # 以人类可读的方式显示当前目录中的文件和目录大小
gunzip xzhdx.txt.gz
ls
ls -lh

经验技巧

(1)只能压缩文件不能压缩目录

(2)不保留原来的文件

(3)同时多个文件会产生多个压缩包

zip/unzip 压缩

基本语法

zip [选项] XXX.zip 将要压缩的内容                                         # 功能描述:压缩文件和目录的命令
unzip [选项] XXX.zip                                                    # 功能描述:解压缩文件
zip -r myroot.zip /root                  # 把/root直接压缩为myroot.zip,压缩+重命名
ls 
ls -lh
unzip -d /tmp myroot.zip                 # 解压myroot.zip到/tmp目录下
cd /tmp
ls

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ohMAEzBx-1686570839710)(img\image-20230607185833928.png)]

经验技巧

zip 压缩命令在windows/linux都通用,可以压缩目录且保留源文件。

tar 打包

基本语法

tar [选项] XXX.tar.gz 将要打包进去的内容                                        # 功能描述:打包目录,压缩后的文件格式.tar.gz
cd ~
ls
tar -zcvf temp.tar.gz initial-setup-ks.cfg xzhdx.txt info 公共/                       # 将initial-setup-ks.cfg xzhdx.txt info 公共/打包压缩为temp.tar.gz且显示详细信息
ls
ls -lh
tar -zxvf temp.tar.gz -C /tmp              # 将temp.tar.gz解压到/tmp目录下
cd /tmp/
ls

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ztZCCEed-1686570839710)(img\image-20230607190058399.png)]

磁盘查看和分区类

du 查看文件和目录占用的磁盘空间

du: disk usage 磁盘占用情况

基本语法

du 目录/文件                                          # 功能描述:显示目录下每个子目录的磁盘使用情况
ls
ll
yum install tree                                 # 下载tree
tree ./                                           # 树结构查看 ./ 目录的所有
ls -lh
ls -lh /
du                              # 把所有目录,所有文件夹下的,隐藏文件下的全部显示占据空间大小。
du -ah                          # 把所有目录显示占据空间大小且用人类易于看懂的方式显示
du -ach                         # 用的-c,但是发现没有简化多少
du -sh                          # 用-s只统计当前的总和
du --max-depth=1 -ah            # 显示最大深度为1, 就是只显示一层,且显示占据空间大小用人类易于看懂的方式显示。

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8oFWwC8h-1686570839710)(img\image-20230607190320202.png)]

df 查看磁盘空间使用情况

df: disk free 空余磁盘

基本语法

df 选项                      # 功能描述:列出文件系统的整体磁盘使用量,检查文件系统的磁盘空间占用情况
du -sh
du -sh /                        # 根目录的大小,只是文件占用的,不是磁盘的空间
df -h                           # 列出文件系统的整体磁盘使用量,检查文件系统的磁盘空间占用情况,用人易于看懂的方式显示 
free -h                         # 当前内存的使用情况

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lxElFUCN-1686570839710)(img\image-20230607190454581.png)]

lsblk 查看设备挂载情况

基本语法

lsblk                                  # 功能描述:查看设备挂载情况 ls block
lsblk                                   # 查看设备挂载情况
ls /dev/ | grep sr0    
ll /dev/ | grep sr0

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RnyHAS5l-1686570839710)(img\image-20230607190634276.png)]

mount/umount 挂载/卸载

对于Linux用户来讲,不论有几个分区,分别分给哪一个目录使用,它总归就是一个根目录、一个独立且唯一的文件结构。

Linux中每个分区都是用来组成整个文件系统的一部分,它在用一种叫做“挂载”的处理方法,它整个文件系统中包含了一整套的文件和目录,并将一个分区和一个目录联系起来,要载入的那个分区将使它的存储空间在这个目录下获得。

挂载前准备(必须要有光盘或者已经连接镜像文件),如图 7-5, 7-6所示

image-20230607190850634 image-20230607190920218

基本语法

mount [-t vfstype] [-o options] device dir                                # 功能描述:挂载设备
umount 设备文件名或挂载点                                                    # 功能描述:卸载设备
lsblk                                    # 查看CentOS 7 x86_64 的挂载点
ls /run/media/root/CentOS\ 7\ x86_64/
lsblk                                     # 弹出光驱后就没有这个了
ls /run/media/root/CentOS\ 7\ x86_64/      # 无法访问,没有那个文件或目录
mkdir /mnt/cdrom
mount /dev/cdrom /mnt/cdrom                # 找不到媒体,要重新登录,连接上光盘
lsblk
mount /dev/cdrom /mnt/cdrom                # 写保护,将以只读方式挂载
lsblk
ls /mnt/cdrom/
umount /dev/cdrom
lsblk
ls /mnt/cdrom/
vim /etc/fstab                             # fstab 设置开机自动挂载 , UUID写/dev/cdrom,后面挂载点写 /mnt/cdrom ,文件类型iso9660,配置默认配置defaults ,后面0 0

参数说明

image-20230607191019516

设置开机自动挂载

vi /etc/fstab

添加红框中内容,保存退出。

如图7-7所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mYJhKw3B-1686570839711)(img\image-20230607191304668.png)]

fdisk 分区

基本语法

fdisk -l                                       # 功能描述:查看磁盘分区详情
fdisk 硬盘设备名                                 # 功能描述:对新增硬盘进行分区操作
fdisk -l                                    # 查看磁盘分区情况
fdisk -l                                   # 新添加的硬盘没有显示
lsblk -l                                   # 新添加的同样也没有被查询到,需要重启
reboot
lsblk                                       # 查询到了sdb磁盘
fdisk -l
fdisk /dev/sdb                             # m    p    n{p(Partition type)   分区号(默认)    起始扇区(默认)    size(默认即是最大的扇区)}    p    w
fdisk -l                                   # 发现添加了新的分区
lsblk                                      # 也可以查看到
lsblk -f                                  # 没有文件信息,UUID和挂载点
mkfs -t xfs /dev/sdb1                     # 对它作一个格式化
lsblk -f                                    # 有UUID信息,没有挂载点,进行挂载
mount /dev/sdb1 /home/atguigu/            # 将sdb挂载到atguigu下给atguigu用户使用
lsblk -f
df -h
ls
ll
ll -h
cp myroot.zip /home/atguigu/
df -h                                     # sdb1的空间被占用了
umount /home/atguigu                      # 卸载
df -h                                     # 没有sdb1
ll /home/atguigu/                          # 只有之前的两个配置文件,没有刚刚存放的myroot.zip了

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9bujFOTd-1686570839711)(img\image-20230607191503131.png)]

经验技巧

该命令必须在 root 用户下才能使用

功能说明

  1. Linux 分区

    Device:分区序列

    Boot:引导

    Start:从X磁柱开始

    End:到Y磁柱结束

    Blocks:容量

    Id:分区类型ID

    System:分区类型

  2. 分区操作按键说明

    m:显示命令列表

    p:显示当前磁盘分区

    n:新增分区

    w:写入分区信息并退出

    q:不保存分区信息直接退出

进程管理类

进程是正在执行的一个程序或命令,每一个进程都是一个运行的实体,都有自己的地址空间,并占用一定的系统资源。

ps 查看当前系统进程状态

ps:process status 进程状态

基本语法

ps aux | grep xxx                               # 功能描述:查看系统中所有进程
ps -ef | grep xxx                               # 功能描述:可以查看子父进程之间的关系
ls /usr/lib/systemd/system
ls /usr/lib/systemd/system | grep d.service
ps                                            # 只显示当前用户和当前控制台的进程
ps aux
ps aux | less
ps -ef
ps -ef | less                          # PPID是父进程的ID
ps aux |  less
ps -ef |  less                         # PPID 0是系统进程idu
ps -ef | grep sshd                        # 查看sshd相关的进程 ,和远程登录相关的
systemctl status sshd                      # 查看sshd进程的状态信息
ps -ef | grep sshd                        # 再打开一个xshell的远程连接后,查看远程登录相关的进程,发现多了一个sshd: root@pts/2
ps -ef | grep sshd                          # 再打开一个xshell的用atguigu用户的身份登录的远程连接,查看远程登录相关的进程,发现多了两个sshd的进程 sshd: atguigu...     atguigu[priv]是权限分离

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DJaovwYw-1686570839711)(img\image-20230609092335444.png)]

功能说明

  1. ps aux 显示信息说明

    USER:该进程是由哪个用户产生的

    PID:进程的 ID 号

    %CPU:该进程占用 CPU 资源的百分比,占用越高,进程越耗费资源;

    %MEM:该进程占用物理内存的百分比,占用越高,进程越耗费资源;

    VSZ:该进程占用虚拟内存的大小,单位 KB;

    RSS:该进程占用实际物理内存的大小,单位 KB;

    TTY:该进程是在哪个终端中运行的。对于 CentOS 来说,tty1 是图形化终端,tty2-tty6 是本地的字符界面终端。pts/0-255 代表虚拟终端。

    STAT:进程状态。常见的状态有:R:运行状态、S:睡眠状态、T:暂停状态、Z:僵尸状态、s:包含子进程、l:多线程、+:前台显示、< : 表示当前进程优先级很高、N : 表示当前进程优先级比较低

    START:该进程的启动时间

    TIME:该进程占用 CPU 的运算时间,注意不是系统时间

    COMMAND:产生此进程的命令名

  2. ps -ef 显示信息说明

    UID:用户 ID

    PID:进程 ID

    PPID:父进程 ID

    C:CPU 用于计算执行优先级的因子。数值越大,表明进程是 CPU 密集型运算,执行优先级会降低;数值越小,表明进程是 I/O 密集型运算,执行优先级会提高

    STIME:进程启动的时间

    TTY:完整的终端名称

    TIME:CPU 时间

    CMD:启动进程所用的命令和参数

经验技巧

如果想查看进程的 CPU 占用率和内存占用率,可以使用 aux;

如果想查看进程的父进程 ID 可以使用 ef;

kill 终止进程

基本语法

kill [选项] 进程号(PID)                               # 功能描述:通过进程号杀死进程
killall 进程名称                                     # 功能描述:通过进程名称杀死进程,也支持通配符,这在系统因负载过大而变得很慢时很有用
kill 3535                                   # 终止进程3535
ps -ef | grep sshd
kill 3481
ps -ef | grep sshd                         # 再重新远程登录一个root后再,ps
kill 3195                                   # kill掉自己
kill 1130                                   # kill掉了守护进程
ps -ef | grep sshd
ls                                         # 当前登录的还是可以运行的,但是如果要打开一个新的连接,是打不开的,因为sshd服务已经关闭
systemctl status sshd
systemctl start sshd                       # 启动sshd后,再打开一个新的连接就可以打开了
ps -ef | grep 3746                        # 查看3746相关进程,3746是sshd的父进程,3746就是终端界面进程bash
ps -ef | grep bash
kill 3273                                  # kill当前打开的的终端界面
ps -ef | grep bash                         # 发现没有kill掉,因为当前终端在使用,在运行,系统不认同kill这条指令
kill -l                                    # 查看当前系统的信号值
kill -9 3273                               # 强制关掉这个终端页面
ps -ef | grep bash                         # 确实被关掉了
kill -9 3818
ps -ef | grep bash
kill 3746
kill -9 3746
ps -ef | grep sshd
killall sshd

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fnj7o3Rr-1686570839711)(img\image-20230609093352994.png)]

pstree 查看进程树

基本语法

pstree [选项]
yum install pstree                         # 如果第一次使用没有安装pstree,执行这个安装一下
pstree | less                              # 分页显示pstree
pstree -p | less                            # 分页显示进程的PID
pstree -u | less                            # 分页显示用户相关的进程信息

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p5f05PCG-1686570839711)(img\image-20230609093650905.png)]

top 实时监控系统进程状态

基本命令

top [选项]
top                                        # 可以按 P(shift + p)、M(shift + m)、N(shift + n) 对查询出的进程结果进行排序。
top -d
top -i
top -p 4910 
top -i
top -p 2655
top -d 1                                   # 想要监控某个固定用户,可以按u,提示Which user (blank for all) ,可以输一个atguigu看 ; 可以按k,提示PID to signal/kill [default pid = 4936] ,比如输入4950,就会kill这个进程,然后它还问要求输入给它发送的信号Send pid 4950 signal [15/sigterm](就是之前kill -l 能够发送的所有信号), 这里可以发信号名称也可以发数字这里输入9发送的信号就是9; 

选项说明

image-20230609093852431

操作说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PERb3ifo-1686570839712)(img\image-20230609094043345.png)]

查询结果字段解释

第一行信息为任务队列信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MBjCQ2XT-1686570839712)(img\image-20230609094151305.png)]

第二行为进程信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nKoCdXj7-1686570839712)(img\image-20230609094720025.png)]

第三行为 CPU 信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X1XK7N13-1686570839712)(img\image-20230609094847204.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FZjWuZ85-1686570839712)(img\image-20230609094958158.png)]

第四行为物理内存信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JAegnQcf-1686570839713)(img\image-20230609095042133.png)]

第五行为交换分区(swap)信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PoKXDAaS-1686570839713)(img\image-20230609095206615.png)]

执行上述命令后,可以按 P(shift + p)、M(shift + m)、N(shift + n) 对查询出的进程结果进行排序。

案例实操

top -d 1
top -i
top -p 2575

netstat 显示网络状态和端口占用信息

基本语法

netstat -anp | grep 进程号                            # 功能描述:查看该进程网络信息
netstat –nlp | grep 端口号                            # 功能描述:查看网络端口号占用情况
ifconfig                                   # 查看当前所有的网络连接
ping 192.168.111.1
netstat -anp                               # 查看该进程网络信息
netstat -anp | less                         # 查看该进程网络信息进行分页展示
netstat -anp | less                        # 这个也是进程的快照,新建atguigu用户的连接,然后再netstat,可以看到atguigu就存在了。

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vYkDzxYK-1686570839713)(img\image-20230609095502137.png)]

crontab 系统定时任务

crontab 服务管理

重新启动 crond 服务

systemctl restart crond                     # crond是crontab的守护进程
systemctl status crond                     # 看到crond进程的是开启的

crontab 定时任务设置

基本语法

crontab [选项]
crontab -l                                 # crontab使用的话必须后面跟上一些选项,-l列举当前的所有定时任务, no crontab for root ,发现没有
crontab -e                                  # 写入 */1 * * * * echo "hello, world" >> /root/hello
ls
ls
ls
ls
cat hello
tail -f hello
crontab -l
crontab -r
crontab -l

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YEYLSLP2-1686570839713)(img\image-20230609101738626.png)]

参数说明

crontab -e
  1. 进入 crontab 编辑界面。会打开 vim 编辑你的工作。

    * * * * * 执行的任务

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-osqn7ljF-1686570839713)(img\image-20230609104139545.png)]

  2. 特殊符号

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N0eOvLQR-1686570839714)(img\image-20230609104402045.png)]

  3. 特定时间执行命令

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q52feBPZ-1686570839714)(img\image-20230609104450469.png)]

案例实操

  1. 每隔 1 分钟,向 /root/bailongma.txt 文件中添加一个 11 的数字

    */1 * * * * /bin/echo ”11” >> /root/bailongma.txt
    

软件包管理

RPM

RPM 概述

RPM(RedHat Package Manager),RedHat软件包管理工具,类似windows里面的setup.exe是Linux这系列操作系统里面的打包安装工具,它虽然是RedHat的标志,但理念是通用的。

RPM包的名称格式

Apache-1.3.23-11.i386.rpm

  • “apache” 软件名称
  • “1.3.23-11”软件的版本号,主版本和此版本
  • “i386”是软件所运行的硬件平台,Intel 32位处理器的统称
  • “rpm”文件扩展名,代表RPM包

RPM 查询命令 (rpm -qa)

基本语法

rpm -qa                               # 功能描述:查询所安装的所有 rpm 软件包
rpm -qa                                    # 查询所安装的所有 rpm 软件包
rpm -qa | grep firefox                      # 查询firefox的软件包
rpm -qi firefox                            # -qi information ,就是查询展示详细信息

经验技巧

由于软件包比较多,一般都会采取过滤。rpm -qa | grep rpm软件包

RPM 卸载命令 (rpm -e)

基本语法

  1. rpm -e RPM软件包
    
  2. rpm -e --nodeps 软件包
    
rpm -e firefox                              # 卸载firefox
rpm -qi firefox                            # 未安装软件包 firefox

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g5sqOrR4-1686570839714)(img\image-20230609110231639.png)]

RPM安装命令 (rpm -ivh)

基本语法

rpm -ivh RPM 包全名
lsblk
cd /run/media/root/CentOS\ 7\ x86_64/
ls
cd Packages/
ls
ls | grep firefox
rpm -ivh firefox-68.10.0-1.el7.centos.x86_64.rpm
rpm -qi firefox

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FunYZ5us-1686570839714)(img\image-20230609110529727.png)]

YUM 仓库配置

YUM 概述

YUM(全称为 Yellow dog Updater, Modified)是一个在 Fedora 和 RedHat 以及 CentOS中的 Shell 前端软件包管理器。基于 RPM 包管理,能够从指定的服务器自动下载 RPM 包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖的软件包,无须繁琐地一次次下载、安装,如图 8-1 所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ui2wRAvT-1686570839714)(img\image-20230609110826772.png)]

YUM 的常用命令

基本语法

yum [选项] [参数]
yum list
yum list | grep firefox
yum remove firefox
yum list | grep firefox
rpm -q firefox
yum -y install firefox
yum list | grep firefox
rpm -q firefox

选项说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-djlai5ku-1686570839714)(img\image-20230609162022614.png)]

参数说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RGGYKU04-1686570839715)(img\image-20230609162113771.png)]

修改网络 YUM 源

默认的系统 YUM 源,需要连接国外 apache 网站,网速比较慢,可以修改关联的网络YUM 源为国内镜像的网站,比如网易 163,aliyun 等

  1. 安装 wget, wget 用来从指定的 URL 下载文件

    yum install wget
    
  2. 在/etc/yum.repos.d/目录下,备份默认的 repos 文件,

    pwd /etc/yum.repos.d
    cp CentOS-Base.repo  CentOS-Base    .repo.backup
    
  3. 下载网易 163 或者是 aliyun 的 repos 文件,任选其一,如图 8-2

    wget http://mirrors.aliyun.com/repo/Centos-7.repo //阿里云
    wget http://mirrors.163.com/.help/CentOS7-Base-163.repo //网易 163
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3UPpWfeX-1686570839715)(img\01.png)]

  4. 使用下载好的 repos 文件替换默认的 repos 文件

    例如:用 CentOS7-Base-163.repo 替换 CentOS-Base.repo

    mv CentOS7-Base-163.repo  CentOS-Base.repo
    
  5. 清理旧缓存数据,缓存新数据

    yum clean all
    yum makecache
    

    yum makecache 就是把服务器的包信息下载到本地电脑缓存起来

  6. 测试

    yum list | grep firefox
    yum -y install firefox
    
less /etc/yum.repos.d/CentOS-Base.repo

克隆虚拟机

克隆

  1. 从现有虚拟机(关机状态)克隆出新虚拟机,右键选择管理=>克隆,如图 9-1

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CJ0BeAFI-1686570839715)(img\02.png)]

  2. 点击下一步,如图 9-2

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R5i6431d-1686570839715)(img\image-20230610131452769.png)]

  3. 选择虚拟机中的当前状态,如图 9-3

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jamTtDWs-1686570839715)(img\image-20230610131548651.png)]

  4. 选择创建完整克隆,如图 9-4

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2IPTsSXA-1686570839716)(img\image-20230610131630054.png)]

  5. 设置虚拟机名称及存储位置,如图 9-5

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kRHrfOtA-1686570839716)(img\03.png)]

  6. 等等等……等待克隆完成,如图 9-6,9-7

开机修改系统相关配置

注意: 使用 root 用户。

  1. 修改 vim /etc/sysconfig/network-scripts/ifcfg-ens33 ,修改 IP 地址,如图 9-8

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q9SAHFFl-1686570839716)(img\image-20230610134745601.png)]

  2. 修改/etc/hostname,修改主机名,如图9-9

ifconfig                                        # 因为是克隆的所以主机名,域什么的都一样
vim /etc/sysconfig/network-scripts/ifcfg-ens33 # 修改克隆机的配置,进去之后将IP地址IPADDR=192.168.126.100改为IPADDR=192.168.126.101
systemctl status network                         # 查看网络服务配置
systemctl status NetworkManager                   # 其实CentOS 7 中是NetworkManager
systemctl stop network                           # 为了保险起见
systemctl restart NetworkManager                 # 重启网络服务
ifconfig
ping 192.168.111.1                               # ping主机
ping www.baidu.com                               # ping 外网
cat /etc/hostname
hostnamectl set-hostname hadoop101
cat /etc/hostname
hostname

# 用xshell连接上克隆的虚拟机
ls
touch hello2                               # 新建一个文件尝试一下
ls

快照: 可以保存当前虚拟机的状态,一般在作一些危险的操作之前会拍一个快照,万一虚拟机崩了可以用快照恢复。

shell编程

Shell 概述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IRjlv86i-1686570839716)(img\shell01.png)]

  1. Linux 提供的 Shell 解析器有

    cat /etc/shells                                          # 查看所有的shell解析器
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UzGDjyh0-1686570839716)(img\image-20230610162929567.png)]

  2. bash 和 sh 的关系

    ls -l /bin/ | grep sh
    ls -l /bin/ | grep bash
    
  3. Centos 默认的解析器是 bash

    echo $SHELL                             # .sh就是shell脚本文件的后缀名
    

Shell 脚本入门

less /bin/unix-lpr.sh                      # 先看看写好的,格式; 第一行#!/bin/sh 这个指的是默认选择的命令行的解析器是sh,sh链接指向了bash

  1. 脚本格式

    脚本以==#!/bin/bash== 开头(指定解析器)

  2. 第一个 Shell 脚本:helloworld.sh

    1. 需求:创建一个Shell脚本,输出helloworld

    2. ls 
      mkdir scripts
      cd scripts/
      touch hello.sh
      vim hello.sh                        # 进入之后先第一行写 #!/bin/bash ,第二行写 echo "hello, world"
      ls
      
      
    3. 脚本的常用执行方式

      第一种(实际运用当中不用这种方式):采用bash或sh+脚本的相对路径或绝对路径(不用赋予脚本+x 权限)

      sh+脚本的相对路径

      sh+脚本的绝对路径

      bash+脚本的相对路径

      bash hello.sh                        # 因为这里已经在scripts目录下了,所以可以直接hello.sh
      cd ~
      bash scripts/hello.sh                # 用相对路径
      bash /root/scripts/hello.sh              # 用绝对路径
      sh scripts/hello.sh
      
      

      第二种(实际中最常用的):采用输入脚本的绝对路径或相对路径执行脚本==(必须具有可执行权限+x)==【前面的执行方式是当作bash命令的参数传入的,所以不需要x权限;但是这种方式是在当前bash界面解析执行,需要x权限】

      1. 首先要赋予 helloworld.sh 脚本的+x 权限
      1. 执行脚本

        相对路径

        绝对路径

      /root/scripts/hello.sh            # 绝对路径,但提示权限不够
      ll scripts                        # 发现只有可读权限,没有可执行权限
      chmod +x scripts/hello.sh
      ll scripts/                      # hello.sh 文件变为绿色,就是可执行文件
      /root/scripts/hello.sh           # 绝对路径执行成功
      scripts/hello.sh                 # 相对路径执行成功
      cd scripts/                      # 但是要注意切换到scripts目录下时
      ls
      hello.sh                         # bash: hello.sh: 未找到命令...   ,这样用相对路径执行Shell脚本时,系统把它当作时命令执行了
      ./hello.sh                        # 这样就正确执行了
      
      

      注意:第一种执行方法,本质是 bash 解析器帮你执行脚本,所以脚本本身不需要执行权限。第二种执行方法,本质是脚本需要自己执行,所以需要执行权限。

      [了解] 第三种:在脚本的路径前加上“.”或者 source

      1. 有以下脚本

        cat /root/scripts/hello.sh
        #!/bin/bash
        # echo "hello, world"
        
      1. 分别使用 sh,bash,./ 和 . 的方式来执行,结果如下:

        source hello.sh                 # 当前在scripts目录下
        source /root/scripts/hello.sh
        . hello.sh                      # 这里的" . "是命令, ./hello.sh中的" . "表示当前目录
        type source                     # source 是 shell 内嵌
        
        

      原因:

      前两种方式都是在当前 shell 中打开一个子 shell 来执行脚本内容,当脚本内容结束,则子 shell 关闭,回到父 shell 中。

      第三种,也就是使用在脚本路径前加“.”或者 source 的方式,可以使脚本内容在当前shell 里执行,而无需打开子 shell!这也是为什么我们每次要修改完/etc/profile 文件以后,需要 source 一下的原因。

      开子 shell 与不开子 shell 的区别就在于,环境变量的继承关系,如在子 shell 中设置的当前变量,父 shell 是不可见的。

      ps -f
      bash                                     # bash命令打开子shell
      ps -f                                    # 多了一个bash
      ./hello.sh
      exit                                     # 推出的是子shell
      
      

变量

系统预定义变量

  1. 常用系统变量

    $HOME(当前的主目录)、$PWD(当前的工作目录)、$SHELL(当前使用的shell解析器)、$USER(当前的用户) 等

  2. 案例实操

    (1)查看系统变量的值

    echo $HOME       # 当前主目录
    env                                      # 显示系统中已存在的环境变量,以及在定义的环境中执行指令
    env | less
    printenv | less                          # 和env几乎是一样的
    printenv $USER                            # 再printenv的时候就不用加$符了,直接USER就可以了 
    printenv USER       #  root
    echo $USER                                # 一般情况下,打印USER都要$,把USER当变量使用,只是printenv比较特殊,是专门打印env的
    ls $HOME
    bash                                      # 打开一个子shell
    ps -f
    echo $HOME                              # 父shell的变量,子shell也可以看
    exit
    
    

    (2)显示当前 Shell 中所有变量:set

    set                                      # 所有变量
    set | less
    
    

自定义变量

基本语法

定义变量:变量名=变量值,# 注意,=号前后不能有空格
撤销变量:unset 变量名
声明静态变量:readonly 变量,注意:不能 unset
a=2                                          # 定义a变量
echo $a                                      # 查看a变量的值
echo $my_var                                # 查看my_var,my_var未定义,所以显示空
my_var=hello                                # 赋值my_var为hello
echo $my_var
my_var=Hello                                # 改变my_var为Hello
echo $my_var
my_var = Hello                              # bash: my_var: 未找到命令...   ,my_var变量赋值时=两边不能有空格,如果有,系统会认为my_var是个命令。
my_var=hello, world                          # 所赋的值中间有空格,也会有 未找到命令
my_var="hello, world"                       # 用"“把字符串引起来
echo $my_var
my_var='Hello, world'                      # 当然用""还是''没有关系,都是可以的
echo $my_var
env | grep my_var                          # 系统中找不到
set | grep my_var                          # 所有变量可以找到,是个局部变量
bash                                        # 子shell
ps -f
echo $my_var                                # 是空,说明刚刚的my_var确实是局部变量,局部变量
exit
echo $my_var
export my_var                              # 将my_var升级成全局变量
echo $my_var                                # 全局变量,当前shell肯定可以
ps -f
bash
ps -f                                      # 查看ps -f命令是在子shell中执行的
echo $my_var                                # 子shell可以查看my_var变量
my_var=”hello, Linux"                      # 在子shell中更改my_var变量
echo $my_var                               # 在子shell中确实更改了
exit
ps -f                                      #查看是退出到了父shell
echo $my_var                                # 发现父shell中的变量不变,还是Hello, world;子shell中的变量改变只作用在子shell的范围内,不会影响父shell中的变量的值。
bash 
ps -f
my_var="hello, Linux"
export my_var                              # 在子shell中把变量值改变后,再将他升级成全局变量
echo $my_var
exit
echo $my_var                                # 再父shell中依然没有改变;用了这么多子进程,就是为了看在脚本中的变量,在脚本中哪些变量可以访问到
vim hello.sh                                # 添加一句  echo $my_var
source hello.sh                            # source可以执行出
./hello.sh                                  # 也可以执行出
echo $new_var                              # 没有new_var,为空
new_var="hello, linux"
echo $new_var
vim hello.sh                                # 新增一行  echo $new_var
./hello.sh                                  # 前两行输出了,但是最后一样new_var没有输出,因为是局部变量,在子shell中访问不到;
. hello.sh                                  # 想要让他输出,第一种方式就是用source或者是 . ,执行它
export new_var                              # 想要让他输出,第二种方式就是export,将这个变量改为全局变量
./hello.sh
echo $a                                    # 是2
a=1+5
echo $a                                    # 输出的是   1+5 ,不是6,这里是没有类型的,如果想要得到结果,就需要用到后面的运算符
a=$((1+5))                                  # 使用运算符
echo $a                                    # 输出的是6
a=$[5+9]                                    # 使用运算符
echo $a                                    # 输出的是14
readonly b=5                                # 定义只读变量
b=10                                        # 报错  -bash: b: 只读变量
echo $b
set | less
unset a                                    # 撤销掉不用的变量
set | less                                  # 所有变量里就找不到a了
unset b                                    # unset b同样也会报错    -bash: unset: b: 无法反设定: 只读 variable

变量定义规则

  1. 变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建议大写

  2. 等号两侧不能有空格

  3. 在 bash 中,变量默认类型都是字符串类型,无法直接进行数值运算。

  4. 变量的值如果有空格,需要使用双引号或单引号括起来。

案例实操

  1. 定义变量 A

    A=5
    echo $A    # 5
    
  2. 给变量 A 重新赋值

    A=8
    echo $A    # 8
    
  3. 撤销变量 A

    unset A
    echo $A
    
    
  4. 声明静态的变量 B=2,不能 unset

    readonly B=2
    echo $B         # 2
    B=9             # -bash: B: readonly variable
    
  5. 在 bash 中,变量默认类型都是字符串类型,无法直接进行数值运算

    C=1+2
    echo $C        # 1+2
    
  6. 变量的值如果有空格,需要使用双引号或单引号括起来

    D=I love banzhang        # -bash: world: command not found
    D="I love banzhang"
    echo $D                  # I love banzhang
    
  7. 可把变量提升为全局环境变量,可供其他 Shell 程序使用

    export 变量名
    vim helloworld.sh
    

    在 helloworld.sh 文件中增加 echo $B

    #!/bin/bash
    echo "helloworld"
    echo $B
    
    ./helloworld.sh     
    # helloworld
    # 
    

    发现并没有打印输出变量 B 的值。

    export B
    ./helloworld.sh      
    # helloworld       
    # 2
    

全局环境变量

  • 系统环境变量基本使用全大写字母,区分普通环境变量
  • 全局环境变量作用范围:所有会话和所有生成的子shell
  • 查看环境变量使用env或者printenv

局部环境变量

  • 作用范围:定义在它们的进程中可见
  • 目前没有一个命令可以查看局部环境变量
  • set命令:全局变量、局部变量、用户定义变量,按照字母顺序对结果排序
ls
cd scripts/
hello.sh                                    # 未找到命令...
cp hello.sh /bin/                            # 所有系统命令都放在了/bin/目录下,所以把hello.sh也放到/bin/下
hello.sh                                    # 成功显示,后面两行空的是因为那两个变量unset之前掉了
rm -f /bin/hello.sh                          # 但是/bin/是放系统命令的,这里放hello.sh不好
echo $PATH                                  # 其实如果想要改的话,改PATH也可以,在PATH的后面直接用冒号(:)隔开,在后面添加上/bin/hello.sh 就可以

特殊变量

$n

基本语法

$n                            # 功能描述:n 为数字,$0 代表该脚本名称,$1-$9 代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如${10}
vim hello.sh                                # 删掉后两行,增加echo "hello, $1"
./hello.sh                                  # 输出    hello, world               hello, 
./hello.sh xiaoming                          # 输出    hello, world               hello, xiaoming
./hello.sh xiaoliang                        # 输出    hello, world               hello, xiaoliang
vim parameter.sh                           
#!/bin/bash
echo '===================$n===================' # 这里用单引号是因为怕双引号会认为$n是个参数
echo script name: $0
echo 1st parameter: $1
echo 2nd parameter: $2
ll
chmod +x parameter.sh                        # 添加可执行权限
./parameter.sh abc def
# ===================$n===================
# script name: ./parameter.sh
# 1st parameter: abc
# 2nd parameter: def
/root/scripts/parameter.sh abc def
# ===================$n===================
# script name: /root/scripts/parameter.sh             #这里不想要这么长,可以使用basename命令
# 1st parameter: abc
# 2nd parameter: def

$#

基本语法

$#                             # 功能描述:获取所有输入 ==参数个数== ,常用于循环,判断参数的个数是否正确以及加强脚本的健壮性。
vim parameter.sh
#!/bin/bash
echo '===================$n===================' # 这里用单引号是因为怕双引号会认为$n是个参数
echo script name: $0
echo 1st parameter: $1
echo 2nd parameter: $2
echo '===================$#==================='
echo parameter numbers: $#
./parameter.sh
# ===================$n===================
# script name: ./parameter.sh
# 1st parameter: 
# 2nd parameter: 
# ===================$#===================
# parameter numbers: 0
/root/scripts/parameter.sh abc def
# ===================$n===================
# script name: /root/scripts/parameter.sh
# 1st parameter: abc
# 2nd parameter: def
# ===================$#===================
# parameter numbers: 2

$*、$@

基本语法

$*               # 功能描述:这个变量代表命令行中所有的参数,== $*把所有的参数看成一个整体 ==
$@               # 功能描述:这个变量也代表命令行中所有的参数,不过 == $@把每个参数区分对待 ==
vim parameter.sh
#!/bin/bash
echo '===================$n===================' # 这里用单引号是因为怕双引号会认为$n是个参数
echo script name: $0
echo 1st parameter: $1
echo 2nd parameter: $2
echo '===================$#==================='
echo parameter numbers: $#
echo '===================$*==================='
echo $*
echo '===================$@==================='
echo $@
/root/scripts/parameter.sh abc def
# ===================$n===================
# script name: /root/scripts/parameter.sh
# 1st parameter: abc
# 2nd parameter: def
# ===================$#===================
# parameter numbers: 2
# ===================$*===================
# abc def
# ===================$@===================
# abc def
$?

基本语法

$?                 # 功能描述:最后一次执行的命令的返回状态。如果这个变量的值为 0,证明上一个命令正确执行;如果这个变量的值为非0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。
echo $?         # 因为之前执行过脚本,之前都是正常执行的
parameter.sh    # 未找到命令...
echo $?         # 127

运算符

基本语法

"$((运算式))""$[运算式]"
a= 1 + 2             # 未找到命令
a=1+2
echo $a              # 1+2
1+2                  # 未找到命令
expr 1+2             # 1+2 不对,还是1+2
expr 1 + 2           # 3 得到得数了,expr像是命令,1 + 2是3个参数
expr 5 - 2           # 3
expr 5 * 2           # expr: 语法错误    可能是*造成的
expr 5 \* 2          # 10      使用\转译字符
echo $[5 * 2]        # 为了简化引入了运算符#(()) 和#[]
echo $[5*2]           # 10        中间的空格可有可无
echo $((5*2))         # 10
a=$[6+8]
echo $a               # 14
a=expr 5 \* 2         # 未找到命令...
a="expr 5 \* 2"       # 会不会是需要加""
echo $a               # expr 5 \* 2
a=$(expr 5 \* 2)      # 这里用了命令替换,就是用$()括号里写替换的内容,和运算符的$(())有些像
echo $a               # 10
a=`expr 5 \* 2`       # 反引号`也是命令替换
echo $a               # 10
a=`expr 5 \* 4`      
echo $a               # 20
s=$[(2+3)*4]          # 计算(2+3)*4
echo $s               # 20
cd scripts/           # 进入scripts目录下创建add.sh
vim add.sh            # 在脚本中用加法
#!/bin/bash
sum=$[$1 + $2]
echo sum=$sum
chmod +x add.sh         # 添加执行权限
./add.sh 25 89          # sum=114

条件判断

基本语法

test condition
[condition]                       # 注意 condition 前后要有空格
# 注意:条件非空即为 true,[ atguigu ]返回 true,[ ] 返回 false。
a=hello
echo $a                           # hello
test $a = hello                   # 测试,a的值是否等于hello,test是函数,会返回一个值,通过$?判断是否返回正确
echo $?                           # 0    返回0就是true,和其他的语言颠倒
test $a = Hello
echo $?                           # 1     返回1就是false,返回错误
a=Hello
test $a = Hello
echo $?                           # 0
[ $a = Hello ]                    # test太麻烦了,就有了[  ],[]里一定左右都要有空格
echo $?                           # 0
[ $a = hello ]                    # 判断a的值是不是hello
echo $?                           # 1    返回1  false
[ $a=hello ]                      # $a=hello中间也一定要有空格,如果没有,会认为这是一个参数
echo $?                           # 0
[ afadafafafaf ]                  # 在[]中随便打一些内容
echo $?                           # 0
[  ]                              # [  ]中间是空的
echo $?                           # 1
[ $a = hello ]                    
echo $?                           # 1
[ $a = Hello ]  
echo $?                           # 0
[ $a != Hello ]                   # !=试一下
echo $?                           # 1
[ $a != hello ]                   
echo $?                           # 0
[ 2 = 8 ]                         # 试数字可以吗
echo $?                           # 1
[ 2 = 2 ]                         
echo $?                           # 0
[ 2 < 8 ]                         # 没有那个文件或目录,在shell中 < > 被认为是输入输出
[ 2 -lt 8 ]                       # -lt 表示小于
echo $?                           # 0
[ 2 -gt 8 ]                       
echo $?                           # 1
ls
touch test
ls 
ll                                # test没有x权限
[ -r hello.sh ]                   # 看hello.sh有没有可读的权限
echo $?                           # 0
[ -w hello.sh ]                   # 看hello.sh有没有可写的权限
echo $?                           # 0
[ -r test ]                       
echo $?                           # 0
[ -x test ]                     
echo $?                           # 1   没有可执行的权限
[ -e /home/atguigu/info ]         # 看该文件是否存在
echo $?                           # 1
ls /home/atguigu/                 # 确实没有
[ -e /home/atguigu/initial-setup-ks.cfg ]
ls /home/atguigu/                 # 是有initial-setup-ks.cfg
echo $?                           # 0
[ -f add.sh ]                     # 看add.sh文件存在并且是一个常规的文件(file)
echo $?                           # 0
[ -d add.sh ]                     # 看add.sh是不是一个目录
echo $?                           # 1
[ -d /home/atguigu ]              
echo $?                           # 0
a=15
[ $a -lt 20 ] && echo "$a < 20" || echo "$a > 20"                         # 15 < 20               多条件判断(&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一条命令执行失败后,才执行下一条命令)【可以使用得类似三元运算符?:一样】
a=27
[ $a -lt 20 ] && echo "$a < 20" || echo "$a > 20"                         # 15 > 20
[ atguigu ] && echo OK || echo notOK                   # OK     [  ]中间有东西就是0
[  ] && echo OK || echo notOK      # notOK       [  ]中间是空就是1

常用判断条件

  1. 两个整数之间比较

    -eq等于(equal)												-ne不等于(not equal)
    
    -lt小于(less than) 											-le小于等于(less equal)
    
    -gt大于(greater than)											-ge大于等于(greater equal)
    
    # 注:如果是字符串之间的比较 ,用等号“=”判断相等;用“!=”判断不等。
    
  2. 按照文件权限进行判断

    -r 有读的权限(read)
    
    -w 有写的权限(write)
    
    -x 有执行的权限(execute)
    
  3. 按照文件类型进行判断

    -e 文件存在(existence)
    
    -f 文件存在并且是一个常规的文件(file)
    
    -d 文件存在并且是一个目录(directory)
    

案例实操

  1. 23 是否大于等于 22

  2. helloworld.sh 是否具有写权限

  3. /home/atguigu/cls.txt 目录中的文件是否存在

  4. 多条件判断(&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一条命令执行失败后,才执行下一条命令)【可以使用得类似三元运算符?:一样】

流程控制==(重点)==

if 判断

基本语法

  1. 单分支

    if [ 条件判断式 ];then
        程序
    fi
    

    或者

    if [ 条件判断式 ]
    then
        程序
    fi
    
  2. 多分支

    if [ 条件判断式 ]
    then
        程序
    elif [ 条件判断式 ]
    then
        程序
    else
        程序
    fi
    

    注意事项:

    ①[ 条件判断式 ],中括号和条件判断式之间必须有空格

    ②if 后要有空格

cd /home/atguigu/;   ls -l                 # ;把两个命令隔开,和管道|不同,管道是执行的结果通过管道传递给后面的命令
cd ~
a=25
if [ $a -gt 18 ]; then echo OK; fi         # 单分支
a=15
if [ $a -gt 18 ]; then echo OK; fi
cd scripts/                                # 还是到scripts/目录下写脚本
vim if_test.sh
#!/bin/bash

if [ $1 = atguigu ]                  
then
	echo "welcome, atguigu"
fi

chmod +x if_test.sh
./if_test.sh                          # 期待一元表达式          传入空会报错
vim if_test.sh
#!/bin/bash

#if [ $1 = atguigu ]                    # 如果没有传入参数的话,是空,会报错,所以在实际通常写成[ "$1"x = "atguigu"x ]
if [ "$1"x = "atguigu"x ]
then
	echo "welcome, atguigu"
fi

./if_test.sh
./if_test.sh xiaoming
./if_test.sh atguigu                  # welcome, atguigu
if [ $a -gt 18 ] && [ $a -lt 35 ]; then echo OK; fi
echo $a                               # 15   a的值是15,当然不会OK
a=25
if [ $a -gt 18 ] && [ $a -lt 35 ]; then echo OK; fi                           # OK
a=36
if [ $a -gt 18 ] && [ $a -lt 35 ]; then echo OK; fi                           # 没有输出OK
if [ $a -gt 18 && $a -lt 35 ]; then echo OK; fi                                # 报错,直接放在[]中不行
if [ $a -gt 18 -a $a -lt 35 ]; then echo OK; fi                                # 这样才行,-a就是add 逻辑与;-o就是or 逻辑或; 这里没有输出OK是因为a是36
a=20
if [ $a -gt 18 ] && [ $a -lt 35 ]; then echo OK; fi                            # OK 
vim if_test.sh
#!/bin/bash

#if [ $1 = atguigu ]                    # 如果没有传入参数的话,是空,会报错,所以在实际通常写成[ "$1"x = "atguigu"x ]
if [ "$1"x = "atguigu"x ]
then
	echo "welcome, atguigu"
fi

# 输入第二个参数,表示年龄,判断属于哪个年龄段
if [ $2 -lt 18 ]
then
	echo "未成年人”
else
	echo "成年人"
fi
./if_test.sh atguigu 15
# welcome, atguigu
# 未成年人
./if_test.sh atguigu 25
# welcome, atguigu
# 成年人
vim if_test.sh
#!/bin/bash

#if [ $1 = atguigu ]                    # 如果没有传入参数的话,是空,会报错,所以在实际通常写成[ "$1"x = "atguigu"x ]
if [ "$1"x = "atguigu"x ]
then
	echo "welcome, atguigu"
fi

# 输入第二个参数,表示年龄,判断属于哪个年龄段
if [ $2 -lt 18 ]
then
	echo "未成年人”
elif [$2 -lt 35 ]
then
	echo "青年人”
elif [ $2 -lt 60 ]
then
	echo "中年人"
else
	#echo "成年人"
	echo "老年人"
fi
./if_test.sh atguigu 15
# welcome, atguigu
# 未成年人
./if_test.sh atguigu 25
# welcome, atguigu
# 青年人
./if_test.sh atguigu 36
# welcome, atguigu
# 中年人
./if_test.sh atguigu 67
# welcome, atguigu
# 老年人

case 语句

基本语法

case $变量名 in
"值 1")
    如果变量的值等于值 1,则执行程序 1
;;
"值 2")
    如果变量的值等于值 2,则执行程序 2
;;
    …省略其他分支…
*)
    如果变量的值都不是以上的值,则执行此程序
;;
esac

注意事项:

  1. case 行尾必须为单词" in ",每一个模式匹配必须以右括号“)”结束。

  2. 双分号" ;; "表示命令序列结束,相当于java中的 break。

  3. 最后的"" *) "表示默认模式,相当于java中的 default。

vim case_test.sh
#!/bin/bash

case $1 in
1)
	echo "one"
;;
2)
	echo "two"
;;
3) 
	echo "three"
;;
*) 
	echo "number else"
;;
esac
chmod +x case_test.sh
./case_test.sh 2                            # two
./case_test.sh 1                            # one
./case_test.sh 6                            # number else

for 循环

基本语法 1(和其他的语言比较相似,但是不是Shell中最常用的)

for (( 初始值;循环控制条件;变量变化 ))
do
	程序
done
vim sum_to.sh
#!/bin/bash

for (( i=1; i <= $1; i++ ))                # for后必须有空格,但是括号里无所谓;这里使用了双小括号(()),里面就可以用<=一类的运算符了
do
	sum=$[ $sum+$i ]
done
echo sum
chmod +x sum_to.sh
./sum_to.sh 100                             # 5050            for循环加到100
./sum_to.sh 10                             # 55
a=3
if (($a > 2)); then echo OK; else echo notOK; fi                                   # OK          接放一个数学表达式,这里用(())实现if,但是一般还是用[]这种标准化的写法
a=1
if (($a > 2)); then echo OK; else echo notOK; fi                                   # notOK

案例实操

从 1 加到 100


基本语法 2

for 变量 in 值1 值2 值3…
do
	程序
done
for os in linux windows macos; do echo $os; done
# linux
# windows
# macos
for i in {1..100}; do sum=$[$sum+$i]; done; echo $sum                                  # 5050         这里用了{},它是shell的内部运算符,表示一个序列,{1..100}表示1到100,这种遍历方式像增强for循环
vim parameter_for_test.sh
#!/bin/bash

echo '===============$*================'
for para in $*
do
	echo $para
done

echo '===============$@================'
for para in $@
do
	echo $para
done
chmod +x parameter_for_test.sh
./parameter_for_test.sh a b c d e          # $* 和 $@ 没有加引号
# ===============$*================
# a
# b
# c
# d
# e
# ===============$@================
# a
# b
# c
# d
# e
vim parameter_for_test.sh    # 加引号
#!/bin/bash

echo '===============$*================'
for para in "$*"
do
	echo $para
done

echo '===============$@================'
for para in "$@"
do
	echo $para
done
./parameter_for_test.sh a b c d e
# ===============$*================
# a b c d e                  # $*认为这是多个参数的整体
# ===============$@================
# a                          # $@则是将它们作为独立的参数输出
# b
# c
# d
# e
  1. 使用$*
    相当于将所有位置参数不带引号的形式再次传递出去。由于不带引号,最大的问题是参数个数会被重新解析。比如第一个参数"I like"作为一个整体被拆成了2个位置参数。 另外,由于每个位置参数都没有双引号,会再次做变量扩展,因此java*变成了"javac"。 这种使用方式,相当于bar $1 $2 $3 $4。所以最终输出结果是4个位置参数,并且java*被扩展为"javac"
  2. 使用 @ 与 ‘ @ 与 ` @*`没有区别。
  3. 使用"$*"
    根据man文档解释,相当于将所有位置参数连接成一个word。连接符就是IFS(一般就是空格),所以,此时输出的结果只有一个位置参数,位置参数格式变成了1个。由于有双引号的作用,java*没有被扩展为"javac"。 这种方式,相当于bar "$1 $2 $3 $4"
  4. 使用"$@" 根据man文档解释,相当于拆分成多个word,并且每个word都有双引号。即相当于bar "$1" "$2" "$3" "$4"。因此,位置参数格式保持不变,同时java*没有被扩展为"javac"

案例实操

打印所有输入参数


比较 ∗ 和 *和 @区别

∗ 和 *和 @都表示传递给函数或脚本的所有参数,不被双引号“”包含时,都以$1 2 … 2 … 2n的形式输出所有参数。


当它们被双引号""包含时,$*会将所有的参数作为一个整体,以“$1 $2 …$n”的形式输出所有参数;$@会将各个参数分开,以“$1” “$2”…“$n”的形式输出所有参数。


while 循环

基本语法

while [ 条件判断式 ]
do
	程序
done
vim sum_to.sh
#!/bin/bash

# 用for进行实现
for (( i=1; i <= $1; i++ ))                # for后必须有空格,但是括号里无所谓;这里使用了双小括号(()),里面就可以用<=一类的运算符了
do
	sum=$[ $sum+$i ]
done
echo sum

# 用while做一个实现
a=1
while [ $a -le $1 ]
do
	sum2=$[ $sum2 + $a ]
	a=$[$a + 1]
done
echo $sum2
./sum_to.sh 100
# 5050
# 5050
vim sum_to.sh
#!/bin/bash

# 用for进行实现
for (( i=1; i <= $1; i++ ))                # for后必须有空格,但是括号里无所谓;这里使用了双小括号(()),里面就可以用<=一类的运算符了
do
	sum=$[ $sum+$i ]
done
echo sum

# 用while做一个实现
a=1
while [ $a -le $1 ]
do
#	sum2=$[ $sum2 + $a ]
#	a=$[$a + 1]   # 这样也太麻烦了,后来的版本在优化
# 内嵌命令:
	let sum2+=a
	let a++
done
echo $sum2
./sum_to.sh 100
# 5050
# 5050

案例实操

从 1 加到 100


read 读取控制台输入

基本语法

read (选项) (参数)
# 1) 选项:
# -p:指定读取值时的提示符;
# -t:指定读取值时等待的时间(秒)如果-t 不加表示一直等待
# 2) 参数
# 变量:指定读取值的变量名
vim read_test.sh
#!/bin/bash

read -t 10 -p "请输入您的芳名:" name
echo "welcome, $name"
chmod +x read_test.sh
./read_test.sh
# 请输入您的芳名:atguigu           # 输入atguigu
# welcome, atguigu
./read_test.sh
# 请输入您的芳名:welcome,           # 一直等,不输入

案例实操

提示 7 秒内,读取控制台输入的名称


函数

函数和Shell脚本差不多,Shell脚本的返回值是$?,但是这往往不是我们想要的,且在调用脚本时过于麻烦,

系统函数

basename

基本语法

basename [string / pathname] [suffix]                  # 功能描述:basename 命令会删掉所有的前缀包括后一个(‘/’)字符,然后将字符串显示出来。
# basename 可以理解为取路径里的文件名称
# 选项:
# suffix 为后缀,如果 suffix 被指定了,basename 会将 pathname 或 string 中的 suffix 去掉。
ls
vim add.sh
date                             # 2023年 06月 12日 星期一 16:20:25 CST             当前的时间
date +%s                         # 1686558040                 当前的时间戳
vim cmd_test.sh
#!/bin/bash

filename="$1"_log_$(date +%s)            # $(date +%s)这里叫做命令替换,但是如果从函数角度看,这个就是调用了一下系统函数,后面+%s就是传入的参数,把得到的结果用$()符包起来,再进行字符串的拼接。
echo $filename
chmod +x cmd_test.sh
./cmd_test.sh atguigu
# atguigu_log_167572035
vim cmd_test.sh
vim parameter.sh
./parameter.sh a
# ===================$n===================
# script name: ./parameter.sh
# 1st parameter: a
# 2nd parameter: 
# ===================$#===================
# parameter numbers: 1
# ===================$*===================
# a
# ===================$@===================
# a
/root/scripts/parameter.sh a b
# ===================$n===================
# script name: /root/scripts/parameter.sh
# 1st parameter: a
# 2nd parameter: b
# ===================$#===================
# parameter numbers: 2
# ===================$*===================
# a b
# ===================$@===================
# a b
# 如果不想看前面的/root/scripts/,只想看到parameter.sh
basename /root/scripts/parameter.sh       # parameter.sh
basename /root/scri/safdia                # sfdia             所以发现它并不是查找这个文件在不在,而只是作字符串的剪切
basename /root/scripts/parameter.sh .sh    # parameter         suffix,在后面再加上后缀,就也可以把后缀名剪切掉
vim parameter.sh
#!/bin/bash
echo '===================$n===================' # 这里用单引号是因为怕双引号会认为$n是个参数
echo script name: $( basename $0 .sh )
echo 1st parameter: $1
echo 2nd parameter: $2
echo '===================$#==================='
echo parameter numbers: $#
echo '===================$*==================='
echo $*
echo '===================$@==================='
echo $@
./parameter.sh a b
# ===================$n===================
# script name: parameter
# 1st parameter: a
# 2nd parameter: b
# ===================$#===================
# parameter numbers: 2
# ===================$*===================
# a b
# ===================$@===================
# a b
/root/scripts/parameter.sh a b
# ===================$n===================
# script name: parameter
# 1st parameter: a
# 2nd parameter: b
# ===================$#===================
# parameter numbers: 2
# ===================$*===================
# a b
# ===================$@===================
# a b

案例实操

截取该/home/atguigu/banzhang.txt 路径的文件名称。

dirname

基本语法

dirname 文件绝对路径                          # 功能描述:从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分)
# dirname 可以理解为取文件路径的绝对路径名称
dirname /root/scripts/parameter.sh         # /root/scripts            发现和basename相反
dirname ../scripts/parameter.sh            # ../scripts              和basename一样,都是只是字符串的剪切,不会查看文件是否存在
dirname ../scri/dsafdi/adsgsdagf           # ../scri/dsafdi
vim parameter.sh
#!/bin/bash
echo '===================$n===================' # 这里用单引号是因为怕双引号会认为$n是个参数
echo script name: $( basename $0 .sh )
# cd $(dirname $0)                 # 切换目录到当前目录
echo script path: $(cd $(dirname $0); pwd)
echo 1st parameter: $1
echo 2nd parameter: $2
echo '===================$#==================='
echo parameter numbers: $#
echo '===================$*==================='
echo $*
echo '===================$@==================='
echo $@
./parameter.sh a b
# ===================$n===================
# script name: parameter
# script path: /root/scripts
# 1st parameter: a
# 2nd parameter: b
# ===================$#===================
# parameter numbers: 2
# ===================$*===================
# a b
# ===================$@===================
# a b
cd /home/atguigu/                         # 换路径
../../root/scripts/parameter.sh a b        # 无论在哪个目录path都可以对
# ===================$n===================
# script name: parameter
# script path: /root/scripts
# 1st parameter: a
# 2nd parameter: b
# ===================$#===================
# parameter numbers: 2
# ===================$*===================
# a b
# ===================$@===================
# a b

# $()命令替换,就是函数的调用

案例实操

获取 banzhang.txt 文件的路径。


自定义函数

基本语法

[ function ] funname[()]
{
	Action;
	[return int;]
}
vim fun_test.sh
#!/bin/bash

function add(){
	s=$[$1 + $2]
	echo "和:"$s
}

read -p "请输入第一个整数:" a
read -p "请输入第二个整数:" b

add $a $b
chmod +x fun_test.sh
./fun_test.sh
# 请输入第一个整数: 35
# 请输入第二个整数: 67
# 和: 102
vim fun_test.sh                           # 参数解决了,但是只是直接echo显示,没有返回值
#!/bin/bash

function add(){
	s=$[$1 + $2]
	# echo "和:"$s
	return "和: " $s
}

read -p "请输入第一个整数:" a
read -p "请输入第二个整数:" b

add $a $b
echo $?
./fun_test.sh                               # 说返回值只能是0-255的数
# 请输入第一个整数: 35
# 请输入第二个整数: 67
# ./fun_test.sh: 第 5 行:return: 和: 102: 需要数字参数255
vim fun_test.sh
#!/bin/bash

function add(){
	s=$[$1 + $2]
	# echo "和:"$s
	return $s
}

read -p "请输入第一个整数:" a
read -p "请输入第二个整数:" b

add $a $b
echo "和: " $?
./fun_test.sh                              # 成功执行了
# 请输入第一个整数: 35
# 请输入第二个整数: 67
# 和: 102
./fun_test.sh                           # 得数错了
# 请输入第一个整数: 156
# 请输入第二个整数: 237
# 和: 137
vim fun_test.sh
#!/bin/bash

function add(){
	s=$[$1 + $2]
	# echo "和:"$s
	# return $s
	echo $s
}

read -p "请输入第一个整数:" a
read -p "请输入第二个整数:" b

sum=$(add $a $b)
echo "和: " $sum
echo "和的平方:" $[$sum * $sum]
./fun_test.sh
# 请输入第一个整数: 156
# 请输入第二个整数: 237
# 和: 393
# 和的平方: 154449

经验技巧

  1. 必须在调用函数地方之前,先声明函数,shell 脚本是逐行运行。不会像其它语言一样先编译。

  2. 函数返回值,只能通过$?系统变量获得,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。return 后跟数值 n(0-255)

案例实操

计算两个输入参数的和。

综合应用案例

归档文件

实际生产应用中,往往需要对重要数据进行归档备份。

需求:实现一个每天对指定目录归档备份的脚本,输入一个目录名称(末尾不带/),将目录下所有文件按天归档保存,并将归档日期附加在归档文件名上,放在/root/archive 下。

这里用到了归档命令:tar

后面可以加上-c 选项表示归档,加上-z 选项表示同时进行压缩,得到的文件后缀名为.tar.gz。

脚本实现如下:

#!/bin/bash

# 首先判断输入参数个数是否为 1
if [ $# -ne 1 ]
then
	echo "参数个数错误!应该输入一个参数,作为归档目录名"
	exit
fi

# 从参数中获取目录名称
if [ -d $1 ]
then
	echo
else
	echo
	echo "目录不存在!"
	echo
exit
fi

DIR_NAME=$(basename $1)
DIR_PATH=$(cd $(dirname $1); pwd)

# 获取当前日期
DATE=$(date +%y%m%d)

# 定义生成的归档文件名称
FILE=archive_${DIR_NAME}_$DATE.tar.gz
DEST=/root/archive/$FILE

# 开始归档目录文件
echo "开始归档..."
echo

tar -czf $DEST $DIR_RATH/$DIR_NAME

if [ $? -eq 0 ]
then
	echo
	echo "归档成功!"
	echo "归档文件为:$DEST"
	echo
else
	echo "归档出现问题!"
	echo
fi

exit
vim daily_archive.sh
#!/bin/bash

# 首先判断输入参数个数是否为1
if [ $# -ne 1 ]
then
	echo "参数个数错误!应该输入一个参数,作为归档目录名"
	exit       # exit就可以直接退出
fi

# 从参数中获取目录名称
if [ -d $1 ]
then
	echo
else
	echo
	echo "目录不存在!"
	echo
exit
fi

# 提取目录名称
DIR_NAME=$(basename $1)
DIR_PATH=$(cd $(dirname $1); pwd)

# 获取当前日期
DATE=$(date +%y%m%d)

# 定义生成的归档文件名称
FILE=archive_${DIR_NAME}_$DATE.tar.gz   # 文件名称
DEST=/root/archive/$FILE                #文件的绝对路径名



# 开始归档目录文件
echo "开始归档..."
echo

tar -czf $DEST $DIR_PATH/$DIR_NAME     # 归档

# 判断归档是否成功
if [ $? -eq 0 ]
then
	echo
	echo "归档成功!"
	echo "归档文件为:$DEST"
	echo
else
	echo "归档出现问题!"
	echo
fi

exit
chmod u+x daily_archive.sh
ll
./daily_archive.sh                         # 参数个数错误!应该输入一个参数,作为归档目录
./daily_archive.sh a b
# 参数个数错误!应该输入一个参数,作为归档目录
./daily_archive.sh ../scripts              # 提示归档出现问题!,是因为没有/root/archive/目录
mkdir /root/archive
./daily_archive.sh ../scripts              # 归档成功
crontab -l                                # 这个我们也没有必要每次手动去归档,可以设置定时任务
crontab -e                                # 编辑定时任务,     在里面添加0 2 * * *  /root/scripts/daily_archive.sh /root/scripts
crontab -l                                # 这样就每天定时归档,实现数据的备份归档管理

正则表达式入门

正则表达式使用单个字符串来描述、匹配一系列符合某个语法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。在 Linux 中,grep,sed,awk 等文本处理工具都支持通过正则表达式进行模式匹配。

常规匹配

一串不包含特殊字符的正则表达式匹配它自己,例如:

cat /etc/passwd | grep atguigu 

就会匹配所有包含 atguigu 的行。

ls
vim daily_archive.sh
cat /etc/passwd                            # 可以获取到所有的用户信息
cat /etc/passwd | grep atguigu              # 信息太多,如果只要看atguigu的信息,可以在后面加上| grep atguigu,直接筛选出来atguigu的相关信息
cat /etc/passwd | grep 1000:                # 筛选出所有的和1000:相关的信息
cat /etc/passwd | grep 00:                  # 筛选出所有的和00:相关的信息

常用特殊字符

  1. 特殊字符:^

    ^ 匹配一行的开头,例如:

    cat /etc/passwd | grep ^a 
    

    会匹配出所有以 a 开头的行

  2. 特殊字符:$

    $ 匹配一行的结束,例如

    cat /etc/passwd | grep t$
    

    会匹配出所有以 t 结尾的行

    思考:^$ 匹配什么?

  3. 特殊字符:.

    . 匹配一个任意的字符,例如

    cat /etc/passwd | grep r..t
    

    会匹配包含 rabt,rbbt,rxdt,root 等的所有行

  4. 特殊字符:*

    ==*== 不单独使用,他和上一个字符连用,表示匹配上一个字符 0 次或多次,例如

    [atguigu@hadoop101 shells]$ cat /etc/passwd | grep ro*t

    会匹配 rt, rot, root, rooot, roooot 等所有行

    思考:.*匹配什么?

  5. 字符区间(中括号):[ ]

    [ ] 表示匹配某个范围内的一个字符,例如

    [6,8]------匹配 6 或者 8

    [0-9]------匹配一个 0-9 的数字

    [0-9]*------匹配任意长度的数字字符串

    [a-z]------匹配一个 a-z 之间的字符

    [a-z]* ------匹配任意长度的字母字符串

    [a-c, e-f]-匹配 a-c 或者 e-f 之间的任意字符

    cat /etc/passwd | grep r[a,b,c]*t
    

    会匹配 rt,rat, rbt, rabt, rbact,rabccbaaacbt 等等所有行

  6. 特殊字符:\

    \ 表示转义,并不会单独使用。由于所有特殊字符都有其特定匹配模式,当我们想匹配

    某一特殊字符本身时(例如,我想找出所有包含 ‘$’ 的行),就会碰到困难。此时我们就要

    将转义字符和特殊字符连用,来表示特殊字符本身,例如

    cat /etc/passwd | grep 'a\$b' 
    

    就会匹配所有包含 a$b 的行。注意需要使用单引号将表达式引起来。

cat /etc/passwd | grep ^a                   # 获取到的都是以a开头的行
cat /etc/passwd | grep ^at                 # 获取所有以at开头的行
cat /etc/passwd | grep bash$               # 获取所有以bash结尾的行
cat /etc/passwd | grep ^atbash$            # 写死了时获取atbash
cat /etc/passwd | grep ^$                 # 什么都没有,其实^$是指空行
cat daily_archive.sh | grep ^$             # 空行
cat daily_archive.sh | grep -n ^$
# 显示行号的空行
cat daily_archive.sh | grep r..t           # 显示所有r和t中间只隔2个字符的行
cat /etc/passwd | grep r..t
cat /etc/passwd | grep r.t                # 显示所有r和t中间只隔1个字符的行
cat /etc/passwd | grep r...t                # 显示所有r和t中间只隔3个字符的行
cat /etc/passwd | grep ro*t                # 获取所有r和t之间有任意个o的行,包含没有
cat /etc/passwd | grep ^a.*bash$           # .*是指任意字符,这里表示以a开头,bash结尾的中间有任意字符的行
cat /etc/passwd | grep ^a.*in$            # .*是指任意字符,这里表示以a开头,in结尾的中间有任意字符的行
cat /etc/passwd | grep ^a.*var.*in$       # 以a开头,in结尾,中间有任意位置有var的行
cat /etc/passwd | grep r[a,b]t             # 匹配rat或者是rbt
echo "rbtadfasf" | grep r[a,b]t
echo "23ddratadfasf" | grep r[a,b]t
echo "23ddratadfasf" | grep r[ab]t        # r[ab]t中间也可以不加逗号
echo "23ddraaatadfasf" | grep r[ab]*t     # 匹配a或者b出现任意多次
echo "23ddrabbadfasf" | grep r[ab]*t      
# 也可以匹配到
cat /etc/passwd | grep r[a-z]*t           # 匹配r和t之间有任意字母的行
cat daily_archive.sh | grep $             # 默认认为$是结尾,但是这里没有指定以什么结尾,所有就全部输出了
cat daily_archive.sh | grep '\$'           # 要匹配$符,就要进行转义, 并且必须要用单引号''引起来,不能用双引号。
cat daily_archive.sh | grep '/\$'         # 匹配/$
# 匹配一个手机号
echo "13812345678" | grep ^1[34578][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$ # 匹配一个手机号
echo "138123456780" | grep ^1[34578][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$                                      # 匹配失败
echo "15912345678" | grep ^1[34578][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$ # 匹配成功
echo "138123456780" | grep ^1[34578][0-9]{9}$                                      # 这里使用拓展的正则表达式,但是不支持,需要加-E
echo "138123456780" | grep -E ^1[34578][0-9]{9}$                                    # 加上-E之后就支持这种{}表示次数的写法了

文本处理工具

cut

cut 的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出。

基本用法

cut [选项参数] filename
# 说明:默认分隔符是制表符
vim cut.txt
dong shen
guan zhen
wo wo
lai lai
le le
cat cut.txt
# dong shen
# guan zhen
# wo wo
# lai lai
# le le
cut -d " " -f 1 cut.txt                    # 按空格分割,提取第一列
# dong
# guan
# wo
# lai
# le
cut -d " " -f 2,3 cut.txt                 # 按空格分割,提取第2,3列
# shen
# zhen
# wo
# lai
# le
cat /etc/passwd | grep bash$                # 信息太多
cat /etc/passwd | grep bash$ | cut -d ":" -f 1,6,7
cat /etc/passwd | grep bash$ | cut -d ":" -f 1-4                                   # 按:分割,提取1到4列
cat /etc/passwd | grep bash$ | cut -d ":" -f 4-
# 提取4列到最后
cat /etc/passwd | grep bash$ | cut -d ":" -f -4                                     # 提取第4列到开头的列
echo $PATH                                # /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
echo $PATH | cut -d ":" -f 2-             # /usr/local/bin:/usr/sbin:/usr/bin:/root/bin
echo $PATH | cut -d ":" -f 3-             # /usr/sbin:/usr/bin:/root/bin
ifconfig
ifconfig ens33
ifconfig ens33 | grep netmask             #         inet 192.168.126.100 netmask 255.255.255.0 broadcast 192.168.126.255            筛选出了有ip地址的行
ifconfig ens33 | grep netmask | cut -d " " -f 10                                     # 192.168.126.100        这样就剪切出了IP,前面有空格,所以是10
ifconfig
ifconfig | grep netmask | cut -d " " -f 10    # 提取出了所有的IP地址
# 192.168.126.100
# 127.0.0.1
# 192.168.122.1

选项参数说明

选项参数功能
-f列号,提取第几列
-d分隔符,按照指定分隔符分割列,默认是制表符"\t"
-c按字符进行切割 后加加 n 表示取第几列 比如 -c 1

案例实操

数据准备


切割 cut.txt 第一列


切割 cut.txt 第二、三列


在 cut.txt 文件中切割出 guan


选取系统 PATH 变量值,第 2 个“:”开始后的所有路径:


切割 ifconfig 后打印的 IP 地址


awk

一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。

基本用法

awk [选项参数] '/pattern1/{action1} /pattern2/{action2}...' filename
# pattern:表示 awk 在数据中查找的内容,就是匹配模式 # pattern其实是正则表达式
# action:在找到匹配内容时所执行的一系列命令
which awk                              # /usr/bin/awk
ll /usr/bin | grep awk                 # awk->gawk       awk链接指向了gawk,awk实际上用的是gawk,gawk是awk的GNU版
cat /etc/passwd | grep ^root | cut -d ":" -f 7                                    # /bin/bash                      截取
cat /etc/passwd | awk -F ":" '/^root/ {print $7}'                                 # awk -F指定按什么分割,如果不指定,默认按空格分割,'/pattern/ {}'   pattern是正则表达式,{}里面放执行的代码,直接输出第7列 print $7 , awk一个工具代替了grep和cut两个命令
cat /etc/passwd | grep ^root | cut -d ":" -f 1,6,7                                # root:/root:/bin/bash    这样只能按原来的输出,如果想在1 6 7中间加逗号,这样grep和cut就没法实现了
cat /etc/passwd | awk -F ":" '/^root/ {print $1","$7}'                       # root,/bin/bash         用awk就可以在中间加东西,它会按照$1","$7的格式输出第1列和第7列
cat /etc/passwd | awk -F ":" '/^root/ {print $1","$6","$7}'                  # root, /root,/bin/bash             同样,这样可以输出1 6 7 列
cat /etc/passwd | awk -F ":" '{print $1","$7}'                              # 所有行的第1列和第7列
cat /etc/passwd | awk -F ":" 'BEGIN{print "user, shell"}{print $1","$7} END{print "end of file"}'                        # 在输出的时候在头部输出 user, shell 在尾部输出end of file
cat /etc/passwd | awk -F ":" '{print $3}'  # 打印出所有的ID
cat /etc/passwd | awk -F ":" '{print $3+1}'                                  # 打印出所有的ID+1
cat /etc/passwd | awk -F ":" '{print $3+2}'                                  # 打印出所有的ID+2,如果又想改ID+n,就又得改命令
cat /etc/passwd | awk -v i=1 -F ":" '{print $3+i}'                          # 这样就不用一直改命令了,只要传参数,且在{}中不需要加$i,直接写i
cat /etc/passwd | awk -v i=2 -F ":" '{print $3+i}'                           # ID+2
cat /etc/passwd | awk -F ":" '{print "文件名:"FILENAME "行号:"NR "列数:"NF}'       # 所有的文件名都是-,因为这里是管道操作,利用内置变量获取
awk -F ":" '{print "文件名:"FILENAME "行号:"NR "列数:"NF}' /etc/passwd           # 直接传入,文件名就可以直接显示了
ifconfig | grep -n ^$                    # 用grep显示空行的行号,且打印出的行号后面有冒号
# 9:
# 18:
# 26:
ifconfig | awk '/^$/ {print NR}'                    # awk没有冒号
# 9
# 18
# 26
ifconfig | awk '/^$/ {print "空行:"NR}'   # 按照格式
# 空行:9
# 空行:18
# 空行:26
ifconfig ens33 | grep netmask             # 之前用cut剪切IP
ifconfig ens33 | grep netmask | cut -d " " -f 10
ifconfig | grep netmask | cut -d " " -f 10
ifconfig | awk '/netmask/ {print $2}'      # awk默认就是按照空格分割的,awk不用想cut一样要考虑前面的空格,直接$2

选项参数说明

选项参数功能
-F指定输入文件分隔符
-v赋值一个用户定义变量

案例实操

数据准备


搜索 passwd 文件以 root 关键字开头的所有行,并输出该行的第 7 列。


搜索 passwd 文件以 root 关键字开头的所有行,并输出该行的第 1 列和第 7 列,中间以“,”号分割。


注意:只有匹配了 pattern 的行才会执行 action。

只显示/etc/passwd 的第一列和第七列,以逗号分割,且在所有行前面添加列名 user,shell 在最后一行添加"dahaige,/bin/zuishuai"。


注意:BEGIN 在所有数据读取行之前执行;END 在所有数据执行之后执行。

将 passwd 文件中的用户 id 增加数值 1 并输出


awk 的内置变量

变量说明
FILENAME文件名
NR已读的记录数(行号)
NF浏览记录的域的个数(切割后,列的个数)

案例实操

统计 passwd 文件名,每行的行号,每行的列数


查询 ifconfig 命令输出结果中的空行所在的行号


切割 IP


综合应用案例

发送消息

我们可以利用 Linux 自带的 mesg 和 write 工具,向其它用户发送消息。

需求:实现一个向某个用户快速发送消息的脚本,输入用户名作为第一个参数,后面直接跟要发送的消息。脚本需要检测用户是否登录在系统中、是否打开消息功能,以及当前发送消息是否为空。

脚本实现如下:

#!/bin/bash

login_user=$(who | grep -i -m 1 $1 | awk '{print $1}')

if [ -z $login_user ]
then
	echo "$1 不在线!"
	echo "脚本退出.."
	exit
fi

is_allowed=$(who -T | grep -i -m 1 $1 | awk '{print $2}')

if [ $is_allowed != "+" ]
then
	echo "$1 没有开启消息功能"
	echo "脚本退出.."
	exit
fi

if [ -z $2 ]
then
	echo "没有消息发出"
	echo "脚本退出.."
	exit
fi

whole_msg=$(echo $* | cut -d " " -f 2- )

user_terminal=$(who | grep -i -m 1 $1 | awk '{print $2}')

echo $whole_msg | write $login_user $user_terminal

if [ $? != 0 ]
then
	echo "发送失败!"
else
	echo "发送成功!"
fi
exit
who am i                                  # 查看自己的用户信息
who                                       # 查看所有的用户
who am i
who                                       # 打开atguigu用户的连接之后,查看所有用户
mesg                                      # 查看消息接收是否开启
who -T                                    # 用户有"+",就是打开消息接收了,CentOS是默认开启的,ubuntu是默认关闭的
# root     + pts/0   2022-03-18 14:33 (192.168.126.1)
# atguigu  + pts/1   2022-03-18 18:58 (192.168.126.1)
mesg n                                    # 关闭mesg
who -T                                     # root就变成"-"
# root     - pts/0   2022-03-18 14:33 (192.168.126.1)
# atguigu  + pts/1   2022-03-18 18:58 (192.168.126.1)
mesg y                                      # 开启mesg
who -T
# root     + pts/0   2022-03-18 14:33 (192.168.126.1)
# atguigu  + pts/1   2022-03-18 18:58 (192.168.126.1)
who -T                                    # 如果再开一个atguigu的控制台
# root     + pts/0   2022-03-18 14:33 (192.168.126.1)
# atguigu  + pts/1   2022-03-18 18:58 (192.168.126.1)
# atguigu  + pts/2   2022-03-18 18:58 (192.168.126.1)
write atguigu pts/1                       # 后面要传入控制台pts/1,因为一个用户可以开多个控制台,如atguigu有pts/1和pts/2
# hi, atguigu
# hello
# a^Hh^H^H^H          # 这里按tab键,被认为是非法字符
# how are you
vim send_msg.sh                           # 写一个脚本文件,以后发送消息就可以直接调用脚本,不用想前面的
#!/bin/bash

# 查看用户是否登录
login_user=$(who | grep -i -m 1 $1 | awk '{print $1}')   # 命令替换,grep -i 是忽略打消写 -m 后面加数字,是获取多少行

if [ -z $login_user ]     # 判断login_user有没有,-z判断是否为空,判断login_user里面有没有,是不是空
then
	echo "$1 不在线!"
	echo "脚本退出.."
	exit
fi

# 查看用户是否开启消息功能
is_allowed=$(who -T | grep -i -m 1 $1 | awk '{print $2}')

if [ $is_allowed != "+" ]
then
	echo "$1 没有开启消息功能"
	echo "脚本退出.."
	exit
fi

# 确认是否有消息发送
if [ -z $2 ]
then
	echo "没有消息发出"
	echo "脚本退出.."
	exit
fi

# 从参数中获取要发送的消息
whole_msg=$(echo $* | cut -d " " -f 2- )   # $*全部参数

# 获取用户登录的终端
user_terminal=$(who | grep -i -m 1 $1 | awk '{print $2}')

# 写入要发送的消息
echo $whole_msg | write $login_user $user_terminal

# 判断发送是否成功
if [ $? != 0 ]
then
	echo "发送失败!"
else
	echo "发送成功!"
fi
exit
chmod u+x send_msg.sh
./send_msg.sh
# 用法: grep [选项]... PATTERN [FILE]...
# 试用'grep --help'来获取更多信息。
#  不在线!
# 脚本退出..
./send_msg.sh xiaoming
# xiaoming  不在线!
# 脚本退出..
./send_msg.sh atguigu
# 没有消息发送
# 脚本退出..
./send_msg.sh atguigu hi, atguigu
# 发送成功!
./send_msg.sh atguigu boss is coming
# 发送成功!
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值