1. Linux的文件权限
对于每一个文件来说,使用它的用户主要分为三个类别:文件的拥有者、文件所属群组中的用户、其他用户。另外,root用户是比较特别的,他拥有特别大的权利。 如果需要root的权限,可以使用 su - 这个指令来切换身份。处理完毕后使用 exit 退出。
使用ls命令查看当前工作目录下的文件信息:
dr-xr-x---. 5 root root 248 Jul 23 10:47 .
dr-xr-xr-x. 17 root root 224 Jan 27 2023 ..
-rw-------. 1 root root 2843 Jan 27 2023 anaconda-ks.cfg
-rw-------. 1 root root 1561 Jan 31 2023 .bash_history
...
前十个字符中,第一个表示文件(-)、目录(d)、链接(l)等,接下来的九个字符中,每三个一组就分别代表了三种用户的权限:r表示读权限、w表示写权限、x表示可执行权限,另外,-代表没有该种权限。 相关命令:
- chgrp:改变文件所属的群组
- chown:改变文件拥有者
- chmod:改变文件的权限(rwx分别对应4,2,1)
对于文件来说:
- r:可以读取该文件的内容。
- w:可以编辑该文件的内容(不能删除)
- x:该文件可以被执行
对于目录来说:
- r:可以查询该目录下的文件名
- w:可以创建删除新的文件、目录;对已存在的文件和目录更改名字等;
- x:可以进入该目录作为工作目录(cd进来)
2. Linux文件和目录管理
一些特殊的目录:
. 此层目录
.. 上一层目录
- 前一个工作目录
~ “目前使用者身份”所在的主文件夹
一些常见的处理目录的指令:
cd:变换目录
pwd:显示目前目录
mkdir:创建新的目录
rmdir:删除空目录
2.1 文件与目录管理
使用ls来查看目录下的内容,常用到 -l
使用cp复制文件或目录,默认复制出的新文件与来源文件的权限是不同的,新文件的拥有者是指令操作者。
使用rm来删除文件或者目录
使用mv来移动文件与目录,或者更名
使用basename、dirname取得路径的文件名和目录名
2.2 文件内容查阅
使用cat查看文件内容
使用tac(cat反过来)从后往前查看文件内容
使用more、less(更常用)查看文件内容(可以翻页)
使用head、tail查看文件的头部、尾部多少行内容(使用tail -f xxxx来持续检测文件内容,新写入的数据都会被显示到屏幕上)
使用touch来创建文件或者修改文件的时间属性为当前(mtime文件修改时间、atime文件读取时间)
2.3 文件与目录的默认权限和隐藏权限
使用 umask 命令查看或者设置当前使用者在创建文件或目录时的权限默认值。在默认权限的属性上,目录与文件是不一样的。另外,该命令显示的是被拿掉的值。例如,umask为022,则user没有被拿掉任何权限,group和others被拿掉了2的权限。
使用chattr设置文件隐藏属性,chattr +i 可以让文件“不能被删除、改名、修改内容”,连root都不能。
使用isattr显示文件隐藏属性。
另外,文件还存在一些特殊权限:SUID、SGID、SBIT
- SUID:当s出现在文件拥有者的x权限时:“-rwsr-xr-x”,此时就叫做Set UID简称为SUID。SUID有这样的功能与限制:1. 执行者将具有该程序拥有者的权限。2. 本权限只在执行该程序的过程中有效。3. 执行者对于该程序需要具有x的可执行权限。 例子:虽然记录密码的文件/etc/shadow只有root可读且修改,但是普通用户也可以修改自己的密码呀。这不相当于普通用户修改了shadow文件吗?其实,这里就涉及到了SUID。普通用户在执行的过程中暂时过得了root权限。
- SGID:显然,当这个s出现在group的x位置的时候,就叫做SGID,出现在文件中:1. 程序的执行者对于该程序来说,需要具备x的权限。2. 执行者在执行的过程中将会获得该程序群组的支持;出现在目录中:使用者在此目录下的有效群组将会变成该目录的群组。
2.4 指令与文件的搜索
使用which命令寻找可执行文件的文件名(根据PATH环境变量)
使用whereis命令查找文件或者目录(比find命令快很多,因为前者只在特定的几个目录里边寻找,后者全盘搜索)
(常用)使用locate命令查找文件或者目录,输入部分名称也能得到结果。(如果数据库没有及时更新,可能导致搜索不到目标文件。可以使用updatedb命令手动更新数据库)
使用find命令查找文件。可包含时间参数,例如查找四天内被修改过的文件。
2025.8.14
3. 定时任务调度
使用 crond、atd 来完成定时任务调度:
- Crond 执行周期性任务
- 使用 crontab -e 编辑内容,创建周期性任务
- 使用 crontab -l 查看任务
- Atd 执行一次性定时任务
- 使用 at 指令指定任务
- 使用 atq 查看任务队列
4. Linux文件系统底层
Linux操作系统的文件除了实际内容外,还有非常多的属性,例如文件权限(rwx)、文件属性(拥有者、群组、时间参数等),文件系统通常将这两部分数据分别放在不同的区块,权限和属性放在 inode 中,实际数据放在 data block中。另外,还有一个 superblock 用于记录整个文件系统的整体信息:
- superblock: 记录此filesystem的整体信息,包括inode/block的总量、使用量等;
- inode:记录文件属性,一个文件占用一个inode,同时记录此文件的数据所在block号码;
- block:实际记录文件的内容,若文件太大,会占用多个block。一个block最多存放一个文件的数据。
以上被称为索引式文件系统。而U盘一般使用的文件系统叫FAT格式,这种格式没有inode,每一个block都会记录下一个block的位置 假设文件的数据依次写入1、7、4、15这四个block,但是这个文件系统没办法一口气直到这四个号码,它得一个一个地读。所以如果一个文件的数据写得太过分散时,磁盘就需要转好几圈才能读取到所有数据,效率低。
继续介绍Ext2文件系统(Linux),其分为多个block group,每一个group都有独立的inode、block、superblock。
当我们创建一个目录时,文件系统会分配一个inode和至少一块block给该目录。其中inode用于记录该目录的相关权限与属性;而block则是记录在这个目录下的文件名与该文件名占用的inode号码数据。
所以文件的名字实际是存储在目录的block中的。
读取文件或者目录的流程:inode和block反复跳转。。。。 新建文件或者目录的流程:查看权限,查看inode bitmap,哪里有未使用的inode?查看block bitmap,哪里有未使用的block?
5. Shell script
shell有多个版本,/bin/sh /bin/bash... 通常是使用bash。在shell脚本中,通常以 #!/bin/bash开始。表明使用/bin/bash执行。如下:
#!/bin/bash
写好xxx.sh文件后,有几种执行它的方法。第一种是使用bash工具,如下:
bash xxx.sh
第二种是直接将这个xxx.sh的属性修改为可执行文件,然后直接运行它(这是常用方法):
chmod +x xxx.sh
./xxx.sh
# 这里的./只是为了防止直接写出xxx.sh,它会误认为xxx.sh是一个linux命令。
以上两种方法都会在当前的bash环境中创建一个子bash,那么父bash中的局部变量啊啥的就无法在子bash中使用了(全局变量还可以)。下面的两种方法,就不会创建父子bash环境,而是直接在大bash环境中执行:
source xxx.sh
# or
. xxx.sh
5.1 变量
通常来说,shell中的系统变量都以大写字母来表示,例如:
$HOME $HOSTNAME
可以使用 set 命令来查看bash环境中的局部变量和全局变量:
set
用户自己定义局部变量,规范如下:
# 等号两边不要有空格
my_var="hello, world"
# 修改值就直接修改
my_var=hello
# 使用变量这个值的时候,需要加一个$符号
echo $my_var
# 使用export,将局部变量提升为全局变量
export my_var
此时,在子bash中就可以看到这个my_var了。但是,子bash中的修改对其不起作用。
可以使用readonly将变量设置为常量,如下:
readonly a=hello
a=tyy # 报错
使用unset将一个变量清除掉:
b=hello
unset b
echo $b # 没有了
在bash中,默认所有的变量都是字符串类型,比如:
x=1+5
echo $x # 结果为1+5,而不是6
5.2 shell脚本参数
在bash中,每当你输入一个命令:
ls
系统会在一个特定的路径去寻找这个命令,有就执行,没有就报错。这个路径就是$PATH:
echo $PATH
# 结果:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
所以,如果你将自己写的xxx.sh放到其中的某一个路径下:
cp xxx.sh /bin/ # 将xxx.sh复制到根目录下的bin中
那么就可以实现,直接输入xxx.sh,就可以当做是一个命令一样去执行:
xxx.sh
# 输出xxx.sh中的结果
使用$n可以获取脚本的参数:
echo "name of script: $0" # 其中$0比较特殊,会输出脚本的名称xxx.sh
echo "the first parameter: $1"
echo "the second parameter: $2"
使用$#可以获取脚本的参数个数,常用于循环:
echo $#
使用$*, 和$@都可以获取脚本的所有参数,只是前者返回的是一个整体(比如“a b c”),而后者相当于返回一个参数的集合(比如[a, b, c])
echo $@
echo $*
5.3 数值运算
在bash中,想要使用数值运算,可以将运算写在$[]中,例如:
#!/bin/bash
a=10
s=$[a + 2] # 也可以使用$(())
echo $s # 得到结果12
5.4 判断、循环等逻辑
在bash中,如果想要执行条件判断,可以使用 test condition,或者 [ condition ](通常使用这个),例如:
#!/bin/bash
a=10
s=$[$a + 2]
test $s = 12 # 或者 [ $s = 12 ],中括号里边一定要各有一个空格
echo $? # 使用$?可以返回上一条命令执行的结果,0为true
使用 -lt -gt -eq等等判断数值(less than, greater than, equal)
使用 -r -w -x 判断文件的权限
[ -r xxx.sh ] # 判断xxx.sh是否有可读的权限?
使用 -e 判断文件是否存在(existence), -f 文件存在,且是一个常规文件, -d 文件存在而且是一个目录
#!/bin/bash
[ -e /bin/bash ]
echo $? # 得到0,表示存在
下面这句话可以起到java中的三目运算符的效果:
a=20
[ $a -gt 15 ] && echo "$a > 15" || echo "$a < 15"
# 输出20 > 15
条件判断,格式如下:
#!/bin/bash
str="chr"
if [ $str = "chr" ]
then
echo "welcome, chr"
fi
多条件判断,如下:
if [ a -gt 12 ] && [......] || [....]
then
do something
fi
如果想要把条件都放在一个括号里边,可以使用 -a 或者 -o连接。(and和or)
#!/bin/bash
age=140
if [ $age -lt 18 ]
then
echo "未成年"
elif [ $age -lt 35 ]
then
echo "青年人"
elif [ $age -lt 60 ]
then
echo "壮年人"
else
echo "老年人"
fi
多分支,使用case:(注意两个分号哦)
#!/bin/bash
number=3
case $number in
1)
echo "one"
;;
2)
echo "two"
;;
*)
echo "else"
;;
esac
for 循环:
#!/bin/bash
for animal in dog cat elephant
do
echo "there are ${animal}"
done
while 循环:
#!/bin/bash
while [ "${yn}" != "yes" ]
do
read-p "infor" yn
done
6. Linux 磁盘分区、挂载
Linux 使用“载入”的方法将硬盘的一个分区与文件系统的一个目录联系起来。
Linux 硬盘分为 IDE 硬盘和 SCSI 硬盘,其中 SCSI 硬盘的标识为 “sdx~”,比如 sda1 表示基本盘(“a”)的第一个分区,sdb3 表示从属盘的第二个分区。
使用 lsblk 命令 查看所有设备的挂载情况
6.1 如何增加一块硬盘?
- 添加一块硬盘
- 分区
- 使用命令 fdisk 对硬盘分区。例如新添加了一块硬盘 sdb(通常放置在 /dev/ 下),可以使用 fdisk /dev/sdb 对其进行分区
- 格式化(在分区上创建文件系统)
- 使用命令 mkfs 对硬盘进行格式化。例如 mkfs -t ext4 /dev/sdb1
- 挂载
- 使用 mount 命令将分区挂载到目录上。例如将 sbd1 分区挂载到 /newDist 目录上:mount /dev/sdb1 /newDist
- 可以使用 umount 卸载:umount /dev/sdb1
- 使用指令挂载分区,重启之后挂载会失效
- 设置自动挂载
- 编辑 /etc/fstab 文件,可以将分区自动挂载到目录
使用 df -h 查看磁盘使用情况
使用 du -h 指令查询指定目录的磁盘占用情况
一些常用指令:
- 统计 /data 下文件的数量
ll /data | grep '^-' | wc -l
- 统计 /data 下目录的个数
ll /data | grep '^d' | wc -l
- 使用 tree 指令以树状图查看目录情况
7. Linux账号管理
每一个登录的使用者都会取得两个ID:一个user id,一个 group id。
一个用户可以同时存在多个群组中,那当这个用户创建一个文件后,该文件的群组是?(是用户当前的有效群组,使用groups命令查看,第一个群组就是有效群组) 可以使用newgrp来切换有效群组(会切换进入一个新的shell)
Linux的账号信息多涉及到:
- /etc/passwd
- /etc/shadow
- /etc/group
- /etc/gshadow
使用 useradd 命令添加用户,在centos7中,每一个新用户newUser在/home目录都会有一个主文件夹。(比如用户chr的主文件夹为/home/chr)
使用 usermod 来修改用户相关
使用 userdel 删除用户
使用 id 查询某人或自己的UID等相关信息
groupadd, groupmod, groupdel
7.1 ACL
在linux中使用ACL来实现颗粒度更细的权限分配(以前只能在所有者、群组以及其他人这三个范围内修改权限)
使用
- getfacl
- setfacl
[root@study ~] setfacl -m u:vbird1:rx acl_test1
[root@study ~] ll acl_test1
-rw-r-xr--+ 1 root root 0 Jul 21 17:33 acl_test1
# 权限部分多了个 + ,且与原本的权限 (644)
[root@study ~]# getfacl acl_test1
# file: acl_test1 <==说明文档名而已!
# owner: root <==说明此文件的拥有者,亦即 ls -l 看到的第三使用者字段
# group: root <==此文件的所属群组,亦即 ls -l 看到的第四群组字段
user::rwx # 使用者列表栏是空的,代表文件拥有者的权限
user:vbird1:r-x # 针对 vbird1 的权限设置为 rx ,与拥有者并不同!
group::r-- # 针对文件群组的权限设置仅有 r
mask::r-x # mask用来规范此文件的最大权限,别人的权限只能是mask这里的子集
other::r-- # 其他人拥有的权限啰!
8. Linux网络配置
网络地址转换 NAT:
虚拟机的 ip 可以和宿主机的虚拟网卡 vmnet8 相互 ping 通,NAT 服务将由虚拟机发送的数据包的源 ip 转换为宿主机的物理网络适配器的 ip 地址。
可以通过修改配置文件来指定 ip,编辑:
vim /etc/sysconfig/network-scripts/ifcfg-ens33
可以通过修改 /etc/hostname 指定主机名
通过修改配置文件,可以建立主机名与 ip 的映射,例如,在 linux 中,可以修改 /etc/hosts 文件,指定某个 ip 与主机名的映射,之后就可以通过主机名来访问对应的 ip。
9. Linux进程管理
Linux中的每一个进程都有一个 pid
使用 ps -aux 命令查看当前所有的进程
其中 STAT 表示进程当前的状态,s 表示 sleeping,r 表示 running,z 表示 僵尸进程(需要定时清除)
TTY 表示终端名称
使用 ps -ef 可以查看到进程的父进程 pid
使用 kill 指令杀死某一个进程,使用 killall 杀死进程及其子进程
kill 1324
killall gedit
kill -9 423 # 强制 kill
使用 pstree 以树状的形式查看进程
9.1 服务管理
服务本质就是运行在后台的进程,也称为守护进程 daemon(所以多以 d 结尾)。它们通常都会监听某一个端口,等待其他程序的请求。
使用 service 服务名 [start | stop | status ...] 来管理服务(现在很多服务都不再用 service 管理,而是使用 systemctl 管理)
服务的运行级别有七种,常用的级别是3和5:
- 3:多用户状态(有网络),无界面,登录后植入控制台命令行模式
- 5:登录后进入图形GUI模式
使用 systemctl get-default 和 systemctl set-default 设置服务的运行级别
使用 chkconfig 管理各个服务在不同运行级别的自启动情况(同样也是被 systemctl 代替)
9.2 systemctl
几乎所有服务都可以使用 systemctl 管理。具体语法是:
systemctl [start | stop | restart | status] 服务名
Systemctl 管理的服务可以在 /usr/lib/systemd/system 中查看(ubuntu 下是在 /etc/systemd/system)
使用 systemctl list-unit-files 查看服务的自启动状态
使用 systemctl enable/disable 服务名 开启/关闭服务开机自启
使用 systemctl is-enabled 服务名 查询某个服务是否是自启动的
9.3 防火墙
外部客户端想要访问linux中的服务时,会首先被防火墙检测。如果这个服务的端口是对外开放的,则可以访问。反之,访问不了。
telnet 192.168.200.130 111 # 访问这个ip下面的111端口
防火墙比较重要,应该打开。但是有的时候,某一个服务就需要被外部客户端访问,如何将这个服务对外开放呢?
firewall-cmd --permanent --add-port=端口号/协议 # 开放某一个端口
# 关闭、重新载入防火墙、查询端口是否开放等都有相应的指令,这里就不记录了
9.4 动态查看进程
使用 top 动态显示正在执行的进程
使用 P 按照CPU使用率排序,使用 M 以内存使用率排序
输入 u 可以指定查看目标用户相关的进程
输入 k 可以杀死目标进程
9.5 netstat 查看系统网络状况
键入 netstat -anp 可以查看当前系统有哪些服务处于监听状态,哪些服务处于连接状态等
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.1.1:53 0.0.0.0:* LISTEN 1235/dnsmasq
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 5989/sshd
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 3076/cupsd
tcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN 944/postgres
tcp 0 0 127.0.0.1:6010 0.0.0.0:* LISTEN 2715/8
tcp 0 0 192.168.163.129:22 192.168.163.1:51474 ESTABLISHED 2715/8
tcp 0 0 192.168.163.129:22 192.168.163.1:51483 ESTABLISHED 2870/sshd: root@not
# 第八行表示,本地的22端口与外部ip为192.168.163.1,端口号为51483的服务进行了连接
# 协议为tcp协议(且本地的这个服务是sshd)
10. Linux软件包管理
Yum是一个shell前端软件包管理器。基于RPM包管理,能够从指定的服务器自动下载RPM包并且安装,同时它可以自动处理依赖性关系,一次安装所有依赖的软件包。
使用 yum list 查询yum服务器是否有需要安装的软件
下载安装指定的yum包: yum install xxx
(在ubuntu系统中,与yum所对应的是 apt 指令)
当执行 apt install 命令时,linux从远程服务器下载软件包。主要涉及:
- 软件源:软件源通常是官方或者第三方维护的软件仓库,这些服务器上存放着大量的软件包。
- 源列表:Linux系统上有一个配置文件,里面记录了这些软件源服务器的地址。
所以,总结就是:软件包来源于远程的软件源服务器,但 apt
依靠本地的索引数据库来知道该下载什么。(软件被安装后,它的文件就分散到了系统的各个标准位置,而不是集中在一个文件夹里)
apt工具的相关指令有:
- Sudo apt update: 当你执行
sudo apt update
时,apt
工具会连接到源列表中配置的服务器,下载最新的软件包索引列表到本地。(sudo apt update 几乎是必做的一个步骤) - Sudo apt upgrade: 升级所有已安装的软件包。
- Sudo apt install <package name="">: 安装指定软件包。
- Sudo apt remove <package name="">: 卸载指定软件包。
- apt search <keyword>:在软件源中搜索包含关键字的软件包。
11. Linux日志管理
在Linux系统中,日志文件通常是存储在 /var/log 下面。其中日志文件较多,重要的日志文件主要有:
/var/log/syslog
- 系统的“万能日志”,几乎所有服务和内核消息都会写入这里。
- 用来查看大部分系统运行时信息和排错。
/var/log/auth.log
- 记录认证相关日志,例如 SSH 登录、
sudo
使用、用户登录和失败尝试。 - 对安全审计非常关键。
/var/log/kern.log
- 内核日志,记录内核产生的消息。
- 当涉及驱动、硬件问题时非常重要。
/var/log/dmesg
- 系统启动时内核检测硬件的输出信息。
- 经常用来排查设备驱动加载和硬件识别问题。
/var/log/apt/history.log
- 记录通过 APT(包管理器)进行的软件安装、升级和卸载操作。
- 用于追踪系统软件变动历史。
/var/log/dpkg.log
- 更底层的包管理日志,记录 dpkg 的具体操作。
- 结合
apt/history.log
可以完整了解系统软件变动。
/var/log/Xorg.0.log
- X Window(图形界面)的日志文件。
- 图形界面启动失败时,常要查看这里。
日志管理服务 rsyslogd
负责将日志写入 /var/log/*.log
中去,它通过配置文件 /etc/rsyslog.conf
决定将不同的日志信息写入到不同的日志文件中。
- 查询Linux中的rsyslogd服务是否启动
ps aux | grep "rsyslog"
- 查询rsyslogd服务的自启动状态
systemctl list-unit-files | grep "rsyslog"
在ubuntu中,重要的配置文件在/etc/rsyslog.d/*.conf
中,如下:
其中的格式是:
*.* 存放日志文件
第一个*代表日志类型,比如auth、corn、kern、mail等
第二个*代表日志级别,比如debug、info、emerg等
具体的日志信息如何看?
Aug 24 22:47:42 ubuntu sshd[4699]: Accepted password for root from 192.168.163.1 port 49709 ssh2
日期 主机 服务 具体信息
(在现代Ubuntu中,很多系统服务的日志是先写到systemd-journald,再由它转发给rsyslog)
11.1 日志轮替
在Ubuntu中,日志轮替主要是依靠 logrotate 工具来完成,它的配置文件在 /etc/logrotate.conf
,这里用于存放所有日志的轮替规则。同时, /etc/logrotate.d/
下可以单独为某些日志存放轮替规则。
日志轮替怎么运行的?
以 /var/log/syslog
为例:
当前日志文件满了,logrotate 会:
- 把
syslog
重命名为syslog.1
- 创建一个新的空白
syslog
文件(继续写入) - 旧的
syslog.1
可以再压缩成syslog.1.gz
- 更老的可能是
syslog.2.gz
,syslog.3.gz
……
保留时间与数量
- 通过配置指定,比如“保留 7 天日志”或者“保留 4 个历史文件”。
配置文件大概长这样:
# /etc/logrotate.d/rsyslog
/var/log/syslog
{
rotate 7
daily
missingok
notifempty
delaycompress
compress
postrotate
invoke-rc.d rsyslog rotate > /dev/null
endscript
}
rotate 7
→ 保留 7 个旧日志daily
→ 每天轮替一次missingok
→ 如果日志不存在,不报错notifempty
→ 如果日志为空,就不轮替compress
→ 用 gzip 压缩旧日志delaycompress
→ 延迟一轮再压缩(避免刚写完的日志立刻压缩)postrotate … endscript
→ 通知 rsyslog 重新打开日志文件