# 文件系统与权限模型

Linux 的权限模型基于用户和用户组的概念,每一个用户都有唯一的用户 ID (uid) 以及唯一的组 ID (gid)。文件和目录的权限由所属的用户和用户组来决定

同时也存在访问控制列表(ACL), 可以精细的控制文件和目录的权限

# 文件权限

# 基本权限标记

每个文件具有三种权限:属主权限,所属组织权限,其他用户权限

常见的文件权限标记:

r,w,x (执行权限),-(空)

删除文件算在 w,但是取决于所在目录权限,而不是本文件的权限

这一点和 windows 不一样,windows 每个文件都有独立的 ACL, 当没有从父目录继承权限或者被单独修改时,是不能被删除的 —— 但是,父目录也必须有权限!这是基础条件

这些标记每三个一组,依次对应一种文件权限,共三组:

rwxr-w---

也用三个八进制数字来表达:

r=4,w=2,x=1,将值相加得到最终该种权限的值

所以上面的权限也可以表示为:

750

chmod -R 755 ddd.txt //-R表示递归
find /home/user/project -type f -exec chmod 644 {} \; //对于文件夹可以用find区分文件类型赋予权限

PS:chmod 只能用于修改本用户所属的文件(除非是 root 组),chown 仅限 root 组

当查看文件权限时,前面通常还有一位

1758095242420

表示文件类型,有一下几种:

1758095981596

通过 ls -all 来查看

# 特殊权限标记
# SUID

Set User ID, 允许普通用户临时获得属主权限

# SGID

Set Group ID, 作用于目录,里面的文件和目录会继承属组

# Sticky

粘滞位,只用于目录,比如 /temp 文件夹,只允许用户删除自己的文件,一般配合 777 使用

以上三种都是用特殊符号位表示

//SUID,撤销时+改-或者数字改0,下面同理
chmod u+s xxx  
chmod 4755 xxx
//SGID
chmod g+s xxx
chmod 2755 xxx
//Sticky
chmod o+t xxx
chmod 1755 xxx

PS:没有 x 权限时 s/g 会显示为大写,此时 SUID/SGID 无效,这是 t 实际上也会大写,不符合共享的目的,虽然依旧生效但是这个用户(组)没法访问,更没法操作。

# 进程管理

ps 
top #顺带显示系统性能信息,这是交互式的
kill #默认是 pid
killall #这个是终止指定名称,不是全杀,可以 - u,-r (正则)
pgrep   #根据名字找 ID
pkill #也是根据进程名,但是是部分匹配,也可以 - u,-t,-p,-f
nice #设置进程优先级
renice #设置正在运行的进程的优先级
nohup #运行进程,并且用户注销后继续运行
bg/fg #放到后台 / 前台运行,只认作业号而不是 pid

# PS

ps -aux #显示所有用户的所有进程
ps -ef #显示完整格式
ps -e --forest #树形结构显示进程关系

1758099705675

STAT 是进程状态:

S:等待态
T:停止态
R:运行态
Z:僵尸态
D:不可被中断的等待态进程
X:死亡态
s:拥有子进程的进程
I (大写 i):闲置在内核的进程
l (小写 L):拥有子线程的进程
<:高优先级的进程
N:优先级较低的进程
+:运行在前台的进程

# kill

kill -1/hangup pid #挂起,用于重启或重新加载
kill -2/interrupt pid #中断,就是发个 Ctrl+C
kill -3/quit pid #退出,就是发个 Ctrl+\
kill -9 pid #强制终止(SIGKILL)
kill -15/terminate pid #发送终止信号
kill -17/stop pid #暂停
kill -18/cont pid #继续,作用于之前被暂停的进程

# top

top -c #显示完整命令,正常只会输出运行的命名,-c 可以显示路径和参数 
top -b #假设这是批处理,刷新是再此输出,容易被刷屏
top -S #累计模式,没看出什么区别
top -n 2 #只更新两次就退出
top -d 3 #每 3 秒更新
top -p pid #指定进程
#运行后也可以按 c 切换是否显示完整命令

1758101515643

# jobs

查看后台运行的作业状态( bg

jobs -l  #详细显示,有显示 pid
jobs -p xxx #仅显示作业的进程组 IDvomy
jobs -n  #只显示和上次状态不同的部分
jobs -r  #只显示运行中的
jobs -s  #只显示已停止的

1758103790007

tip:使用 Ctrl+Z 暂停,1 就是作业号,% 可以省略(只是为了防止和 pid 混淆,如果使用 kill 等其他命令来操作作业的话就不能省略)

# 启动三个后台任务
$ sleep 100 &
$ sleep 200 &
$ sleep 300 &
# 查看所有作业
$ jobs -l
[1]   12345 running    sleep 100 &
[2]  -12356 running    sleep 200 &
[3]  +12367 running    sleep 300 &
# 将作业 2 恢复到前台
$ fg %2
# 终止作业 3
$ kill %3

1758106239637

默认情况下后台作业和终端会话关联,使用 nohup xxx & 即可避免

引用作业:

%x 作业x
%+/%% 当前作业
%- 前一个作业

jobs 只显示当前 shell 会话中的作业,ps 会直接显示所有,包括其他用户和终端的进程

# 实践

为后台作业重定向输出,避免干扰当前终端

command > output.log 2>&1 &

重要作业使用 nohup,确保终端断开后继续运行

nohup important_command &

# 网络配置

# iptables

包过滤 + 防火墙

# 结构

1758380308482

1758380325791

1758380344525

这个命令的语法:

iptables [-t 表名] <命令> <链名> [规则号] [匹配条件] [-j 目标动作]
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.0.100:80
//将访问自身8080端口tcp协议的包发送到内网另外一台机器的80端口
#-A 对应命令,即追加操作,-p 匹配协议头

类似的:

iptables -A INPUT -s 192.168.1.100 -p tcp --dport 22 -j ACCEPT
#filter 是默认表
# 基本操作

查看

#-L 列出所有链,-n 和 - v 同 ss 中的作用,使用默认表(filter)
iptables -L -n
# 更详细的查看,显示规则编号和更多信息
iptables -L -n -v
# 查看 nat 表的规则
iptables -t nat -L -n

清空规则

iptables -F INPUT
iptables -F   #清除所有链的规则
iptables -t nat -F #清除对应表的所有链的规则

删除规则

iptables -L --line-numbers #查看编号
iptables -D INPUT 3  #使用编号删去
# 使用测试
# 设置默认策略(先允许所有,避免被踢出)
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -F # 清空现有规则
# 2. 允许所有本地回环 (lo) 接口的通信,-l 匹配网口
iptables -A INPUT -i lo -j ACCEPT
# 3. 允许已建立的和相关连接通过(响应请求)-m 加载拓展
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 允许外部 ping 本机
iptables -A INPUT -p icmp -j ACCEPT
#开放 SSH 端口 (22),只允许特定 IP(如 192.168.1.100)访问
iptables -A INPUT -p tcp --dport 22 -s 192.168.1.100 -j ACCEPT
# 如果允许所有 IP 访问 SSH,则用下面这条
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
#再次设置默认策略,不影响上面特别设置的
iptables -P INPUT DROP
iptables -L -n -v

1758381523601

# PS
iptables -t nat -A PREROUTING -p tcp  -j DNAT --to-destination xxx.xxx.xxx.xxx:xxx
#这样你就可以随便把什么连接到这台机子的发送到其他地方

# netstat

显示当前开放的端口

-t TCP
-u UDP
-n --numeric 直接使用IP和端口号,不用DNS
-l 仅列出监听状态的网络服务
-a 列出所有
-r --route 列出所有路由列表,等同于route
-s 网络统计信息
-o 显示计时器
-i 显示网络界面信息表单
-M 显示伪装的网络连线
-w 显示RAW传输协议的连线情况
-v 显示命令执行过程
可以组合使用
-tuln -an  -rn 
-A <网络类型> --<网络类型>
	-A unix(等效于 -x --unix)	-A inet(等效于 -ip --inet) 
netstat -rn 和route -n是一样的

# ss

和netstat类似。
-K, --kill:通过 Inode号 杀死指定的 socket,实际上可以结合其他的
-a, --all:显示所有的套接字,包括监听和非监听的。
-t, --tcp:仅显示 TCP 套接字。
-u, --udp:仅显示 UDP 套接字。
-l, --listening:仅显示监听状态的套接字。
-p, --processes:显示与套接字关联的进程信息。
-n, --numeric:不进行DNS解析,也不尝试寻找对应服务。!!!!!
-r, --resolve:尝试反向解析IP(PTR)并找到已知服务名称。!!!!!
-s, --summary:显示套接字的摘要信息。
-4:仅显示 IPv4 套接字。
-6:仅显示 IPv6 套接字。
-i, --info:显示详细的内部信息。
-o, --options:显示 TCP 计时器信息。
-f, --family=FAMILY:指定协议族(如 inet, inet6, unix, link)。
-m, --memory:显示每个套接字使用的内存。
-H, --no-header:不显示标题行。
-v, --verbose:显示详细的输出。
# 使用测试

1758379159551

这里显示了 Inode 号 (ino 字段), 可以:

ss -k 73
ss -k dport=333978#即 dst port, 同样存在 sport,可以用 >= 等符号比较
ss -k dst :333978  #前面可以是个 IP
ss -k src :327580  #前面为 IP 时表示本机的这个 IP 下的连接

# 其他

连接测试

ping -c<发送次数>
ping6 使用ipv6ping
traceroute 跟踪到目标主机的路径
tracepath 类上,但是无需root
mtr ...
curl 发送HTTP请求
wget 下载
telnet 测试TCP连接
nc 创建TCP/UDP连接以测试端口
dig 查询DNS
nslookup 同上
host 解析域名为IP

流量监控

iptraf 是个交互式的监控工具,需
iftop 实时监控网络接口的带宽使用
nethogs 实时监控每个进程的带宽使用
nload 实时显示网络流量

1758166022049

vnstat   流量统计,-d是查看日流量
tcpdump  捕获分析网络数据包 tcpdump -i eth0

# 服务管理

# systemctl

系统服务管理

用于和 systemd (系统服务管理器,这个进程的 PID 为 1)进行交互,管理进程

start
stop
restart
reload #重新加载配置文件,不重启
status #检查运行状态
enable #加入自启动
disable
is-enabled
is-active #是否正在运行
daemon-reload #对 systemd 的 reload
systemctl list-unit-files --type=service #列出自启动的

# crontab

定时任务管理器

新创建的 cron 任务要至少两分钟后才能执行,也可以通过重启 cron 来立即启动

任务调度分为两类,系统执行的工作,如备份数据,清理缓存以及用户定期要做的工作,可以自行设置

crontab [-u user] file
crontab [-u user] {-l | -r | -e }
参数说明:
-l 查看当前用户的crontab文件
-e 编辑当前用户的crontab文件
-r 删除当前用户的crontab文件
使用-u参数编辑其他人的文件时要拥有相应的权限

格式:

f1 f2 f3 f4 f5 program

1758431827320

实例:

1758433282621

存在输出(包括发生错误的输出)的计划任务执行时会给对应用户发送邮件,可以查看其输出:

1758433410022

如果不想接收或者想要记录到日志,可以重定向

* * * * * /bin/ls > /dev/null 2>&1
#丢弃输出
* * * * * /bin/ls >> /var/log/mycron.log 2>&1
#输出到日志

crontab 可以添加环境变量来解决 shell 脚本不能加载环境变量必须写绝对路径的问题:

* * * * * ./etc/profile;/bin/sh <path_to_your_shell>

# 日志分析

# /var/log

默认日志存放目录,包括:

syslog/messages:系统全局日志

auth.log:认证相关,包括登录 / ssh / sudo 等权限操作

kern.log:内核事件,驱动错误,硬件相关错误

boot.log:启动日志

dbkg.log/yum.log:软件包管理日志

/nginx/

/mysql/

# journalctl

用于管理日志,不带参数则输出所有,默认时间倒序,最新的最后

-f 实时跟踪。类似于tail -f,不过journalctl可以不指定文件
--since "xx" --until "xx" 时间筛选
--since "1 hour ago"

1758435425706

-u nginx/sshd 按服务/单元筛选
-p err 按优先级
#优先级:debug<info<notice<warning<err<crit<alert<emerg
-k 内核日志
# 显示特定进程 ID 的日志
_PID=1234
# 显示特定用户的日志
_UID=1000  
#可以组合起来
-p warning -u nginx -f
-k -f
-u nginx.serive --since yesterday -p err

1758435838850

others:

journalctl --disk-usage  #显示占用空间
journalctl --vacuum-size=100M  # 保留最近 100M 日志
journalctl --vacuum-time=7d    # 保留最近 7 天日志
journalctl -o json #输出为 json
journalctl -o verbose #显示完整字段
# 使用测试
journalctl | less #分页查看
journalctl -b0 | grep "Starting" #tip:本次启动日志(-b)
journalctl -a #查看所有,包括归档的
journalctl --no-pager 
#增加行数限制,避免显示不全(一次性输出,下图效果)

1758436384690

tail 是显示文件内容的,所以要指定文件

tail -c 10 file.txt #读取前 10 个字符
tail -c +10 file.txt #读取最后 10 个字符
tail -n 10 file.txt #读取前 10 行
tail -n +10 file.txt #读取最后 10 行
tail -f --pid=PID
tail -f -s x file.txt #每次反复间隔 x 秒

1758436845160

# 包管理

由于之前刚接触 pip 痛苦了非常久,所以这里就不说包或者依赖什么的

也不解释这些命令是干什么的,如果同样痛苦过的应该一眼就能看懂

# apt

sudo apt

update
upgrade
list --upgradable
upgrade full-upgrade #是删除再安装的更新
install <package_name1> <package_name2>
update <package_name>
show <package_name> #显示其具体信息,包括版本以及依赖关系
remove <package_name>
automove #清理不再使用的包,通常是手动卸载某个包后执行
purge <package_name>
#移除,比 remove 多一个移除配置文件的作用,可以在 remove 后执行 purge,无需重装
serch <keyword>
list --installed
list --all-versions

-y :无需确认,全部都是 yes

special:

install <package_name> --no-upgrade
#如果存在,不要升级
install <package_name> --only-upgrade
#存在时升级,只升级不安装
install <package_name>=<version_number>

# yum

check-update
update #更新所有
install <package_name>
update <package_name>
list #列出所有可安装的
remove
search
clean packages #清除缓存
clean headers #清除 header
clean oldheaders
clean (all)
provides 
#查看文件或者命令的来源,返回包名,版本,来源仓库等。可以模糊查找。可能需要更新缓存(sudo yum makecache)

换源

下载对应系统的 repo 文件,放在 /etc/yum.repos.d/ 然后:

yum clean all
yum makecache

要先备份

# 编译安装

# 流程

首先安装编译器:

sudo apt-get update
sudo apt-get install build-essential
sudo apt-get install make
sudo apt-get install automake
sudo apt-get install libtool
sudo apt-get install gcc g++
通过
dpkg -l | grep <dependency>
检查是否安装成功

如果是交叉编译?

sudo apt-get install gcc-arm-linux-gnueabi
#目标架构的包名

开始:

wget xxxx #下载源码,通常是.tar.gz,怎么来的自己搞
tar -xzvf source-code.tar.gz #解压
ls -l #查看文件结构
./configure #查看配置步骤,这玩意儿是个脚本,会生成 Makefile 文件
建议创建一个目录用于编译
mkdir build && cd build
在构建目录中编译源码,安装
make
make install
#清理构建目录
make clean 
#在源码目录下执行
make distclean

tar 命令:

-x 提取文件

-z 使用 gzip 算法,此外还有 - j(bzip2)-J(xz),--lzip/lzma/lzop/zstd

-v 显示详细过程,可以加上 --progess 显示进度条

-f 指定处理的归档文件名

-a 自动选择压缩方式

-I 使用指定软件进行压缩或者解压

-C 指定解压到的目录,如:/usr/local/

-t 列出里面的内容

-c 创建一个新的归档文件

-r 往归档文件中追加内容

-u 更新归档文件的对应文件

-A 将一个.tar 追加到另一个.tar 中

详见 Linux tar 命令 | 菜鸟教程

# 配置参数

运行 configure 脚本时:

--prefix: 指定安装目录,默认为 /usr/local。
--enable-feature: 启用某个特性。
--disable-feature: 禁用某个特性。
--with-library: 指定使用某个库。
--without-library: 不使用某个库。
--enable-debug: 启用调试信息。
--disable-debug: 禁用调试信息。

例如

./configure --prefix=/usr/local --enable-ssl --with-openssl=/usr/local/openssl
#启用ssl模块。with用于告诉脚本这个依赖库的位置

假设编译安装 python:

# 下载源码并解压后进入目录
./configure \
  --prefix=/usr/local/python3.11 \  # 安装到指定目录
  --enable-optimizations \          # 启用编译优化
  --with-openssl=/usr/local/openssl  # 指定 OpenSSL 库路径
# 编译参数
make CFLAGS="xxx" CXXFLAGS="xxx" LDFLAGS="xxx" MAKEFLAGS="xxx"
#指定 C,C++, 链接器,make 的选项

交叉编译?

make CC=xxxx CXX=xxxx
#xxxx 是目标架构的编译器,不是选项
# 编译器参数

可以是编译选项,优化参数和调式参数

优化参数:

-O0 不优化

-O (1) 基础优化

-O2

-O3 PS: 可能使得体积变大以及导致兼容性问题

-Os 优化体积

调试参数:

-g

-g3 更为详细

-ggdb 使得 gdb 调试信息

# 链接参数

-static

静态链接,即使是动态链接也会被替换成静态。此时的可执行程序可以不依赖任何库,但是由于连系统库都要被替换,相当浪费磁盘和内存空间。不过兼容性好,也不用担心各个库的版本兼容问题

-shared

生成动态链接库

-l <库名>

链接指定的库。如,-lm 链接数学库 libm.so

-L <路径>

指定库文件的搜索路径

# 使用测试
make CFLAGS="-O2 -march=native" LDFLAGS="-Wl,-rpath,/usr/local/lib"
#-march=native 自动检测当前 CPU 架构以针对性优化。
#-Wl 告诉编译器将参数传输给链接器 ld ,-rpath 表示运行时到后面的路径找链接库,这样就无需手动设置环境变量 LD_LIBRARY_PATH

# 其他

可能有用的小东西:

记一次简单的挖矿病毒清除 --- 实战_chattr -ia-CSDN 博客

日志分析 入侵检测 -- 实战_atop 日志分析 - CSDN 博客

1759585543182