1 bio
1.1 bio
00.localhost和127.0.0.1区别
a.总结
localhost 是本机域名,localhost 通过系统的 host 文件会自动解析到 127.0.0.1。
127.0.0.1 是本机 IP 地址
-----------------------------------------------------------------------------------------------------
相同点:两者都指向本地主机,通常用来进行本地测试和开发工作。通信不会离开主机本身,不会经过外部网络。
不同点:解析过程:localhost 需要通过主机文件解析,而 127.0.0.1 是直接使用的IP 地址。
配置依赖:localhost 的解析依赖于系统配置(如 /etc/hosts),如果该配置被修改或破坏,localhost 可能无法正常解析为 127.0.0.1,但 127.0.0.1 则不受影响。
b.localhost
localhost 是一个域名,它在大多数操作系统中被配置为指向本地计算机,我们在浏览器中输入 localhost 时,浏览器会将其解析为本地计算机的地址。
通常情况下,在操作系统的主机文件(如 /etc/hosts 或 C:\Windows\System32\drivers\etc\hosts)中,localhost 被定义为指向 127.0.0.1。
使用 localhost 进行网络通信时,操作系统会将其解析为 127.0.0.1。
其实 localhost 就相当于一个域名,我们可以使用 ping 来查看域名对应的 IP 地址
c.127.0.0.1
127.0.0.1 是一个特殊的 IP 地址,称为回环地址(loopback address),它用于标识本地计算机,并且是网络协议中保留的地址之一,用于测试和本地通信。
127.0.0.1 是一个特殊的 IPv4 地址,保留用于主机自身的通信,不会经过任何物理网络接口。
d.IPv6 中的 localhost
在 IPv6 中,localhost 对应的地址是 ::1,这个地址是 IPv6 的回环地址,用于本地设备自我通信,就像 IPv4 中的 127.0.0.1 一样。
IPv6 中的 localhost 可以像 IPv4 一样在网络通信和开发中使用。
当你需要在 IPv6 环境中进行本地测试和开发时,可以使用 ::1 来指代本地主机。
如果你在本地机器上运行一个支持 IPv6 的 Web 服务器,可以通过在浏览器中输入 http://[::1]:port 来访问,其中 “port” 是你的Web服务器运行的特定端口。
-----------------------------------------------------------------------------------------------------
表示形式:
IPv4: localhost 是一个主机名,通常解析为 127.0.0.1。
IPv6: localhost 同样是一个主机名,通常解析为 ::1。
使用方式:
IPv4: localhost 通常用于软件配置和开发环境,而 127.0.0.1 用于需要 IP地址的网络配置和系统文件中。
IPv6: localhost 和 ::1 的使用方式与 IPv4 类似,具体取决于系统和应用程序的需求。
访问方法:
IPv4: 通过 localhost 或 127.0.0.1 访问服务,本质上达到相同的结果。
IPv6: 通过 localhost 或 ::1 访问服务,同样达到相同的结果,主要区别在于使用的协议版本
01.常见信息
a.命令行
ctrl + a --光标移至当前行的最前面
ctrl + e --光标移至当前行的最前面
ctrl + c --放弃当前行,直接开始下一行
b.系统资源
top --进程
free --内存使用情况
uname -a --内核版本
ifconfig -a --查看IPV4
netstat -nap --查看正常使用的端口以及关联的进程
------------------------------------------------------------------------
lsblk --查看全部磁盘
df -T -h --查看全部磁盘
fdisk -l --查看分区表状态
c.系统开关
history --历史
crontab -l --查看crontab任务
logout / exit --注销用户
reboot / shutdown -r now --重启
halt -p / shutdown -h now --关闭系统并断电
d.别名
alias mountsdb1 ='mount -t ext3 /dev/sdb1 /mnt/sdb1' --别名
unalias mountsdb1 --取消别名
e.其他
echo 'world' > hello.txt --覆盖文件内容
rm -rf /root/.local/share/Trash/files --删除回收站内容
02.screen
a.安装
yum install screen -y --安装screen
screen -ls --列出全部会话
screen -S demo01 --创建demo01
screen -r demo01 --返回demo01
screen -d demo01 --远程中断demo01
screen -d -r demo01 --结束当前会话并返回demo01
b.快捷键
Ctrl + A + ? --显示所有键绑定信息
Ctrl + A + C --Create,创建新窗口并切换到该窗口
Ctrl + A + N --Next,切换到下一个窗口
Ctrl + A + P --Previous,切换到前一个窗口
Ctrl + A + 0 --切换到第0-9个窗口
Ctrl + A + SPACE --由视窗0循序切换到视窗9
Ctrl + A + Ctrl + A --在两个最近使用的窗口间切换
Ctrl + A + X --锁住当前的创建,用户密码解锁
Ctrl + A + D --Detach,暂时离开当前窗口
Ctrl + A + Z --当前窗口后台执行
Ctrl + A + W --显示所有窗口列表
Ctrl + A + T --Time,显示当前时间
Ctrl + A + K --Kill,强行关闭当前窗口
Ctrl + A + ] --将剪切板的内容进行粘贴
03.Centos7与Centos6配置的三点不同
a.hostname
Centos6:配置文件
Centos7:命令行,hostnamectl set-hostname bigdata01
b.网卡
Centos6:vi /etc/sysconfig/network-scripts/ifcfg-eth0
rm -r /etc/udev/rules.d/70-persistent-net.rules
Centos7:vi /etc/sysconfig/network-scripts/ifcfg-ens33
c.服务
Centos6:service iptables stop
Centos7:systemctl stop firewalld
04.ibus拼音版
a.安装
yum install ibus-libpinyin
b.添加
Region&Language -> input Source
c.切换
win + 空格
05.自动同步时间
a.安装
yum -y install ntp ntpdate --终端安装时间同步插件
ntpdate cn.pool.ntp.org --设置时间同步
b.将系统时间写入硬盘时间
hwclock --systohc
1.2 dir
00.汇总
a.查看文件
a.模糊查询
find /root/upFiles/temp -name "*钢材装车时间*"
b.使用 ls 和 grep
ls /root/upFiles/temp | grep "钢材装车时间"
c.直接查看文件
ls /root/upFiles/temp/3月钢材装车时间_1743554832180.xlsx
b.查看格式
a.以.xlsx结尾的文件
find /root/upFiles/temp -name "*.xlsx"
b.以_开头并且以.xlsx结尾的文件
find /root/upFiles/temp -name "_*.xlsx"
01.常用命令1
a.根目录
/bin linux常用的命令,如cp,ls,ping,mount,i,tar,kil,grep,rpm,dd,ps,ln,gzip,cat等
/boot 启动文件,如vmlinuz
/dev 设备文件,如fdo(软盘),hda(第一硬盘),hdal,hdb,sda,sdal,cdrom(hdc),mouse(psaux)
/etc 配置文件,如hosts,lilo.conf,inittab,rc,d(dir,samba/smd.conf等
-----------------------------------------------------------------------------------------------------
/home,/root 每个用户在home下有一个自己的目录。-root的在/root权限和保护
/lost+found -Lost?found一些丢失的文件可能可以在这里找到
/lib 共享库相关文件
/mnt -mount文件系统到这个目录如cdrom,floppy
/var 执行中记录数据
/proc 内存文件,报告程序执行的在线动态信息
/sbin 启动时需要,系统管理员程序工具、配置等
/tmp 临时文件夹
/usr 用户应用程序和文件
-----------------------------------------------------------------------------------------------------
/usr 系统级的目录,理解为C:/Windows/
/usr/lib 理解为C:/Windows/System32
/usr/local 用户级的程序目录,可以理解为C:/Progrem Files/,用户自己编译的软件默认会安装到这个目录下
-----------------------------------------------------------------------------------------------------
/opt 用户级的程序目录,可以理解为D:/Software
/opt opt有可选的意思,这里可以用于放置第三方大型软件(或游戏),当你不需要时,直接rm -rf掉即可
/opt 在硬盘容量不够时,也可将/opt单独挂载到其他磁盘上使用
b.切换目录
pwd 显示当前所在目录
cd 切换目录
cd . 上级目录
cd ./modules/ 当前目录
cd ~ 表示用户主目录,即HOME变量指定的目录,如root用户的主目录为/root
cd - 前一个工作目录
cd../../ 连退两级目录
c.创建目录
mkdir [选项] 目录名称
-m 在创建目录时设定权限模式
-p 创建目录结构中指定的每一个目录,如果目录不存在则创建目录,如果目录已存在不会被覆盖
-v 或-verbose:每次创建新目承都显示信息
--help 显示帮助信息
d.删除,文件及目录
a.参数
rm [选项] 目标文件 用来删除文件,也可删除多个文件或目录,以及将某个目录及其下的所有文件及子目录均删除
对于链接文件,只是断开了链接,原文件保持不变
-f 在没有确认删除提示的下删除文件并忽略不存在的文件和参数
-i 删除文件前提示确认
-I 在删除三个以上的文件或递归删除文件之前提示确认
-r, -recursive 以递归方式删除目录及其内容
-d, --dir 不使用 -r/-R/-recursive 删除空目录,rm -dir 等同于 rmdir
-v, --verbose 显示正在进行的步骤
b.示例1
rm atp --删除:单个文件
rm atp1 atp2 atp3 --删除:多个文件
-------------------------------------------------------
rm *.txt --删除:该目录下所有.txt文件
rm atp*.txt --删除:使用'*'任意匹配
c.示例2
rm -f atp --强制删除
-------------------------------------------------------
rm -i atp --询问删除:单个文件
rm -i atp1 atp2 atp3 --询问删除:多个文件
rm -i atp*.txt --询问删除:使用'*'任意匹配,输入y/n提示多次
rm -I atp*.txt --询问删除:使用'*'任意匹配,输入y/n提示一次
-------------------------------------------------------
rm -v atp --输出过程:单个文件
rm -v atp1 atp2 atp3 --输出过程:多个文件
rm -v -i atp*.txt --输出过程+询问删除:使用'*'任意匹配
rm -v -i atp*.txt --输出过程+询问删除:使用'*'任意匹配
d.示例3
rm -i 'filename with spaces' --删除:文件名包含空格(将文件名用引号括起)
rm -i filename\ with\ spaces --删除:文件名包含空格(反斜杠转义每个空格)
-------------------------------------------------------
rm -- -filename --删除:文件名破折开头(前面加上双破折号)
rm /home/-filename --删除:文件名破折开头(加上文件的路径)
e.示例4
rm -d dirname --删除:删除空目录(-d参数,等同于rmdir命令)
rm -r dirname --删除:删除非空目录(-r参数)
rm -i dirname --删除:删除确认提示(y确认或n取消)
f.删除文件
rm -rf /usr/local/hue/atp.txt
g.删除目录
rm -rf dist/*
rm -rf node_modules
-------------------------------------------------------------------------------------------------
rm -rf /usr/local/hue
e.复制,文件及目录(经测试,linux操作cp命令速度,比拖出win10操作要快)
cp [选项] 源文件 目标文件
-a 保留链接、文件属性,复制目录时可递归的复制目录
-i 如果目标文件或目录已经存在,则对用户进行提示,可以用字母y确认,其他字母都是否认
-r 复制目承,实现将源目承下的文件和子目录一起复制到目标目录中
f.移动/重命名,文件及目录
mv [选项] 源文件 目标文件
02.常见命令2
a.创建/更新,文件
a.参数
touch 文件名 用于修改文件或者目录的时间属性,包括存取时间和更改时间
若文件不存在,系统会建立一个新的文件
-------------------------------------------------------------------------------------------------
-a 改变档案的读取时间记录
-m 改变档案的修改时间记录
b.示例
touch newfile --若文件不存在,系统会建立一个新的文件
touch newfile1 newfile2 newfile3 --若文件不存在,系统会建立一个新的文件
-------------------------------------------------------------------------------------------------
touch testfile --将testfile时间修改为【当前系统时间】
ls -l testfile --查看文件的时间属性
-------------------------------------------------------------------------------------------------
echo "write" > job1.md --创建job1.md文件,并将write写入job1.md
b.删除,文件/目录
a.参数
rm [选项] 目标文件 用来删除文件,也可删除多个文件或目录,以及将某个目录及其下的所有文件及子目录均删除
对于链接文件,只是断开了链接,原文件保持不变
-------------------------------------------------------------------------------------------------
-f 在没有确认删除提示的下删除文件并忽略不存在的文件和参数
-i 删除文件前提示确认
-I 在删除三个以上的文件或递归删除文件之前提示确认
-r, -recursive 以递归方式删除目录及其内容
-d, --dir 不使用 -r/-R/-recursive 删除空目录,rm -dir 等同于 rmdir
-v, --verbose 显示正在进行的步骤
b.示例1
rm atp --删除:单个文件
rm atp1 atp2 atp3 --删除:多个文件
-------------------------------------------------------
rm *.txt --删除:该目录下所有.txt文件
rm atp*.txt --删除:使用'*'任意匹配
c.示例2
rm -f atp --强制删除
-------------------------------------------------------
rm -i atp --询问删除:单个文件
rm -i atp1 atp2 atp3 --询问删除:多个文件
rm -i atp*.txt --询问删除:使用'*'任意匹配,输入y/n提示多次
rm -I atp*.txt --询问删除:使用'*'任意匹配,输入y/n提示一次
-------------------------------------------------------
rm -v atp --输出过程:单个文件
rm -v atp1 atp2 atp3 --输出过程:多个文件
rm -v -i atp*.txt --输出过程+询问删除:使用'*'任意匹配
rm -v -i atp*.txt --输出过程+询问删除:使用'*'任意匹配
d.示例3
rm -i 'filename with spaces' --删除:文件名包含空格(将文件名用引号括起)
rm -i filename\ with\ spaces --删除:文件名包含空格(反斜杠转义每个空格)
-------------------------------------------------------
rm -- -filename --删除:文件名破折开头(前面加上双破折号)
rm /home/-filename --删除:文件名破折开头(加上文件的路径)
e.示例4
rm -d dirname --删除:删除空目录(-d参数,等同于rmdir命令)
rm -r dirname --删除:删除非空目录(-r参数)
rm -i dirname --删除:删除确认提示(y确认或n取消)
f.删除目录
rm -rf dist/*
rm -rf node_modules
-------------------------------------------------------------------------------------------------
rm -rf /usr/local/hue
c.复制,文件及目录(经测试,linux操作cp命令速度,比拖出win10操作要快)
cp [选项] 源文件 目标文件
-a 保留链接、文件属性,复制目录时可递归的复制目录
-i 如果目标文件或目录已经存在,则对用户进行提示,可以用字母y确认,其他字母都是否认
-r 复制目承,实现将源目承下的文件和子目录一起复制到目标目录中
d.移动/重命名,文件及目录
mv [选项] 源文件 目标文件
03.常用命令3
a.查看目录
drwxr-xr-x 目录(蓝)
-rw-r--r-- 文件(白)
-----------------------------------------------------------------------------------------------------
ls -a 列出目录下的所有文件,包括以。开头的隐含文件(a11)
ls -l 列出文件的详细信息(1ong)
ls -al
-----------------------------------------------------------------------------------------------------
ls -h
ls -hl 与-l一起,以易于阅读的格式输出文作大小
-----------------------------------------------------------------------------------------------------
ls -ltr --等同与ll
ls -ltr XHTODKY* --等同与ll,查询*gz
ls -ltr | grep XHTODKY --等同与ll,查询*gz
find . -type f -name 'XHTODKY*' --查看以XHTODKY开头的文件
-----------------------------------------------------------------------------------------------------
ls | grep install 管道符
b.查看文件
more 文件名 --浏览过多文件
less 文件名 --浏览过多文件
-----------------------------------------------------------------------------------------------------
cat [选项] 文件名 --将文件内容打印到终端
-----------------------------------------------------------------------------------------------------
head [选项] 文件名 --显示文件头部
head -n 30 ka* --显示文件头部:前30行,默认10行
tail [选项] 文件名 --显示文件尾部
tail -n 30 ka* --显示文件尾部:前30行,默认10行
-----------------------------------------------------------------------------------------------------
grep 关键字 查找范围 --查询字符串
grep oracle /ect/passwd
04.常见命令4
b.grep查找
a.查找文件
ls | grep install --查找文件:文件名
ls | grep install.sh --查找文件:文件名
-------------------------------------------------------
ls | grep 'install.sh' --查找文件:字符串
ls | grep 'stall.sh' --查找文件:字符串
-------------------------------------------------------
grep 关键字 查找范围 --查询字符串
grep oracle /ect/passwd
b.查找文件内容
demo.txt有如下内容:
name
passwd
pick
-------------------------------------------------------
grep 'a' demo.txt --查找单字符串:demo.txt中【'a'单个字符串】
grep 'a' demo* --查找单字符串:前缀为demo中【'a'单个字符串】
grep 'a' *txt --查找单字符串:后缀为txt中【'a'单个字符串】
-------------------------------------------------------
grep -e 'name' -e passwd demo.txt --查找多字符串:demo.txt中【'name' 'passwd'】
c.其他
grep -i 'name' demo.txt --默认grep区分大小写,通过-i开启忽略大小写
grep -i "\<name\>" demo.txt --精确匹配,默认会返回nickname,严格搜索name
grep -n 'name' demo.txt --开启行号
grep -n 'name' demo.txt | sort --开启行号+对结果排序
c.sed命令
sed -i 's/KA1/KA2/' ka14.txt --默认,匹配第一个
sed -i '22,$s/$/|+|/' ka14.txt --
05.常见命令5
a.管道符
命令格式:cmd1 | cmd2 | cmd3 | ... | cmd(n)
作用:将一个命令的执行结果作为另一个命令输入来执行
-----------------------------------------------------------------------------------------------------
ls /etc less --查看/etc目录下的内容
ls /etc grep pass* --显示/ctc目录中文件名以pass开头的文件
b.重定向
所谓重定向,指不使用系统的标准输入、输出、错误端口进行信息的获取或输出,而是通过重新的指定,
让命令从非默认的输入输出设备获取或输出信息。所以重定向分为:输入重定向、输出重定向和错误重定向。
-----------------------------------------------------------------------------------------------------
> 输出重定向。如果原来目标文件存在,则新的内容会覆盖文件中原有的内容
>> 输出重定向。如果原来目标文件存在,则新的内容会追加在原来内容的后面,不覆盖文件中的原有内容
< 输入重定向。即命令的输入不通过键盘来完成,而通过其他的方式
2> 错误重定向
&) 输出重定向和错误重定向同时实现
-----------------------------------------------------------------------------------------------------
ls /list --将ls /命令的执行结果记录到1ist的文件中
useradd lolo 2>errlog --将错误信息保存到当前目录下的errlog文件中
c.Shell
每个命令之间用;隔开
各命令的执行结果,不会影响其它命令的执行。换句话说,各个命令都会执行,但不保证每个命令都执行成功
-----------------------------------------------------------------------------------------------------
每个命令之间用&&隔开
若前面的命令执行成功,才会去执行后面的命令。这样可以保证所有的命令执行完毕后,执行过程都是成功的
-----------------------------------------------------------------------------------------------------
每个命令之间用||或者|隔开
||是或的意思,只有前面的命令执行失败后才去执行下一条命令,直到执行成功一条命令为止

1.3 net
00.压缩
a.如果系统没有安装 zip,需要先安装
# CentOS/RHEL
yum install zip unzip
# Ubuntu/Debian
apt-get install zip unzip
b.使用 zip 命令
# 基本用法
zip -r dist.zip dist/
# 如果要显示打包进度
zip -r -v dist.zip dist/
# 如果要指定压缩级别(0-9,9为最大压缩)
zip -r -9 dist.zip dist/
# 如果要排除某些文件(例如 .DS_Store)
zip -r dist.zip dist/ -x "*.DS_Store"
c.使用 tar 命令(先打包后压缩)
# 创建 tar.gz 格式
tar -czf dist.tar.gz dist/
# 或创建 tar.bz2 格式(更好的压缩比)
tar -cjf dist.tar.bz2 dist/
d.打包时包含时间戳
# 使用当前日期作为文件名
zip -r dist_$(date +%Y%m%d).zip dist/
# 使用日期和时间
zip -r dist_$(date +%Y%m%d_%H%M%S).zip dist/
e.检查打包结果
# 查看 zip 文件内容
unzip -l dist.zip
# 查看文件大小
ls -lh dist.zip
01.解压
a.安装
chmod -R 777 /root/.acme.sh/ --文件夹
tar -zxvf VMwareTools-10.0.0-2977863.tar.gz && sudo ./vmware-install.pl --全屏模式
b.压缩/解压
yum install -y unzip zip --安装zip
unzip xxx.zip --zip
tar -xvf xxx.tar.gz --tar.gz
tar -zxvf xxx.tar.gz --tar.gz
tar -xvJf xxx.tar.xz --tar.gz
rpm -ivh Xxx.rpm --rpm
02.防火墙
a.systemctl
systemctl stop firewalld --关闭防火墙
systemctl disable firewalld --禁止开机自启
systemctl status firewalld --防火墙状态
systemctl start firewalld --开启防火墙
systemctl enable firewalld --开启开机自启
b.firewall-cmd
firewall-cmd --reload --重启防火墙
firewall-cmd --zone=public --add-port=3306/tcp --permanent --开放3306端口
firewall-cmd --zone=public --remove-port=3306/tcp --permanent --关闭3306端口
firewall-cmd --zone=public --list-ports --查看开放端口
firewall-cmd --zone=public --query-port=3306/tcp --查看具体端口
firewall-cmd --state --查看防火墙状态
c.ubuntu-UFW
sudo ufw enable --启用防火墙
sudo ufw disable --禁用防火墙
sudo ufw reload --重载防火墙
sudo ufw status --防火墙状态
sudo ufw reset --重置防火墙(禁用防火墙并删除所有已配置的规则)
------------------------------------------------------------------------
sudo ufw allow 882 --允许某个端口
sudo ufw allow 882/tcp --允许指定端口和协议
sudo ufw allow 882/udp --允许指定端口和协议
sudo ufw allow 8000:8100/tcp --允许端口范围
sudo ufw allow from 192.168.1.100 to any port 882 --允许从特定 IP 地址访问某个端口
sudo ufw allow from 192.168.1.0/24 to any port 882 --允许从特定子网访问某个端口
------------------------------------------------------------------------
sudo ufw deny 882 --拒绝某个端口
sudo ufw deny 882/tcp --拒绝指定端口和协议
sudo ufw deny 882/udp --拒绝指定端口和协议
sudo ufw deny from 192.168.1.100 to any port 882 --拒绝从特定 IP 地址访问某个端口
------------------------------------------------------------------------
sudo ufw default allow incoming --允许所有流量(禁用默认规则)
sudo ufw default allow outgoing --拒绝所有流量(严格模式)
sudo ufw default deny outgoing --拒绝所有流量(严格模式)
sudo ufw default deny outgoing --拒绝所有流量(严格模式)
sudo ufw allow in on eth0 --允许特定方向的流量(入站流量)
sudo ufw allow out on eth0 --允许特定方向的流量(出站流量)
sudo ufw allow in on eth0 to any port 882 --允许特定网络接口的流量
sudo ufw delete allow 882 --删除规则(删除特定规则)
sudo ufw delete allow from 192.168.1.100 to any port 882 --删除规则(删除特定 IP 的规则)
------------------------------------------------------------------------
sudo ufw logging on --启用防火墙日志
sudo ufw logging off --禁用防火墙日志
sudo ufw logging low # 可选:off, low, medium, high, full --设置日志级别
03.查看ip
a.Windows
ipconfig --查看IPV4
----------------------------------------------------------------
netstat -ano --查看全部端口
netstat -aon|findstr 135 --查看某个端口
taskkill -f -pid 135 --删除某个端口
----------------------------------------------------------------
tasklist|findstr 12088 --根据pid查看应用程序
b.Centos7
yum install net-tools -y --安装net-tools
----------------------------------------------------------------
ip a / ip addr / ip address --查看IPV4
ifconfig -a --查看IPV4
hostname -I --查看IPV4
----------------------------------------------------------------
netstat -nap --查看正常使用的端口以及关联的进程
netstat -lnpt | grep 8080 --查看8080端口
netstat -ntulp | grep 8080 --查看8080端口
----------------------------------------------------------------
lsof -i 8080 --查看8080端口
lsof -i :8080 --查看8080端口
ps [pid] --查看8080端口对应的pid进程
kill -9 [pid] --关闭8080端口对应的pid进程
c.mac
ifconfig --查看IPV4
----------------------------------------------------------------
ifconfig | grep "inet " | grep -v 127.0.0.1 --查看内网IP
d.ps进程
ps aux | grep java --查看java程序
ps aux | grep nginx --查看nginx程序
ps aux | grep redis --查看redis程序
kill -9 [进程id]
----------------------------------------------------------------
kill -s 9 pid --常用1:停止【进程pid】,-s 9 强制终止
kill -s 9 `pgrep firefox` --常用2:停止【进程名】
e.优雅关闭端口
(for /f "tokens=5" %a in ('netstat -ano ^| findstr "LISTENING" ^| findstr ":5174"') do taskkill /PID %a /F) & npx http-server . -p 5174
$process = Get-NetTCPConnection -LocalPort 5174 -State Listen | Select-Object -First 1; if ($process) { Stop-Process -Id $process.OwningProcess -Force -ErrorAction SilentlyContinue }; npx http-server . -p 5174
04.查看ip端口
a.netstat命令
yum install net-tools --安装 net-tools
netstat -tunlp | grep 9981 --查看具体某个端
b.ss命令
ss -tunlp | grep 9981 --查看具体某个端
c.lsof命令
yum install lsof --安装 lsof
lsof -i --查看所有网络连接
lsof -i:9981
d.firewall-cmd命令
firewall-cmd --list-ports --查看所有开放的端口
firewall-cmd --query-port=9981/tcp --查询某个端口是否开放
e.ping命令
scutil --dns
ping www.baidu.com
dig openai.newbotai.cn
traceroute www.baidu.com
nslookup openai.newbotai.cn
curl -I https://openai.newbotai.cn
-----------------------------------------------------------------------------------------------------
ping icscrepo1.icsc.com.tw --64 bytes from 198.18.3.169
nslookup icscrepo1.icsc.com.tw --Address: 198.18.3.169
nslookup icscrepo1.icsc.com.tw 8.8.8.8 --谷歌,正确
nslookup icscrepo1.icsc.com.tw 223.5.5.5 --阿里云,错误
-----------------------------------------------------------------------------------------------------
ipconfig /flushdns --刷新DNS:win
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder --刷新DNS:mac
sudo systemctl restart NetworkManager --刷新DNS:linux
05.ps进程
a.参数
-e 显示所有进程
-f 全部列出,通常和其他选项联用
-----------------------------------------------------------------------------------------------------
-a 显示一个终端的所有进程,除了会话引线
-u username显示该用户下的所有进程,且显示各个命令的详细路径
-x 显示没有控制终端的进程,同时显示各个命令的具体路径
-aux 显示所有包含其他使用者的进程
b.查看、杀死
$ top --说明:动态实时视图
$ pstree -aup --说明:以树状图展现
$ ps aux | less --说明:ps查看进程信息,并通过less分页显示
-----------------------------------------------------------------------------------------------------
$ ps -ef
UID PID PPID C STIME TTY TIME CMD
smx 1822 1 0 11:38 ? 00:00:49 gnome-terminal
smx 1823 1822 0 11:38 ? 00:00:00 gnome-pty-helper
-----------------------------------------------------------------------------------------------------
$ ps -aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
smx 1822 0.1 0.8 58484 18152 ? Sl 11:38 0:49 gnome-terminal
smx 1823 0.0 0.0 1988 712 ? S 11:38 0:00 gnome-pty-helper
-----------------------------------------------------------------------------------------------------
$ ps -aux | grep firefox
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
smx 1822 0.1 0.8 58484 18152 ? Sl 11:38 0:49 firefox-3.6.18/firefox-bin
smx 1823 0.0 0.0 1988 712 ? S 11:38 0:00 firefox
-----------------------------------------------------------------------------------------------------
$ kill -s 9 pid --常用1:停止【进程pid】,-s 9 强制终止
$ kill -s 9 `pgrep firefox` --常用2:停止【进程名】
c.杀死-改进1
pgrep firefox --说明:等同【ps -aux | grep firefox】
pidof firefox-bin --说明:xx的PID,【必须给出进程的全名】
d.杀死-改进2
ps -ef | grep firefox | grep -v grep | cut -c 9-15 | xargs kill -s 9
--【“grep firefox”的输出结果是,所有含有关键字“firefox”的进程】
--【“grep -v grep”是在列出的进程中去除含有关键字“grep”的进程】
--【“cut -c 9-15”是截取输入行的第9个字符到第15个字符,而这正好是进程号PID】
--【“xargs kill -s 9”中的xargs命令是用来把前面命令的输出结果(PID)作为“kill -s 9”命令的参数】
e.杀死-改进3
pgrep firefox | xargs kill -s 9
--【“pgrep firefox”】替代【ps -ef | grep firefox | grep -v grep | cut -c 9-15】
--【“xargs kill -s 9”】
f.杀死-改进4
kill -s 9 `ps -aux | grep firefox | awk '{print $2}'` --第一步
kill -s 9 `pgrep firefox` --第二步:pkill=pgrep+kill
pkill -9 firefox --第三步:pkill无须s,终止信号跟在-后
killall -9 firefox --第三步:【必须给出进程的全名】
06.nohup后台运行
a.后台运行
nohup --加在一个命令的最前面,表示不挂断的运行命令
& --加载一个命令的最后面,表示这个命令放在后台执行
-----------------------------------------------------------------------------------------------------
nohup /root/runoob.sh & --示例
b.查看后台运行
a.区别
ps:适用于查看瞬时进程的动态,可以查看其他终端的进程
jobs:只能查看当前终端后台执行的任务,无法查看其他终端的进程
b.jobs
只有在当前命令行中使用nohup和&时,job可以显示进程
如果将【写到命令行内容,写道.sh脚本】中,执行脚本,jobs无法显示进程
停止jobs
c.ps
ps -ef
ps -ef | less
ps -ef | grep java
-------------------------------------------------------------------------------------------------
ps -aux
ps -aux | less
ps -aux | grep java
-------------------------------------------------------------------------------------------------
pstree -aup
c.关闭后台运行
a.前台进程
Ctrl + Z --终止
b.后台进程
kill -s 9 pid --常用1:停止【进程pid】,-s 9 强制终止
kill -s 9 `pgrep firefox` --常用2:停止【进程名】
d.前后台进程的切换与控制
a.fg命令
将后台中的命令调至前台继续运行
如果后台中有多个命令,可以先用jobs查看jobnun,然后用 fg %jobnum 将选中的命令调出
b.bg命令
将一个在后台暂停的命令,变成在后台继续执行
如果后台中有多个命令,可以先用jobs查看jobnum,然后用 bg %jobnum 将选中的命令调出继续执行
c.Ctrl+Z
将一个正在前台执行的命令放到后台,并且处于暂停状态
b.情况判断
nohup sed -i '22,$s/$/|+|/' ka14.txt &
情况1:SQL截断数据假死,开5个窗口同时运行
情况2:若为nohup,则一个窗口由系统自动分配运行
1.4 shell
01.常见信息1
a.服务器健康检查脚本
#!/bin/bash
# 获取CPU使用率
cpu_usage=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}')
# 获取内存使用率
mem_usage=$(free -m | awk 'NR==2{printf "%.2f", $3*100/$2 }')
disk_usage=$(df -h | awk '$NF=="/"{printf "%s", $5}' | sed 's/%//g')
# 判断是否超过阈值并发送告警
if [ $cpu_usage -gt $cpu_threshold ]; then
echo "CPU使用率超过阈值!" | mail -s "CPU告警" [email protected]
fi
if [ $mem_usage -gt $mem_threshold ]; then
echo "内存使用率超过阈值!" | mail -s "内存告警" [email protected]
fi
if [ $disk_usage -gt $disk_threshold ]; then
echo "磁盘使用率超过阈值!" | mail -s "磁盘告警" [email protected]
fi
02.常见信息2
a.自动化部署脚本
#!/bin/bash
# 定义项目目录和代码仓库地址
project_dir="/var/www/myapp"
repo_url="[email protected]:user/myapp.git"
# 拉取最新代码
cd $project_dir
git pull $repo_url
# 安装依赖
npm install
# 修改配置文件
sed -i 's/DATABASE_HOST=localhost/DATABASE_HOST=db.example.com/' .env
# 重启服务
systemctl restart myapp
echo "部署完成!"
b.用户管理脚本
#!/bin/bash
# 定义用户列表文件
user_list="user_list.txt"
# 遍历用户列表文件
while read -r username password; do
# 创建用户
useradd -m -s /bin/bash $username
# 设置用户密码
echo "$username:$password" | chpasswd
# 添加用户到sudo组
usermod -aG sudo $username
done < $user_list
echo "用户创建完成!"
c.软件安装脚本
#!/bin/bash
# 更新软件包列表
apt-get update
# 安装软件包
apt-get install -y nginx mysql-server php-fpm
# 配置软件包
sed -i 's/listen = 127.0.0.1:9000/listen = /var/run/php/php7.4-fpm.sock/' /etc/php/7.4/fpm/pool.d/www.conf
# 启动服务
systemctl start nginx mysql php7.4-fpm
echo "软件安装完成!"
d.网络配置脚本
#!/bin/bash
# 配置网络接口
cat <<EOF > /etc/network/interfaces
auto eth0
iface eth0 inet static
address 192.168.1.100
netmask 255.255.255.0
gateway 192.168.1.1
EOF
# 重启网络服务
systemctl restart networking
# 配置防火墙
ufw allow 22/tcp
ufw allow 80/tcp
ufw enable
echo "网络配置完成!"
03.常用信息3
a.安全加固脚本
#!/bin/bash
# 禁用root登录
sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
# 修改SSH端口
sed -i 's/#Port 22/Port 2222/' /etc/ssh/sshd_config
# 配置防火墙
ufw allow 2222/tcp
ufw deny 22/tcp
ufw enable
# 重启SSH服务
systemctl restart sshd
echo "安全加固完成!"
b.数据同步脚本
#!/bin/bash
# 定义源目录和目标目录
src_dir="/data"
dst_dir="[email protected]:/backup"
# 使用rsync同步数据
rsync -avz --delete $src_dir $dst_dir
echo "数据同步完成!"
c.数据库备份脚本
#!/bin/bash
# 定义数据库信息和备份目录
db_user="root"
db_password="password"
db_name="mydatabase"
backup_dir="/backup"
# 创建备份目录
mkdir -p $backup_dir
# 备份数据库
mysqldump -u$db_user -p$db_password $db_name | gzip > $backup_dir/$db_name_$(date +%Y%m%d).sql.gz
echo "数据库备份完成!"
d.网站监控脚本
#!/bin/bash
# 定义网站URL和监控频率
website="https://www.example.com"
interval=60
# 循环监控网站
while true; do
# 获取网站状态码和响应时间
response=$(curl -o /dev/null -s -w "%{http_code}\n%{time_total}\n" $website)
status_code=$(echo "$response" | head -n 1)
response_time=$(echo "$response" | tail -n 1)
# 判断状态码是否正常
if [ $status_code -ne 200 ]; then
echo "网站不可用!状态码: $status_code" | mail -s "网站监控告警" [email protected]
fi
# 判断响应时间是否超时
if [ $(echo "$response_time > 2" | bc) -eq 1 ]; then
echo "网站响应时间过长!响应时间: $response_time 秒" | mail -s "网站监控告警" [email protected]
fi
# 等待指定时间后继续监控
sleep $interval
done
e.日志分析脚本
#!/bin/bash
# 定义日志文件和分析结果输出文件
log_file="/var/log/nginx/access.log"
output_file="log_analysis.txt"
# 统计访问量最多的IP地址
awk '{print $1}' $log_file | sort | uniq -c | sort -nr | head -n 10 > $output_file
# 统计访问量最多的URL
awk '{print $7}' $log_file | sort | uniq -c | sort -nr | head -n 10 >> $output_file
# 统计HTTP状态码分布
awk '{print $9}' $log_file | sort | uniq -c | sort -nr >> $output_file
echo "日志分析完成!"
04.常用信息4
a.自动化测试脚本
#!/bin/bash
# 定义测试用例目录和测试报告输出文件
test_case_dir="/tests"
report_file="test_report.txt"
# 遍历测试用例目录
for test_case in $test_case_dir/*; do
# 执行测试用例
result=$(bash $test_case)
# 记录测试结果
echo "$test_case: $result" >> $report_file
done
echo "自动化测试完成!"
b.性能测试脚本
#!/bin/bash
# 定义测试URL和并发数
website="https://www.example.com"
concurrency=100
# 使用ab命令进行性能测试
ab -n 1000 -c $concurrency $website > performance_test.txt
echo "性能测试完成!"
c.代码格式化脚本
#!/bin/bash
# 定义代码目录和格式化工具
code_dir="/code"
formatter="black"
# 遍历代码目录
find $code_dir -name "*.py" -exec $formatter {} \;
echo "代码格式化完成!"
d.依赖管理脚本
#!/bin/bash
# 定义项目目录和依赖管理工具
project_dir="/project"
package_manager="pip"
# 安装依赖
cd $project_dir
$package_manager install -r requirements.txt
echo "依赖安装完成!"
e.版本控制脚本
#!/bin/bash
# 定义代码目录和版本控制工具
code_dir="/code"
vcs="git"
# 提交代码
cd $code_dir
$vcs add .
$vcs commit -m "提交代码"
$vcs push
echo "代码提交完成!"
f.文档生成脚本
#!/bin/bash
# 定义项目目录和文档生成工具
project_dir="/project"
doc_generator="sphinx"
# 生成文档
cd $project_dir/docs
$doc_generator-build . ../docs
echo "文档生成完成!"
g.邮件发送脚本
#!/bin/bash
# 定义邮件内容
subject="测试邮件"
body="这是一封测试邮件。"
# 发送邮件
echo "$body" | mail -s "$subject" [email protected]
echo "邮件发送完成!"
2 basic
2.1 apt
01.常用信息1
a.区别
apt(进度条,最常用命令选项的集合) = apt-get + apt-cache + apt-config
apt install apt-get install --安装软件包
apt remove apt-get remove --移除软件包
apt purge apt-get purge --移除软件包及配置文件
apt update apt-get update --刷新存储库索引
apt upgrade apt-get upgrade --升级所有可升级的软件包
apt autoremove apt-get autoremove --自动删除不需要的包
apt full-upgrade apt-get dist-upgrade --在升级软件包时自动处理依赖关系
apt search apt-cache search --搜索应用程序
apt show apt-cache show --显示装细节
b.默认位置
/var/cache/apt/archives --下载的软件存放位置
/usr/share --安装后软件默认位置
/usr/bin --可执行文件位置
/etc --配置文件位置
/usr/lib --lib文件位置
c.搜索
apt-cache search python --搜索软件包
apt-cache show python --获取包的相关信息,如说明、大小、版本等
apt-cache madison vim --列出软件的所有来源
apt-cache policy vim --列出软件的所有来源
apt-cache showpkg vim --列出软件的所有来源
apt-show-versions -u vim --查询是否有升级版本
apt-cache show vim --查询指定包的详情
dpkg -l vim --查询指定包的详情
dpkg -l | grep vim --查询指定包的详情
dpkg -s package --查询指定包的详情
d.查看
dpkg -l python*
ls | grep python
ls /usr/bin/python*
ls -l /usr/bin/ | grep python
apt list --installed --列出所有已安装的包
apt list --all-versions --列出所有已安装的包的版本信息
02.常用信息2
a.安装
apt-get install python --最新版
apt-get install python=3.6.5 --指定版本
apt-get install python --reinstall --重新安装
apt-get install -f python --修复安装
apt-get install -s python --模拟安装
b.卸载
apt-get remove python --删除包
apt-get purge python --删除包,包括配置文件等
apt-get remove python --purge --删除包,包括配置文件等
c.依赖
apt-cache depends python --查看使用该包依赖那些包
apt-cache rdepends python --查看该包被哪些包依赖
apt-get build-dep python --安装相关的编译环境
apt-get source python --下载该包的源代码
apt-get install apt-show-versions && apt-show-versions -a python--列出软件所有的版本,并查看是否已经安装
d.清理
apt-get clean && apt-get autoclean --清理无用的包
apt-get autoremove --清理不再使用的依赖和库文件
apt-get check --检查是否有损坏的依赖
e.更新
apt update --更新源(全部)
apt upgrade --更新已安装的包(全部)
apt full-upgrade --在升级软件包时自动处理依赖关系
apt upgrade python --更新python包
apt list --upgradeable --列出可更新的包
apt dist-upgrade --升级系统
2.2 dpkg
01.dpkg
dpkg -i package.deb --安装包
dpkg -r package --删除包
dpkg -P package --删除包(包括配置文件)
dpkg -L package --列出与该包先关联的文件
dpkg -l package --显示该包的版本
dpkg -l --列出当前已安装的包
dpkg -S keyword --搜索所属的包内容
dpkg -s package --查找包的详细信息
dpkg -c package.deb --列出deb包的内容
dpkg --configure package --配置软件包
dpkg --unpack package.deb --解压deb包的内容
02.dpkg-deb
dpkg-deb -c linuxcool.deb --显示软件包中的文件列表
dpkg-deb -e linuxcool.deb drcom/DEBIAN --解压控制文件
dpkg-deb -x linuxcool.deb drcom --将软件包的文件释放到指定目录下
dpkg-deb -x linuxcool.deb drcom --将软件包的文件释放到指定目录下,显示过程
dpkg-deb -b linuxcool.deb --创建Debian软件包
2.3 trash
01.方式一:root用户,设置回收站
vi ~/.bashrc --打开bashrc,并追加如下内容
---------------------------------------------------------------------------------------------------------
#alias rm='rm -i' --注释掉rm
mkdir -p ~/.trash
alias rm=trash
alias r=trash
alias rl='ls ~/.trash'
alias ur=undelfile
undelfile() {
mv -i ~/.trash/$@ ./
}
trash() {
mv $@ ~/.trash/
}
cleartrash() {
read -p "clear sure?[n/y]" confirm
[ $confirm == 'y' ] || [ $confirm == 'Y' ] && /bin/rm -rf ~/.trash/*
}
---------------------------------------------------------------------------------------------------------
source ~/.bashrc --重新加载环境变量
02.方式二:普通用户,设置回收站
vi /etc/profile --打开/etc/profile,并追加如下内容
---------------------------------------------------------------------------------------------------------
#alias rm='rm -i' --注释掉rm
mkdir -p ~/.trash
alias rm=trash
alias r=trash
alias rl='ls ~/.trash'
alias ur=undelfile
undelfile() {
mv -i ~/.trash/$@ ./
}
trash() {
mv $@ ~/.trash/
}
cleartrash() {
read -p "clear sure?[n/y]" confirm
[ $confirm == 'y' ] || [ $confirm == 'Y' ] && /bin/rm -rf ~/.trash/*
}
---------------------------------------------------------------------------------------------------------
source /etc/profile --重新加载环境变量
03.测试
[root@bigdata01 ~]# cd ~
[root@bigdata01 ~]# ll .trash/ --发现.trash文件夹
total 0
[root@bigdata01 ~]# rm TODO1.txt --删除TODO1.txt
[root@bigdata01 ~]# ll .trash/ --查看回收站,发现TODO1.txt存在
total 4
-rw-r--r-- 1 root root 1679 Jul 23 00:52 TODO1.txt
[root@bigdata01 ~]# cleartrash --清空回收站
clear sure?[n/y]y
[root@bigdata01 ~]# ll .trash/ --查看回收站,发现TODO1.txt不存在
total 0
2.4 make
01.介绍
a.介绍
makefile:自动化编译,make是一个解释makefile中指令的命令工具,
b.命令
a.make / make all / make -j 4
make:根据makefile文件编译源代码、连接、生成目标文件、可执行文件
make all:没有直接使用make,all参数会编译所有子模块
make -j 4:调用4核心进行编译来加快处理速度
b.make test
检查是否有安装错误
c.make clean
清除上次的make命令所产生的object文件(后缀为“.o”的文件)及可执行文件
d.make install / make altinstall
make altinstall:commoninstall,一个过程,不会创建符号链接
make install:commoninstall、bininstall、maninstall,三个过程,会创建符号链接
将编译成功的可执行文件安装到系统目录中,无--prefix参数指定,默认为/usr/local/bin目录
e.make uninstall
卸载make install安装的文件
f.make dist
产生发布软件包文件,会将可执行文件及相关文件打包成一个tar.gz压缩的文件用来作为发布软件的软件包
在当前目录下生成“PACKAGE-VERSION.tar.gz”,configure.in中定义的AM_INIT_AUTOMAKE(PACKAGE, VERSION)
02.通过configure生成makefile文件
a.prefix
如果指定该参数,
自定可执行文件../bin;库文件../lib;配置文件../include;资源../share
如果不指定该参数,
默认可执行文件/usr/local/bin;库文件/usr/local/lib;配置文件/usr/local/include;资源/usr/local/share
b.enable-shared
启用共享,方便其他依赖 python 的一些内置库资源的正常安装
c.enable-optimizations
优化选项,编译后性能有10%左右的优化
2.5 group
01.修改密码
a.root用户
[root@bigdata01 ~]# passwd
更改用户 root 的密码
新的 密码:
b.其他用户
[root@bigdata01 ~]# cat /etc/passwd --查看全部用户
myslayers:x:1002:1002::/home/myslayers:/bin/bash
-----------------------------------------------------------------------------------------------------
[root@bigdata01 ~]# passwd myslayers --修改密码
更改用户 myslayers 的密码
新的 密码:
c.IP下面有多个用户,通过端口连接某一个用户
[root@bigdata01 ~]# cd /home
[root@bigdata01 ~]# ls
02.创建组
a.命令1
groupadd db --创建名为db的组
useradd -g db myslayers --创建名为myslayers的用户
passwd myslayers --创建名为myslayers的对应密码
su myslayers --切换myslayers
su --切换root
-----------------------------------------------------------------------------------------------------
userdel -r myslayers --删除myslayers
cat /etc/passwd --删除myslayers:x:1002:1002::xxx
b.修改权限
a.查看权限文件
whereis sudoers
b.修改权限
chmod 777 /etc/sudoers
c.追加
vi /etc/sudoers
root ALL=(ALL) ALL
myslayers ALL=(ALL) ALL --授予新增用户myslayer全部权限
d.还原权限
chmod 440 /etc/sudoers


2.6 softlink
a.创建
ln -s [源文件或目录] [目标文件或目录]
ln –s /var/www/test test --/var/www/test创建到test(当前路径)
ln –s /var/www/test /var/test --/var/www/test创建到/var/test(绝对路径)
ln -s /usr/local/mysql/bin/mysql /usr/bin --对/usr/bin目录下的mysql命令创建了软连接
b.删除
rm –rf [软链接名称]
rm –rf test --删除该软链接
c.修改
ln –s /var/www/test /var/test --创建软链接
ln –snf /var/www/test1 /var/test --修改指向的新路径
2.7 compile
01.常见编译
a.cmake
a.卸载旧版本
apt remove cmake && cmake --version
b.安装
cd /opt/ && wget https://github.com/Kitware/CMake/releases/download/v3.20.5/cmake-3.20.5-linux-x86_64.sh && chmod +x /opt/cmake-3.20.5-linux-x86_64.sh && bash /opt/cmake-3.20.5-linux-x86_64.sh && mv cmake-3.20.5-linux-x86_64 cmake-3.20.5 && rm -rf cmake-3.20.5-linux-x86_64.sh
c.软链接
ln -s /opt/cmake-3.20.5/bin/* /usr/bin
ln -s /opt/cmake-3.20.5/bin/* /usr/local/bin
d.检查
cmake --version
b.openssl-1.1.1
a.依赖、卸载旧版本
apt-get install build-essential
apt-get -y purge openssl && rm -rf /etc/ssl
b.安装
cd /root/ && wget --no-check-certificate https://www.openssl.org/source/openssl-1.1.1g.tar.gz && tar -zxvf openssl-1.1.1g.tar.gz && rm -rf openssl-1.1.1g.tar.gz && cd openssl-1.1.1g && ./config --prefix=/usr/local/openssl-1.1.1g && make && make install && rm -rf /root/openssl-1.1.1g
c.环境变量、共享库路径
echo 'export PATH=$PATH:/usr/local/openssl-1.1.1g/bin' >> /etc/profile && source /etc/profile
echo '/usr/local/openssl-1.1.1g/lib' >> /etc/ld.so.conf && ldconfig
d.查看版本
openssl version
c.fd-8.2.1
a.安装
cd /root/ && wget https://github.com/sharkdp/fd/releases/download/v8.2.1/fd-v8.2.1-x86_64-unknown-linux-gnu.tar.gz && tar -zxvf fd-v8.2.1-x86_64-unknown-linux-gnu.tar.gz && mv fd-v8.2.1-x86_64-unknown-linux-gnu /usr/local/fd-8.2.1 && rm -rf fd-v8.2.1-x86_64-unknown-linux-gnu.tar.gz
b.编译
cd /usr/local/fd-8.2.1/ && mandb
c.软连接
cp /usr/local/fd-8.2.1/fd /usr/local/bin/
cp /usr/local/fd-8.2.1/fd.1 /usr/local/share/man/
d.测试
fd
02.常见环境
a.alias
echo "alias ll='ls -l'" >> ~/.bashrc && source ~/.bashrc
b.net-tools、yum、wget、curl、git
apt-get install -y net-tools yum wget curl git
c.compile_basic
apt-get -y install gcc g++ make cmake
d.compile_python
apt-get -y install build-essential tk-dev
apt-get -y install libncurses5-dev libncursesw5-dev libreadline6-dev
apt-get -y install libdb5.3-dev libgdbm-dev libsqlite3-dev libssl-dev libc6-dev
apt-get -y install libbz2-dev libexpat1-dev liblzma-dev zlib1g-dev libffi-dev
e.compile_vim8
apt-get -y install libcairo2-dev libx11-dev libxpm-dev libxt-dev python3-dev ruby-dev libperl-dev
2.8 partition
01.磁盘分区与文件系统挂载
a.介绍
a.组成
组成:硬盘分区由主分区、扩展分区和逻辑分区组成
主分区:主要是用来启动操作系统的,放操作系统的启动或引导程序,/boot分区最好放在主分区上
扩展分区:不能使用的,只为逻辑分区的容器存在的,真正存放数据是主分区和逻辑分区,大量数据都放在逻辑分区
-------------------------------------------------------------------------------------------------
LINUX规定:逻辑分区必须建立在扩展分区之上,而不是建立在主分区上
b.扩容
第一种(常规):找一块磁盘分区,格式化,然后挂载,然后把数据拷贝到新加的磁盘上,然后把原有的磁盘卸载掉
如果第二次扩容,空间还是不够,又需要重复上面的步骤;
如果分配的磁盘空间过大,使用一段时间后,有需要再次调整;
第二种(LVM):逻辑卷管理,可以弹性的管理文件系统的容量,
将一些零碎的磁盘分区(PV)合并成一个较大的磁盘(VG),
然后在根据需要对这个较大的磁盘(VG)进行划分成不同的大小分区(LV),
这些小的分区(LV)是可以动态的扩展和缩小的,这就是LVM的逻辑卷管理过程
c.PV、VG、LV
PV(Physical Volume)- 物理卷
物理卷在逻辑卷管理中处于最底层,它可以是实际物理硬盘上的分区,也可以是整个物理硬盘,也可以是raid设备
-------------------------------------------------------------------------------------------------
VG(Volumne Group)- 卷组
卷组建立在物理卷之上,一个卷组中至少要包括一个物理卷,在卷组建立之后可动态添加物理卷到卷组中
一个逻辑卷管理系统工程中可以只有一个卷组,也可以拥有多个卷组
-------------------------------------------------------------------------------------------------
LV(Logical Volume)- 逻辑卷
逻辑卷建立在卷组之上,卷组中的未分配空间可以用于建立新的逻辑卷,逻辑卷建立后可以动态地扩展和缩小空间
系统中的多个逻辑卷可以属于同一个卷组,也可以属于不同的多个卷组
d.组成
primary:主分区 可以做引导分区;最多不能超过四个;在主分区中,不允许再建立其他逻辑分区
extended:扩展分区 不可引导的分区称之为扩展分区;最多一个
logic:逻辑分区 需要从扩展分区中分逻辑分区
e.物理卷、卷组、逻辑卷
pvdisplay --查看物理分区
vgdisplay --查看卷组信息
lvdisplay --查看逻辑分区
b.fdisk分区
a.查看分区
lsblk --查看全部磁盘
df -h --查看全部磁盘
df -k --查看全部磁盘
df -T -h --查看全部磁盘
fdisk -l --查看分区表状态
b.进行分区
Command (m for help): p --查看分区表信息
Command (m for help): d --删除分区
Partition number (1-4): 4 --删除第四个(sda4)
Command (m for help): p --查看分区信息,/dev/sda4已被删除
Command (m for help): n --创建新的分区
First cylinder (1497-3916, default 1497): --默认,设置起始分区
Using default value 3916 --手动,设置结束分区
Command (m for help): wp --保存并退出,如果创建有误,直接退出
c.临时挂载,重启后失效
mkdir /mnt/cdrom && mount -t iso9960 /dev/sr0 /mnt/cdrom --挂载
umount /mnt/cdrom --卸载
d.永久挂载
echo “/dev/mapper/centos-root / ext3 defaults 0 0” >>/etc/fstab
mount -a --读取/etc/fstab,自动挂载
c.parted分区
a.删除分区
# parted /dev/sdb --进入/dev/sdb
(parted)p --查看
(parted)rm 1 --删除分区1
(parted)rm 2 --删除分区2
b.将磁盘格式变成gpt格式
# parted /dev/sdb --进入/dev/sdb
(parted) mklabel gpt --转换gpt
(parted) unit MB(GB,TB) --设置单位为TB
(parted) mkpart primary 1 500 (分第一个主分区500MB)
(parted) mkpart primary 501 1000 (分第二个主分区500MB)
(parted) mkpart logical 1001 2000 (分第三个逻辑分区1000MB)
(parted) quit --退出
c.格式化已经分好的分区
# partprobe --通知操作系统【分区表】已改变
# mkfs -t ext4 /dev/sdb1 --格式化
d.挂载
mount /dev/sdb1 /mnt
echo “/dev/sdb1 / ext4 defaults 0 0” >>/etc/fstab
mount -a --读取配置文件挂载
e.测试
reboot
fdisk -l
c.结论
a.图示
lsblk --查看全部磁盘
-------------------------------------------------------------------------------------------------
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 40G 0 disk
├─sda1 8:1 0 300M 0 part /boot
├─sda2 8:2 0 7G 0 part /home
├─sda3 8:3 0 2G 0 part [SWAP]
├─sda4 8:4 0 1K 0 part
└─sda5 8:5 0 10G 0 part /
sdb 8:16 0 20G 0 disk
└─sdb1 8:17 0 20G 0 part
└─centos-root 253:0 0 20G 0 lvm /troyekk
sdc 8:32 0 20G 0 disk
└─sdc1 8:33 0 20G 0 part
└─centos-tmp 253:1 0 20G 0 lvm /troyekk
b.结论
结论1:TYPE为【part】与【lvm】二者格式不同,不能相互进行扩容
结论2:【sda】与【sdb】、【sdc】,【不同磁盘,但是均为LVM格式,因此可以互相扩容】
结论3:【sda】上,【如果有剩余空间,直接直接扩容】
02.Centos7扩容
a.第一步:给【/dev/sda】分区
编辑虚拟机位置 -> 添加 -> 硬盘 -> 下一步
-> SCSI(S) -> 创建新虚拟磁盘 -> 20GB、拆分为多个文件 -> bigdata03-0.vmdk -> 完成
-----------------------------------------------------------------------------------------------------
[root@bigdata01 ~]# df -h --第1步:查看现有的空间情况
Filesystem Size Used Avail Use% Mounted on
devtmpfs 2.9G 0 2.9G 0% /dev
tmpfs 2.9G 0 2.9G 0% /dev/shm
tmpfs 2.9G 20M 2.9G 1% /run
tmpfs 2.9G 0 2.9G 0% /sys/fs/cgroup
/dev/sda5 10G 10G 20K 100% /
/dev/sda2 7.0G 33M 7.0G 1% /home
/dev/sda1 297M 126M 172M 43% /boot
tmpfs 579M 0 579M 0% /run/user/0
-----------------------------------------------------------------------------------------------------
[root@bigdata01 ~]# lsblk --第1步:查看现有的空间情况
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 40G 0 disk
├─sda1 8:1 0 300M 0 part /boot
├─sda2 8:2 0 7G 0 part /home
├─sda3 8:3 0 2G 0 part [SWAP]
├─sda4 8:4 0 1K 0 part
└─sda5 8:5 0 10G 0 part /
sdb 8:16 0 40G 0 disk
└─sdb1 8:17 0 40G 0 part
└─centos-root 253:0 0 40G 0 lvm
sr0 11:0 1 4.4G 0 rom
-----------------------------------------------------------------------------------------------------
[root@bigdata01 ~]# fdisk -l --第2步:查看新增磁盘分区(/dev/sdb)
Disk /dev/sda: 42.9 GB, 42949672960 bytes, 83886080 sectors --原磁盘:/dev/sda
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x000a3da6
Device Boot Start End Blocks Id System
/dev/sda1 * 2048 616447 307200 83 Linux
/dev/sda2 616448 15296511 7340032 83 Linux
/dev/sda3 15296512 19490815 2097152 82 Linux swap / Solaris
/dev/sda4 19490816 41943039 11226112 5 Extended
/dev/sda5 19492864 40464383 10485760 83 Linux
Disk /dev/sdb: 21.5 GB, 21474836480 bytes, 41943040 sectors --新磁盘:/dev/sdb
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
-----------------------------------------------------------------------------------------------------
[root@bigdata01 ~]# fdisk /dev/sdb --第3步:分配/dev/sdb
Welcome to fdisk (util-linux 2.23.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Device does not contain a recognized partition table
Building a new DOS disklabel with disk identifier 0xc2ee50a1.
Command (m for help): n --n:创建磁盘
Partition type:
p primary (0 primary, 0 extended, 4 free)
e extended
Select (default p): p --p:主分区
Partition number (1-4, default 1):
First sector (2048-41943039, default 2048): 2048
Last sector, +sectors or +size{K,M,G} (2048-83886079, default 83886079): 83886079
Using default value 41943039
Partition 1 of type Linux and of size 40 GiB is set
Command (m for help): t --t:修改分区类型
Selected partition 1 --输入刚才的分区号1
Hex code (type L to list all codes): 8e --输入分区类型8e
Changed type of partition 'Linux' to 'Linux LVM'
Command (m for help): w --w:保存退出
The partition table has been altered!
Calling ioctl() to re-read partition table.
Syncing disks.
-----------------------------------------------------------------------------------------------------
[root@bigdata01 ~]# reboot --重启系统
[root@bigdata01 ~]# fdisk -l --查看全部分区
b.第二步:给【/dev/sda】格式化
[root@bigdata01 ~]# pvcreate /dev/sdb1 --第1步:创建【物理卷】为sdb1
Physical volume "/dev/sdb1" successfully created.
-----------------------------------------------------------------------------------------------------
[root@bigdata01 ~]# vgcreate centos /dev/sdb1 --第2步:创建【卷组】为centos
Volume group "centos" successfully created
-----------------------------------------------------------------------------------------------------
[root@bigdata01 ~]# lvcreate -L 19G -n root centos --第3步:为centos创建【逻辑卷】19G
Logical volume "root" created.
-----------------------------------------------------------------------------------------------------
[root@bigdata01 ~]# mkfs.xfs -f /dev/centos/root --第4步:【格式化】逻辑分区
[root@bigdata01 ~]# lvextend -l +100%FREE /dev/centos/root --第4步:【扩展已有卷】到文件系统
[root@bigdata01 ~]# xfs_growfs /dev/centos/root --第4步:写入文件系统,使扩容生效
-----------------------------------------------------------------------------------------------------
[root@bigdata01 ~]# pvdisplay --第5步:查看物理分区
[root@bigdata01 ~]# vgdisplay --第5步:查看卷组信息
[root@bigdata01 ~]# lvdisplay --第5步:查看逻辑分区
c.第三步:将【格式好的分区】进行挂载
[root@bigdata01 ~]# mkdir /data && mount /dev/centos/root /data --第1步:挂载到【/data】目录
-----------------------------------------------------------------------------------------------------
[root@bigdata01 ~]# df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 2.9G 0 2.9G 0% /dev
tmpfs 2.9G 0 2.9G 0% /dev/shm
tmpfs 2.9G 12M 2.9G 1% /run
tmpfs 2.9G 0 2.9G 0% /sys/fs/cgroup
/dev/sda5 10G 2.9G 7.2G 29% /
/dev/sda2 7.0G 33M 7.0G 1% /home
/dev/sda1 297M 126M 172M 43% /boot
tmpfs 579M 0 579M 0% /run/user/0
/dev/mapper/centos-root 39G 49M 37G 1% /data --新增【/dev/mapper/centos-root】
-----------------------------------------------------------------------------------------------------
[root@bigdata01 ~]# vi /etc/fstab --第2步:永久挂载
[root@bigdata01 ~]# /dev/mapper/centos-root /data xfs defaults 0 0
-----------------------------------------------------------------------------------------------------
[root@bigdata01 ~]# umount /data
[root@bigdata01 ~]# mount -a --第3步:读取/etc/fstab,自动挂载
[root@bigdata01 ~]# reboot --第4步:重启,查看挂载点,是否失效
d.补充:sdc1(20G)扩容到sdb1(20G)上,并挂载到【/data】
[root@bigdata01 ~]# fdisk /dev/sdc --第3步:分配/dev/sdb
Welcome to fdisk (util-linux 2.23.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Device does not contain a recognized partition table
Building a new DOS disklabel with disk identifier 0xc2ee50a1.
Command (m for help): n --n:创建磁盘
Partition type:
p primary (0 primary, 0 extended, 4 free)
e extended
Select (default p): p --p:主分区
Partition number (1-4, default 1):
First sector (2048-41943039, default 2048): 2048
Last sector, +sectors or +size{K,M,G} (2048-83886079, default 83886079): 83886079
Using default value 41943039
Partition 1 of type Linux and of size 40 GiB is set
Command (m for help): t --t:修改分区类型
Selected partition 1 --输入刚才的分区号1
Hex code (type L to list all codes): 8e --输入分区类型8e
Changed type of partition 'Linux' to 'Linux LVM'
Command (m for help): w --w:保存退出
The partition table has been altered!
Calling ioctl() to re-read partition table.
Syncing disks.
-----------------------------------------------------------------------------------------------------
[root@bigdata01 ~]# lvm
lvm> pvcreate /dev/sdc1 --第1步:创建【物理卷】为sdc1
lvm> pvdisplay
--- Physical volume ---
PV Name /dev/sdb1
VG Name centos --VG为centos
PV Size <20.00 GiB / not usable 3.00 MiB
Allocatable yes (but full)
PE Size 4.00 MiB
Total PE 5119
Free PE 0
Allocated PE 5119
PV UUID 24F2K7-kPBU-0IWh-I4EU-j60e-1ozV-0RDJD6
"/dev/sdc1" is a new physical volume of "<20.00 GiB"
--- NEW Physical volume ---
PV Name /dev/sdc1
VG Name --VG为空
PV Size <20.00 GiB
Allocatable NO
PE Size 0
Total PE 0
Free PE 0
Allocated PE 0
PV UUID ZZJVrQ-t9sF-fAmd-GK2v-cQIE-Q15b-6rEcCE
lvm> vgextend centos /dev/sdc1 --第2步:扩展【卷组】为centos
Volume group "centos" successfully extended
lvm> pvdisplay
--- Physical volume ---
PV Name /dev/sdb1
VG Name centos --VG为centos
PV Size <20.00 GiB / not usable 3.00 MiB
Allocatable yes (but full)
PE Size 4.00 MiB
Total PE 5119
Free PE 0
Allocated PE 5119
PV UUID 24F2K7-kPBU-0IWh-I4EU-j60e-1ozV-0RDJD6
--- Physical volume ---
PV Name /dev/sdc1
VG Name centos --VG为centos
PV Size <20.00 GiB / not usable 3.00 MiB
Allocatable yes
PE Size 4.00 MiB
Total PE 5119
Free PE 5119
Allocated PE 0
PV UUID ZZJVrQ-t9sF-fAmd-GK2v-cQIE-Q15b-6rEcCE
lvm> lvextend -l +100%FREE /dev/centos/root --第3步:对逻辑卷扩容
Size of logical volume centos/root changed from <20.00 GiB to 39.99 GiB.
lvm> quit
Exiting.
-----------------------------------------------------------------------------------------------------
[root@bigdata01 ~]# xfs_growfs /dev/centos/root --第4步:同步到文件系统进行扩容
meta-data=/dev/mapper/centos-root isize=512 agcount=9, agsize=1245184 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=0 spinodes=0
data = bsize=4096 blocks=10483712, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=1
log =internal bsize=4096 blocks=2560, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
-----------------------------------------------------------------------------------------------------
[root@bigdata01 ~]# df -h --第5步:【/data】从20GB变为40GB
Filesystem Size Used Avail Use% Mounted on
devtmpfs 2.9G 0 2.9G 0% /dev
tmpfs 2.9G 0 2.9G 0% /dev/shm
tmpfs 2.9G 12M 2.9G 1% /run
tmpfs 2.9G 0 2.9G 0% /sys/fs/cgroup
/dev/sda5 10G 2.9G 7.2G 29% /
/dev/sda2 7.0G 33M 7.0G 1% /home
/dev/sda1 297M 126M 172M 43% /boot
tmpfs 579M 0 579M 0% /run/user/0
/dev/mapper/centos-root 40G 33M 40G 1% /data

2.9 gcc与g++
01.总结
gcc代表的是C语言编译器
g++代表的是C++语言编译器
02.区别
a.区别1
gcc 会将后缀为 .c 的文件当作 C 程序,将后缀为 .cpp 的文件当作 C++ 程序;
g++ 会将后缀为 .c 和 .cpp 的都当成 C++ 程序;
b.区别2
因为 C 和 C++ 语法上有一些区别,所以有时候通过 g++ 编译的程序不一定能通过 gcc 编译。要注意的是,gcc 和 g++ 都可以用来编译 C 和 C++ 代码。
链接方式不同:gcc 不会自动链接 C++ 库(比如 STL 标准库),g++ 会自动链接 C++ 库;
预处理器宏不同:g++ 会自动添加一些预处理器宏,比如 __cplusplus ,但是 gcc 不会;
3 network
3.1 jdk1
01.安装
rpm -ivh jdk-8u231-linux-x64.rpm
02.环境变量
vi /etc/profile
export JAVA_HOME=/usr/java/jdk1.8.0_231-amd64
export CLASSPATH=$JAVA_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$PATH
03.刷新环境变量
source /etc/profile
04.验证java
java -version
05.卸载系统自带的jdk
yum list installed | grep java --列举匹配已安装的java的软件包
yum -y remove java-1.7.0-openjdk* --卸载安装的jdk
yum -y remove java-1.8.0-openjdk*
yum -y remove jdk1.8.x86_64

3.2 jdk2
01.安装
tar -zxvf jdk-8u202-linux-x64.tar.gz -C /usr/local
02.环境变量
vi /etc/profile
export JAVA_HOME=/usr/local/jdk1.8.0_202
export CLASSPATH=$JAVA_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$PATH
03.刷新环境变量
source /etc/profile
04.验证java
java -version
05.卸载系统自带的jdk
yum list installed | grep java --列举匹配已安装的java的软件包
yum -y remove java-1.7.0-openjdk* --卸载安装的jdk
yum -y remove java-1.8.0-openjdk*
yum -y remove jdk1.8.x86_64
3.3 maven
01.安装
tar -zxvf apache-maven-3.6.3-bin.tar.gz -C /usr/local
02.环境变量
vi /etc/profile
export MAVEN_HOME=/usr/local/apache-maven-3.6.3
export PATH=$MAVEN_HOME/bin:$PATH
03.刷新环境变量
source /etc/profile
04.验证mvn
mvn -v
05.settings.xml(pom.xml编码方式来配置Tomcat服务器)
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<pluginGroups></pluginGroups>
<proxies></proxies>
<servers></servers>
<mirrors>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>jdk-1.8</id>
<activation>
<jdk>1.8</jdk>
</activation>
<properties>
<java.version>1.8</java.version>
<maven.test.skip>true</maven.test.skip>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
</profile>
<profile>
<id>sonar</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<sonar.login>admin</sonar.login>
<sonar.password>12345678</sonar.password>
<sonar.host.url>http://192.168.2.129:9089</sonar.host.url>
</properties>
</profile>
</profiles>
<activeProfiles>
<activeProfile>jdk-1.8</activeProfile>
<activeProfile>sonar</activeProfile>
</activeProfiles>
</settings>
3.4 tomcat
01.安装
tar -zxvf apache-tomcat-9.0.78.tar.gz -C /usr/local
02.环境变量
vi /etc/profile
export CATALINA_HOME=/usr/local/apache-tomcat-9.0.78
export PATH=$CATALINA_HOME/bin:$PATH
03.刷新环境变量
source /etc/profile
3.5 git
01.依赖
yum -y install curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils-MakeMaker
02.安装
wget https://github.com/git/git/archive/refs/tags/v2.38.1.tar.gz
tar zxvf git-2.38.1.tar.gz -C /usr/local
03.编译
cd /usr/local/git-2.38.1
make prefix=/usr/local/git-2.38.1 all
make prefix=/usr/local/git-2.38.1 install
04.环境变量
vi /etc/profile
export GIT_HOME=/usr/local/git-2.38.1
export PATH=.:$GIT_HOME/bin:$PATH
05.刷新环境变量
source /etc/profile
06.验证git
git --version
3.6 ssh
01.介绍
a.发展
SCP:secure copy,是用来进行远程文件拷贝的。数据传输使用SSH,并且和SSH使用相同的认证方式
FTP:在TCP/IP网络和INTERNET上最早使用的协议之一,它属于网络协议组的应用层
FTPS:FTP借助SSL协议加密传输,不但要用FTP服务器还要用SSL协议加密
SFTP:SFTP与FTP有着几乎一样的语法和功能,SFTP为SSH的一部分,为传输文件提供一种安全的加密方法
b.SSH
ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]
[-D [bind_address:]port] [-e escape_char] [-F configfile]
[-i identity_file] [-L [bind_address:]port:host:hostport]
[-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]
[-R [bind_address:]port:host:hostport] [-S ctl_path]
[-W host:port] [-w local_tun[:remote_tun]]
[user@]hostname [command]
-----------------------------------------------------------------------------------------------------
ssh [email protected] -p 22 --登录
ssh [email protected] -p 22 ls -l --登录:执行完ls -l返回本机
netstat -lntup | grep ssh --查看SSH端口
----------------------------------------------------------------
cat /etc/ssh/sshd_config --配置文件
cat /root/.ssh/known_hosts --查看已知主机
----------------------------------------------------------------
ssh-keygen -t rsa --第1步:id_rsa私钥、id_rsa.pub公钥
ssh-copy-id localhost --第2步:发送私钥(本机)
ssh-copy-id bigdata02 --第3步:发送公钥(其他计算机)
ssh bigdata02 --第4步:测试免密钥登陆
c.SSH自带SFTP
sftp -oport=22 [email protected] --登录
quit --断开连接
clear --清屏
-----------------------------------------------------------------------------------------------------
lcd --本地
lpwd --本地
lls --本地
lrm path --本地
lmkdir path --远程
lrmdir path --本地
lrename oldname newname --本地
----------------------------------------------------------------
cd --远程
pwd --远程
ls --远程
rm path --远程
mkdir path --远程
rmdir path --远程
rename oldname newname --远程
-----------------------------------------------------------------------------------------------------
sftp> lcd D:/MyKit/test
sftp> cd /home/ilog/test
sftp> put 2020.txt
put D:/MyKit/test/2020.txt /home/ilog/test/ --put 本地目录/文件名 远程目录
----------------------------------------------------------------
sftp> lcd D:/MyKit/test
sftp> cd /home/ilog/test
sftp> put -r log
put -r D:/MyKit/test/logs/ /home/ilog/test/ --put -r 本地目录/文件夹名 远程目录
-----------------------------------------------------------------------------------------------------
sftp> cd /home/ilog/test
sftp> lcd D:/MyKit/test
sftp> get 0824
get /home/ilog/test/0824.txt D:/MyKit/test/ --get 远程目录/文件名 本地目录
----------------------------------------------------------------
sftp> cd /home/ilog/test
sftp> lcd D:/MyKit/test
sftp> get -r data
get -r /home/ilog/test/data/ /home/my/ --get -r 远程目录/文件夹名 本地目录
-----------------------------------------------------------------------------------------------------
注意1:上传或下载文件夹和文件夹下内容需要使用 get -r 或 put -r,-r代表目录
注意2:文件夹number下有2个文件number_1和number_2
get number 会下载文件number及文件number_1和number_2
get number/ 只下载文件number_1和number_2
d.SSH自带SCP
a.下载
scp [email protected]:/home/kimi/test.txt /tmp/local_dir
--下载文件:把 192.168.0.101上的/home/kimi/test.txt文件 下载到 /tmp/local_dir文件夹下
-------------------------------------------------------------------------------------------------
scp -r [email protected] /home/kimi/test /tmp/local_dir
--下载文件夹:把 192.168.0.101上的/home/kimi/test文件夹 下载到 /tmp/local_dir文件夹下
b.上传
scp /var/www/test.php [email protected]:/var/www/
--上传文件:把 本地/var/www/test.php文件 上传到 192.168.0.101上的/var/www/文件夹下
-------------------------------------------------------------------------------------------------
scp -r /var/www/test [email protected]:/var/www/
--上传文件夹:把 本地/var/www/test文件夹 上传到 192.168.0.101上的/var/www/文件夹下
c.注意
注意1:上传或下载文件夹和文件夹下内容需要使用 get -r 或 put -r,-r代表目录
注意2:文件夹number下有2个文件number_1和number_2
get number 会下载文件number及文件number_1和number_2
get number/ 只下载文件number_1和number_2
02.SSH介绍(GPG服务)
a.known_hosts(存放在客户端,客户端检查主机是否为真主机)
服务器认证,用户访问的SSH服务器的DSA主机密钥
客户端连接服务器时,客户端通过检查【储存的主机密钥】来验证服务器身份
{server-id} ssh-rsa {public-key-string} {comment}
b.authorized_keys(存放在服务端,主机检查是否允许客户端登录)
用户认证,服务器的授权公共密钥列表
客户端连接服务器时,服务器通过检查【存储已签名公钥】来验证用户端身份
ssh-rsa {public-key-string} {comment}
c.介绍
ssh -V:OpenSSH_for_Windows_7.7p1, LibreSSL 2.6.5
sshd.exe:远程所管理的系统上必须运行的 SSH 服务器组件
ssh.exe:在用户的本地系统上运行的 SSH 客户端组件
ssh-keygen.exe:为 SSH 生成、管理和转换身份验证密钥
ssh-agent.exe:存储用于公钥身份验证的私钥
ssh-add.exe:将私钥添加到服务器允许的列表中,即添加到 ssh-agent 中
ssh-keyscan.exe:帮助从许多主机收集公用 SSH 主机密钥
sftp.exe:提供安全文件传输协议的服务,通过 SSH 运行
scp.exe:在 SSH 上运行的文件复制实用工具
d.常见报错
内容:kex_exchange_identification: Connection closed by remote host
解决1:找到known_hosts文件,将其清空,然后重新通过终端访问服务器主机
解决2:使用git clone https://github.com/halavah/dotfiles.git,后链接到browser进行认证
03.Linux安装SSH
a.安装openssh-server
yum list installed | grep openssh-server --检测是否安装
yum install openssh-server --如果未安装,则安装openssh-server
yum install -y glibc libgcc libstdc++ python ca-certificates tar openssh-server bash curl
b.配置
vi /etc/ssh/sshd_config
Port 22 --监听端口
ListenAddress 0.0.0.0 --监听地址
ListenAddress :: --监听地址
PermitRootLogin yes --开启远程访问(SSH,root用户登录)
--------------------------
PubkeyAuthentication yes --开启密钥验证(SSH,pubkey登录)
AuthorizedKeysFile .ssh/authorized_keys --开启密钥验证(SSH,pubkey登录)
--------------------------
PasswordAuthentication yes --开启密码验证(SSH,密码验证)
c.开启服务
systemctl start sshd --开启服务
systemctl enable sshd --开机自启
systemctl restart sshd --重启服务
ps -e | grep sshd --检查sshd服务是否已经开启
systemctl list-unit-files | grep sshd --检查sshd服务是否开机自启
yum check-update && yum install code -y --远程机器安装VScode
d.ssh免密钥登录(Remote-SSH只提供使用RSA秘钥远程登录,SSH不支持命令行-p输入明文密码)(默认aes256-cbc类型)
a.win10生成密钥
ssh-keygen -t rsa
b.将Win10中的公钥id_rsa.pub -> 手动放到Centos7中的authorized_keys
chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys
c.win10远程访问(C:\Windows\System32\OpenSSH)
ssh [email protected]
ssh [email protected] -i "C:\Users\mysla\.ssh\id_rsa.ppk" -P 22
ssh [email protected] -i "C:\Users\mysla\.ssh\id_rsa.ppk" -P 22
d.putty远程访问(D:\software\Java\putty-0.74)
connection -> SSH -> Auth -> Browse -> 选中putty密钥(id_rsa.ppk)
session -> IP(192.168.2.128)、Port(22)、Saved(bigdata01) -> 连接
e.报错
a.问题一:Resolver error: Error: at Function.Create...at Object.t.handleInstallOutput
解决:不使用默认Win10的OpenSSH,而是Git自带的SSH
配置:"remote.SSH.path": "D:\\software\\Linux\\Window\\Git\\usr\\bin\\ssh.exe"
b.问题二:Resolver error: Error: at Function.Create...at Object.t.handleInstallOutput
解决:使用 nvm alias default node 命令,将远程服务器的默认值更改为正确的节点版本
配置:nvm ls && nvm alias default node && nvm ls
c.问题三:C:\WINDOWS\system32\cmd.exe,拒绝访问
配置:secpol.msc打开管理员权限,或者以管理员身份运行VScode
04.Windows安装OpenSSH服务器(C:\Windows\System32\OpenSSH)(C:\ProgramData\ssh\sshd_config)
a.安装
a.方式1:自带
设置 -> 应用 -> 应用和功能 -> 可选功能 -> 添加功能 -> OpenSSH客户端
设置 -> 应用 -> 应用和功能 -> 可选功能 -> 添加功能 -> OpenSSH服务器
b.方式2:使用PowerShell安装OpenSSH
Get-WindowsCapability -Online | ? Name -like 'OpenSSH*' --查看是否安装
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0 --安装OpenSSH.Client
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 --安装OpenSSH.Server
Remove-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0 --卸载OpenSSH.Client
Remove-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 --卸载OpenSSH.Server
c.方式3
https://github.com/PowerShell/Win32-OpenSSH/releases/download/v8.1.0.0p1-Beta/OpenSSH-Win64.zip
cd C:\"Program Files\OpenSSH"
powershell.exe -ExecutionPolicy Bypass -File install-sshd.ps1 --服务:安装sshd
sc config sshd start= auto --服务:自启动
sc config sshd start= demand --服务:手动启动
net start sshd --服务:启动sshd
sc delete ssh-agent --服务:删除ssh-agent
sc delete sshd --服务:删除sshd
sc delete ssh-agent --服务:删除ssh-agent
sc stop sshd --服务:停止sshd
sc stop ssh-agent --服务:停止ssh-agent
Get-Service ssh-agent --查看ssh-agent服务
Start-Service ssh-agent --启动ssh-agent服务
ssh-add C:\Users\mysla\.ssh\id_rsa --将私钥加载进ssh-agent
ssh-add -L --验证私钥是否添加成功
netsh advfirewall firewall add rule name=sshd dir=in action=allow protocol=TCP localport=22
b.启动
cd "C:\Windows\System32\OpenSSH"
Start-Service sshd
Set-Service -Name sshd -StartupType 'Automatic'
Get-NetFirewallRule -Name *ssh*
New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
c.配置(默认端口:22,默认用户名:电脑账户名,默认密码:电脑账户密码)
vi C:\ProgramData\ssh\sshd_config
Port 22 --监听端口
ListenAddress 0.0.0.0 --监听地址
ListenAddress :: --监听地址
PermitRootLogin yes --开启远程访问
PasswordAuthentication yes --开启密码验证
--------------------------
PubkeyAuthentication yes --开启密钥验证
AuthorizedKeysFile .ssh/authorized_keys --开启密钥验证
d.报错1:使用PowerShell管理员修复权限
cd C:\"Program Files\OpenSSH"
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process
FixHostFilePermissions.ps1 --修复主机端的文件权限
FixUserFilePermissions.ps1 --修复客户端的文件权限
e.报错2:解决Bad owner or permissions问题
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process
import-Module D:\software_ware\workspace_data\Windows\OpenSSHUtils.psm1
Repair-UserSshConfigPermission ~/.ssh/config
Get-ChildItem ~\.ssh\* -Include "id_rsa","id_dsa" -ErrorAction SilentlyContinue | % {
Repair-UserKeyPermission -FilePath $_.FullName @psBoundParameters
}
05.Windows安装OpenSSH服务器(C:\Windows\System32\OpenSSH)(C:\ProgramData\ssh\sshd_config)
a.开启
设置 -> 应用 -> 应用和功能 -> 可选功能 -> 添加功能 -> OpenSSH客户端
设置 -> 应用 -> 应用和功能 -> 可选功能 -> 添加功能 -> OpenSSH服务器
b.启动
cd "C:\Windows\System32\OpenSSH"
Start-Service sshd
Set-Service -Name sshd -StartupType 'Automatic'
Get-NetFirewallRule -Name *ssh*
c.服务
OpenSSH SSH Server、Open SSH Authentication Agent
d.登陆ssh
ssh [email protected] 22
ssh [email protected] 22
e.登录sftp(OpenSSH 9.0发布,scp默认使用sftp协议)
sftp [email protected] 22
sftp [email protected] 22

3.7 path
01.介绍
a.交互式shell、非交互式shell
交互式shell:用户输入命令后输出相应内容,如登录、登出
非交互式shell:读取存放在文件中的命令,当它读到文件的结尾,shell也就终止了
b.读取流程
当登入系统时候获得一个shell进程时,其读取环境设定档有三步:
首先,读入系统的环境信息,读入/etc/profile,并读取额外配置/etc/profile.d、/etc/inputrc
然后,读入系统的环境信息,读入/etc/bashrc
其次,根据不同的用户类型,根据优先级(~/.bash_profile > ~/.bash_login > ~/.profile)读入配置文件
最后,根据不同的用户类型,读入~/.bashrc
02.配置文件
a.profile:/etc/profile > ~/.bash_profile > ~/.bash_login > ~/.profile
专有路径、环境变量
以login方式进入bash
当用户登录时,该文件仅仅执行一次
b.bashrc:/etc/bashrc > ~/.bashrc
专有路径、专有文档、命令别名
以non-login方式进入bash
每次Shell被打开时,该文件都被被读取
03.环境变量
a.系统变量
vi /etc/profile
PATH=$PATH:$HOME/bin
PATH=$PATH:$HOME/bin:/usr/local/python/bin:/usr/local/maven/bin
b.用户变量
vi /root/.profile
PATH=$PATH:$HOME/bin
PATH=$PATH:$HOME/bin:/usr/local/python/bin:/usr/local/maven/bin
c.查看变量
Advantage:/usr/local/sbin > /usr/local/bin > /usr/sbin > /usr/bin > /sbin > /bin
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
echo $PATH
04.命令别名
a.用户别名
vi /root/.bashrc
echo "alias ll='ls -l'" >> ~/.bashrc && source ~/.bashrc
echo "alias python='/usr/bin/python3.6'" >> ~/.bashrc && source ~/.bashrc
b.查看别名
cat /root/.bashrc
3.8 proxy
01.介绍
a.内容
export http_proxy="http://192.168.2.2:7890" unset http_proxy
export https_proxy="http://192.168.2.2:7890" unset https_proxy
export ftp_proxy="http://192.168.2.2:7890" unset ftps_proxy
export all_proxy="http://192.168.2.2:7890" unset all_proxy
export no_proxy="localhost, 127.0.0.1, ::1" unset no_proxy
b.测试
curl -vv https://www.google.com && curl -vv https://www.youtube.com
ping 属于 ICMP 协议,而非 http、https 协议,应该 curl 发起请求;如果关闭 Clash,则 应用代理 无法连接网络
02.Windows
a.git
git config --global http.proxy 'http://127.0.0.1:7890'
git config --global https.proxy 'http://127.0.0.1:7890'
b.cmd
setx -m http_proxy "http://127.0.0.1:7890" && setx -m https_proxy "http://127.0.0.1:7890"
c.vscode
"http.proxy": "http://127.0.0.1:7890"
d.jetbrains
HTTP:127.0.0.1、7890、SOCKS:127.0.0.1、7891
03.Linux(LAN / TUN / TAP)
a.Centos7
a.vi /etc/profile
export http_proxy=http://192.168.2.2:7890
export https_proxy=http://192.168.2.2:7890
export ftp_proxy=http://192.168.2.2:7890
b.vi /etc/wgetrc
export http_proxy=http://192.168.2.2:7890
export https_proxy=http://192.168.2.2:7890
export ftp_proxy=http://192.168.2.2:7890
c.vi /etc/yum.conf
export http_proxy=http://192.168.2.2:7890
export https_proxy=http://192.168.2.2:7890
export ftp_proxy=http://192.168.2.2:7890
b.Debian10
a.vi /etc/profile
export http_proxy=http://192.168.2.2:7890
export https_proxy=http://192.168.2.2:7890
export ftp_proxy=http://192.168.2.2:7890
export all_proxy=http://192.168.2.2:7890
b.vi /etc/wgetrc
export http_proxy=http://192.168.2.2:7890
export https_proxy=http://192.168.2.2:7890
export ftp_proxy=http://192.168.2.2:7890
c.vi /etc/yum/yum.conf
export http_proxy=http://192.168.2.2:7890
export https_proxy=http://192.168.2.2:7890
export ftp_proxy=http://192.168.2.2:7890
d.vi /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://192.168.2.2:7890" "HTTPS_PROXY=http://192.168.2.2:7890"
3.9 centos6
01.磁盘分区(Linux系统必须开启sshd.service服务:setup -> 系统服务 -> sshd.service)
swap ext4 2048MB
/boot ext4 300MB
/home ext4 7168MB
/ ext4 10240MB
02.虚拟网络编辑器(VMnet8)
子网IP 192.168.2.0
子网掩码 255.255.255.0
NAT设置 192.168.2.1
DHCP设置 192.168.2.128 192.168.2.254
03.网络适配器(VMnet8 -> TCP/IPv4)
IP地址 192.168.2.2
子网掩码 255.255.255.0
默认网关 192.168.2.1
04.修改网卡配置 vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
HWADDR=00:0C:29:7A:D1:F2 --MAC地址
TYPE=Ethernet
UUID=b129cd07-0a05-419e-a3a1-4d73d3f37917 --唯一标识符
ONBOOT=yes --系统启动的时候网络接口是否有效
NM_CONTROLLED=yes --无需重启网卡立即生效
BOOTPROTO=static --静态ip
IPADDR=192.168.2.128 --IP地址
GATEWAY=192.168.2.1 --默认网关IP地址
NETMASK=255.255.255.0 --网络掩码
BROADCAST=192.168.2.255 --广播地址
DNS1=114.114.114.114 --中国电信
DNS2=8.8.8.8 --谷歌
05.映射 vi /etc/hosts 或 C:\Windows\System32\drivers\etc\hosts
192.168.2.128 bigdata01
192.168.2.129 bigdata02
192.168.2.130 bigdata03
192.168.2.131 bigdata04
192.168.2.132 bigdata05
192.168.2.2 bigdata
06.配置DNS解析
vi /etc/resolv.conf --设置DNS解析
service NetworkManager stop --停止网络服务
chkconfig NetworkManager off --禁止网络自启
/etc/init.d/network restart --重启网卡
07.防火墙
service iptables stop --关闭当前防火墙
chkconfig iptables off --禁止开机自启
service iptables status --查看防火墙状态
08.集群搭建
a.修改计算机名
vi /etc/sysconfig/network --修改HOSTNAME=bigdata01
bigdata01 --虚拟机名
bigdata01 --网络名
b.修改ip
vi /etc/sysconfig/network-scripts/ifcfg-eth0 --删除UUID、HWADDR
c.删除文件(防止重启后恢复初始化)
rm -r /etc/udev/rules.d/70-persistent-net.rules
d.增加映射
vi /etc/hosts 或 C:\Windows\System32\drivers\etc\hosts
e.SSH免密钥登陆
a.生成密钥
ssh-keygen -t rsa
b.发送私钥(本机)
ssh-copy-id localhost
c.发送公钥(其他计算机)
ssh-copy-id bigdata02
d.测试免密钥登陆
ssh bigdata02
f.自动同步时间
a.安装用于同步时间的 ntp插件
yum -y install ntp ntpdate --终端安装时间同步插件
ntpdate cn.pool.ntp.org --设置时间同步
b.将系统时间写入硬盘时间
hwclock --systohc


3.10 centos7
01.磁盘分区
swap ext4 2048MB
/boot ext4 300MB
/home ext4 7168MB
/ ext4 10240MB
02.虚拟网络编辑器(VMnet8)
子网IP 192.168.2.0
子网掩码 255.255.255.0
NAT设置 192.168.2.1
DHCP设置 192.168.2.128 192.168.2.254
03.网络适配器(VMnet8 -> TCP/IPv4)
IP地址 192.168.2.2
子网掩码 255.255.255.0
默认网关 192.168.2.1
04.修改网卡配置 vi /etc/sysconfig/network-scripts/ifcfg-ens33
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33
UUID=a31f175d-d650-4fd3-9a6d-b96328b0c896
DEVICE=ens33
ONBOOT=yes
IPADDR=192.168.2.128
GATEWAY=192.168.2.1
BROADCAST=192.168.2.255
DNS1=114.114.114.114
DNS2=8.8.8.8
05.映射 vi /etc/hosts 或 C:\Windows\System32\drivers\etc\hosts
192.168.2.128 bigdata01
192.168.2.129 bigdata02
192.168.2.130 bigdata03
192.168.2.131 bigdata04
192.168.2.132 bigdata05
192.168.2.2 bigdata
06.配置DNS解析
vi /etc/NetworkManager/NetworkManager.conf --在[main]后追加dns=none
vi /etc/resolv.conf --设置DNS解析
systemctl restart NetworkManager --Centos8:重启网络
systemctl status NetworkManager --Centos8:查看状态
systemctl restart network --Centos7:重启网络
systemctl status network --Centos7:查看状态
/etc/init.d/network restart --Centos6:重启网络
/etc/init.d/network status --Centos6:查看状态
sudo systemctl restart networking --Ubuntu/Debian:重启网络
sudo systemctl status networking --Ubuntu/Debian:查看状态
07.防火墙
systemctl stop firewalld --关闭防火墙
systemctl disable firewalld --禁止开机自启
systemctl status firewalld --防火墙状态
systemctl start firewalld --开启防火墙
systemctl enable firewalld --开启开机自启
firewall-cmd --reload --重启防火墙
firewall-cmd --zone=public --add-port=3306/tcp --permanent --开放3306端口
firewall-cmd --zone=public --remove-port=3306/tcp --permanent --关闭3306端口
firewall-cmd --zone=public --list-ports --查看开放端口
firewall-cmd --state --查看防火墙状态
yum install net-tools -y && netstat -lnpt --查看当前所有tcp端口
netstat -lnpt | grep 3306 --查看所有3306端口使用情况
ps 3306 --查看进程的详细信息
08.集群搭建
a.修改计算机名
hostnamectl set-hostname bigdata01
b.修改ip
vi /etc/sysconfig/network-scripts/ifcfg-ens33 --删除UUID
c.增加映射
vi /etc/hosts 或 C:\Windows\System32\drivers\etc\hosts
d.重启网卡
service network restart
e.SSH免密钥登陆
a.生成密钥
ssh-keygen -t rsa
b.发送私钥(本机)
ssh-copy-id localhost
c.发送公钥(其他计算机)
ssh-copy-id bigdata02
d.测试免密钥登陆
ssh bigdata02
f.自动同步时间
a.安装用于同步时间的 ntp插件
yum -y install ntp ntpdate --终端安装时间同步插件
ntpdate cn.pool.ntp.org --设置时间同步
b.将系统时间写入硬盘时间
hwclock --systohc

3.11 gitlab
https://packages.gitlab.com/gitlab/gitlab-ce
https://about.gitlab.com/install/

4 port
4.1 bio
01.汇总
a.Traefik
a.特点
自动服务发现
动态配置
Let's Encrypt 集成
Docker原生支持
提供Web UI
配置简单直观
b.适用场景
容器环境
微服务架构
需要动态配置
b.HAProxy
a.特点
高性能
可靠性强
专注负载均衡
详细的统计信息
支持TCP和HTTP
b.适用场景
高并发
需要精细负载均衡
对性能要求高
c.Caddy
a.特点
配置最简单
自动HTTPS
自动证书管理
开箱即用
Go语言编写
b.适用场景
小型项目
快速部署
重视易用性
d.Apache
a特点
功能全面
稳定可靠
模块化设计
广泛支持
成熟生态
b.适用场景
传统Web服务
需要特定模块
复杂规则配置
e.Envoy
a.特点
现代化设计
C++编写
高性能
可观测性强
适合服务网格
适用场景:
云原生环境
服务网格
需要详细监控
02.对比分析
a.汇总
性能:HAProxy > Nginx > Envoy > Traefik > Caddy
功能性:Nginx > Envoy > Traefik > HAProxy > Caddy
易用性:Caddy > Traefik > Nginx > HAProxy > Envoy
配置复杂度:Caddy < Traefik < Nginx < HAProxy < Envoy
社区活跃度:Nginx > Traefik > HAProxy > Caddy > Envoy
b.不同场景的推荐
小型项目:Caddy(配置最简单)
中型项目:Traefik(好管理,功能足够)
大型项目:HAProxy(性能好,可靠)、Envoy(现代化,可观测)
03.pingora
a.背景
Cloudflare开源
Rust语言编写
2024年发布
b.优势
更高性能
内存安全
异步I/O
易于扩展
现代化架构
c.特色功能
动态配置
热重载
内置监控
TLS 1.3支持
d.与Nginx对比
a.性能方面
Nginx:稳定可靠、经过验证、广泛使用、生态完善
Pingora:更低的延迟、更好的并发处理、更高的吞吐量、更少的资源消耗
b.开发语言
Pingora: Rust(内存安全,性能好)
Nginx: C(传统,成熟)
c.配置方式
Pingora: 代码配置(Rust)
Nginx: 文本配置文件
e.使用场景
适合使用Nginx:稳定性要求高、需要丰富生态、配置简单直观、团队熟悉度高
适合使用Pingora:高性能需求、需要定制开发、熟悉Rust、追求现代化方案、关注安全性
f.优缺点分析
Nginx优点:稳定可靠、文档丰富、生态完善、使用简单
Nginx缺点:性能相对较低、扩展开发难、架构较老
Pingora优点:性能更优、内存安全、现代化设计、可编程性强
Pingora缺点:较新,不够成熟、生态不完善、学习曲线陡、案例较少
g.选择建议
建议使用Nginx:需要稳定性、标准Web服务、团队经验丰富、重视生态支持
建议使用Pingora:对性能要求极高、团队有Rust开发能力、需要深度定制、愿意尝试新技术
4.2 frps
01.服务端
a.下载
wget https://github.com/fatedier/frp/releases/download/v0.33.0/frp_0.33.0_linux_amd64.tar.gz && tar -zxvf frp_0.33.0_linux_amd64.tar.gz && vi /root/frp_0.33.0_linux_amd64/frps.ini
b.编辑frps.ini
[common]
bind_port = 7000
token = 12345678
vhost_http_port = 8080
dashboard_port = 7500
dashboard_user = admin
dashboard_pwd = admin
enable_prometheus = true
log_file = /var/log/frps.log
log_level = info
log_max_days = 3
c.启动frps
mkdir -p /etc/frp && cp /root/frp_0.33.0_linux_amd64/frps.ini /etc/frp && cp /root/frp_0.33.0_linux_amd64/frps /usr/bin && cp /root/frp_0.33.0_linux_amd64/systemd/frps.service /usr/lib/systemd/system/ && systemctl enable frps && systemctl start frps && systemctl status frps
nohup /root/frp_0.33.0_linux_amd64/frps -c /root/frp_0.33.0_linux_amd64/frps.ini &
d.防火墙
yum install net-tools -y && netstat -lnpt
firewall-cmd --state && firewall-cmd --zone=public --list-ports
firewall-cmd --permanent --add-port=7000/tcp && firewall-cmd --permanent --add-port=7500/tcp && firewall-cmd --permanent --add-port=80/tcp && firewall-cmd --permanent --add-port=443/tcp && firewall-cmd --permanent --add-port=8080/tcp && firewall-cmd --permanent --add-port=2222/tcp && firewall-cmd --reload
02.客户端
a.下载
https://github.com/fatedier/frp/releases/download/v0.33.0/frp_0.33.0_windows_amd64.zip
b.配置frpc.ini
[common]
server_addr = myslayers.cn
server_port = 7000
token = 12345678
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 2222
[web]
type = http
local_port = 8080
custom_domains = myslayers.cn
c.启动frpc
d: && cd D:\software\Java\frp-0.33.0 && frpc.exe -c frpc.ini
d: && cd D:\software\Java\frp-0.33.0 && nssm install frpc && net start frpc
d.防火墙
网络 -> 属性 -> Windows Defender防火墙 -> 启动或关闭Windows Defender防火墙 -> 关闭
03.访问:工位主机 -> 穿透 -> 腾讯云 -> 在家办公
http://myslayers.cn:7500
http://myslayers.cn:8080
4.3 turn
01.网络协议
a.NAT的挑战
NAT允许私有网络中的多台设备共享一个公共IP地址访问互联网。
然而,它也给P2P通信带来了困难,因为设备在私有网络中拥有私有IP地址,无法直接被外部网络访问。防火墙的存在也进一步限制了直接连接。
b.STUN协议 (Session Traversal Utilities for NAT)
a.作用
主要用于检测NAT类型并获取客户端的公共IP地址和端口号。
b.工作原理
a.绑定请求
客户端向STUN服务器发送一个“绑定请求”。
b.返回公共IP
STUN服务器将客户端的公共IP地址和端口号返回给客户端。
c.建立P2P连接
客户端可以使用这些公共IP地址信息来尝试与其他客户端建立P2P直接连接。
c.目标
促进P2P直接连接,避免数据中继,从而提高通信效率和降低延迟。
d.部署
通常部署在公共云或数据中心,以确保客户端可以快速获取其公共IP。
e.局限性
STUN并非万能。在某些严格的NAT类型(如对称NAT)或防火墙配置下,STUN可能无法帮助客户端建立P2P连接。
c.TURN协议 (Traversal Using Relays around NAT)
a.作用
当STUN无法建立P2P直接连接时,TURN充当中继服务器,帮助客户端之间传输数据。
b.工作原理
a.连接到TURN服务器
当两个客户端无法直接通信时,它们会连接到TURN服务器。
b.数据中继
客户端A将数据发送给TURN服务器,TURN服务器接收数据并转发给客户端B。
c.中介角色
TURN服务器充当了两个客户端之间的“中介”或“桥梁”。
c.目标
确保在任何网络环境下都能实现可靠的端到端通信,即使无法建立P2P直接连接。
d.安全性
在中继过程中,数据通常会进行加密,以保证传输的安全性。
e.缺点
a.增加延迟
数据需要经过中继服务器,而不是直接传输,会引入额外的网络跳数和处理时间。
b.增加带宽消耗
中继服务器需要处理所有通过它的数据流量。
c.服务器成本
运行TURN服务器需要消耗带宽和计算资源。
f.使用场景
作为STUN的补充,当STUN失败时作为最后的保障。应尽可能避免使用TURN,因为它会降低传输速度并增加延迟,但在必要时它能确保通信的建立。
d.P2P连接的限制及解决方案
a.为什么P2P连接会受限
a.NAT的存在
大多数设备在私有网络中,通过NAT共享一个公共IP。
NAT会将私有IP和端口映射到公共IP和端口。
当两个处于不同NAT网络中的客户端尝试P2P通信时,它们无法直接通过私有IP互相访问。
b.防火墙的存在
出于安全考虑,许多网络会设置防火墙,阻止未经授权的入站连接。
即使没有NAT,防火墙也可能拦截P2P连接尝试的数据包。
b.解决方案
a.STUN
尝试协助客户端发现其公共IP和端口,以便在可能的情况下建立直接的P2P连接(穿透NAT)。
b.TURN
当STUN无法实现直接连接时,TURN服务器作为中继,接收一方的数据并转发给另一方,从而确保通信的建立。
e.总结图示
客户端A <---------------------------------> 客户端B
| |
| (尝试P2P直接连接) |
| |
| (若失败,则通过中继) |
V V
STUN服务器 (获取公共IP) TURN服务器 (中继数据)
f.核心思想
STUN和TURN共同为实时通信提供了健壮的解决方案。STUN优先尝试建立高效的P2P直接连接,
而TURN则作为备用方案,在直接连接不可行时提供可靠的数据中继,确保通信的连通性。
在实际应用中(如WebRTC),通常会同时使用STUN和TURN服务器,以应对各种复杂的网络环境。
02.STUN服务器
a.准备工作
a.安装 coturn 依赖
sudo yum install openssl-devel
sudo yum install sqlite
sudo yum install sqlite-devel
sudo yum install libevent
sudo yum install libevent-devel
sudo yum install postgresql-devel
sudo yum install postgresql-server
sudo yum install mysql-devel
sudo yum install mysql-server
sudo yum install hiredis
sudo yum install hiredis-devel
b.coturn 代码的下载与编译
a.下载 coturn 源代码
cd /opt
git clone https://github.com/coturn/coturn.git # 下载 coturn 源代码
b.编译和安装 coturn
cd coturn # 进入 coturn 源代码目录
source ./configure
make -j 8
sudo make install
-------------------------------------------------------------------------------------------------
说明:
a.source ./configure: 配置编译环境,检查系统依赖等。
b.make -j 8: 使用 8 个并行作业编译 coturn (根据您的 CPU 核心数调整 `-j` 参数以加速编译)。
c.sudo make install: 将编译好的 coturn 程序安装到系统路径中,通常是 `/usr/local/bin` 和 `/usr/local/etc` 等。
c.配置 coturn 服务器
a.查找并拷贝配置文件
`make install` 命令执行后,coturn 的默认配置文件 `turnserver.conf.default` 会被放置在 `/usr/local/etc` 目录下。
进入该目录并将其拷贝一份,命名为 `turnserver.conf`:
-------------------------------------------------------------------------------------------------
cd /usr/local/etc
cp turnserver.conf.default turnserver.conf # 拷贝默认配置文件并重命名
b.vi turnserver.conf
# 监听 IP 地址 (内网 IP)
listening-ip=${内网IP}
# 中继 IP 地址 (内网 IP)
relay-ip=${内网IP}
# 外部 IP 地址 (公网 IP)
external-ip=${外网IP}
# 用户认证信息
user=username:password # 替换为您的用户名和密码,例如 user=wfchat:wfchat
# 下面两个端口均要大于10000,推荐使用 IANA 建议的动态/私有端口范围 (49152-65535)
min-port=49152
max-port=65535
d.启动与管理 coturn 服务
a.启动 coturn 服务
turnserver -v -r ${公网IP}:3478 -a -o -c /usr/local/etc/turnserver.conf
-------------------------------------------------------------------------------------------------
-v: 启用详细输出,方便调试。
-r ${公网IP}:3478: 指定 STUN 服务器的公共地址和端口。
-a: 启用长期凭证机制 (long-term credentials)。
-o: 启用 TURN over TCP。
-c /usr/local/etc/turnserver.conf: 指定使用的配置文件路径。
b.查看服务状态
ps -ef | grep turn
-------------------------------------------------------------------------------------------------
如果看到 `turnserver` 相关的进程信息,则表示服务已启动。
c.关闭单个进程
kill [pid]
d.关闭所有 coturn 进程
killall turnserver
e.验证部署结果
a.访问在线 STUN/TURN 测试网站
https://docs.wildfirechat.cn/webrtc/trickle-ice/
b.输入信息:
STUN/TURN 服务器地址:`stun:${公网IP}:3478`
用户名:您在 `turnserver.conf` 中配置的用户名 (例如 `wfchat`)
密码:您在 `turnserver.conf` 中配置的密码 (例如 `wfchat`)
c.预期结果:
当成功部署并配置正确时,您会看到测试结果显示 `relay` (表示 TURN 功能正常) 和 `done` (表示测试完成)。
f.部署失败常见原因与排查
a.问题
您的云服务器安全组或系统防火墙(如 `firewalld` 或 `ufw`)
没有开放 coturn 使用的端口 (默认为 `3478`,以及您在 `min-port` 和 `max-port` 中设置的端口范围)
b.解决方案
确保在云服务器控制台的安全组规则中同时开放 `TCP` 和 `UDP` 的 `3478` 端口
以及您配置的 `min-port` 到 `max-port` 范围。如果使用了系统防火墙,也需要相应地开放这些端口。
c.问题
某些服务(如 Nginx)可能占用了 coturn 需要的端口,导致 coturn 无法正常启动或工作。
d.解决方案:
1.临时关闭冲突服务:在启动 coturn 之前,尝试临时关闭可能冲突的服务(例如 `sudo systemctl stop nginx`)。
2.启动 coturn:确认 coturn 成功启动并验证。
3.重新启动冲突服务:之后再启动冲突服务 (`sudo systemctl start nginx`)。通常情况下,一旦 coturn 成功绑定了端口,
后续启动的其他服务不会影响它。如果仍然冲突,可能需要调整 coturn 或其他服务的监听端口。
03.TURN服务器
a.准备工作
a.获取root权限 (可选但推荐)
sudo -i
b.安装GCC编译环境
# 首先,检查GCC是否已安装:
which gcc
# 如果未安装,请安装`build-essential`包,它包含了GCC和其他必要的编译工具:
sudo apt update
sudo apt install build-essential
c.安装libssl-dev
# 这是OpenSSL的开发库,coturn编译时需要它。
sudo apt install libssl-dev
b.安装libevent
a.下载
wget --no-check-certificate https://gitee.com/langgehenshuai/softs/raw/master/libevent-2.1.12.tar.gz
b.解压
tar -zxvf libevent-2.1.12.tar.gz
c.编译并安装
cd libevent-2.1.12/
./configure
make
sudo make install
d.安装sqlite(可选)
# 如果您计划使用SQLite作为coturn的用户数据库,请安装以下包:
sudo apt install sqlite3 libsqlite3-dev
c.安装coturn
a.下载
wget --no-check-certificate https://gitee.com/langgehenshuai/softs/raw/master/coturn-4.5.1.1.tar.gz
b.解压
tar -zxvf coturn-4.5.1.1.tar.gz
c.编译并安装
cd coturn-4.5.1.1
./configure
make
sudo make install
d.验证安装:
# 如果返回路径,则表示安装成功
which turnserver
d.生成TURN用户
a.如果您需要为TURN服务器设置用户认证,可以使用`turnadmin`工具
# 添加用户名为 lang,密码为 11111 ,realm 域为 stun.lang.cn 的用户
turnadmin -a -u lang -p 11111 -r stun.lang.cn
-------------------------------------------------------------------------------------------------
-a: 使用长期凭据机制
-u lang: 用户名为`lang`
-p 11111: 密码为`11111`
-r stun.lang.cn: Realm域为`stun.lang.cn`
b.命令说明:
-a - 使用长期凭据机制
-o - 以守护程序身份运行服务器进程
-v - “中等”详细模式。
-n - 无配置文件
-------------------------------------------------------------------------------------------------
no-dtls - 不启动 DTLS 侦听器
-------------------------------------------------------------------------------------------------
no-tls - 不启动 TLS 侦听器
-u - 要使用的用户凭据
-r - 要使用的默认领域,需要 TURN REST API
e.配置TURN服务
a.复制配置文件
sudo cp /usr/local/etc/turnserver.conf.default /etc/turnserver.conf
b.sudo vim /etc/turnserver.conf
# 指定云主机的公网IP地址
external-ip=公网ip
# 用户:密码
user=lang:111111
# 域名,这个一定要设置
realm=stun.lang.cn
# 指定监听的端口, 默认3478
listening-port=3478
# 指定局域网IP地址,默认内网ip
#listening-ip=内网ip
f.开放端口
a.安装`ufw`
sudo apt install ufw
b.允许TCP和UDP端口3478
sudo ufw allow 3478/tcp
sudo ufw allow 3478/udp
c.允许UDP端口范围
# TURN服务器通常会使用一个范围的UDP端口来传输媒体数据。建议开放`32355-65535`范围的UDP端口。
sudo ufw allow 32355:65535/udp
d.启用`ufw`
sudo ufw enable
e.检查`ufw`状态
sudo ufw status
f.重要提示
如果您的服务器是在云服务提供商(如阿里云、腾讯云等)上,您还需要在云服务商的安全组规则中配置入站和出站规则,
允许UDP和TCP的`3478`端口,以及UDP的`32355-65535`端口
g.启动服务
a.前台启动 (用于测试和调试)
a.方式1
turnserver
b.方式2
turnserver -c /etc/turnserver.conf -v
b.后台启动 (推荐用于生产环境)
a.创建systemd服务文件,sudo vim /etc/systemd/system/coturn.service
[Unit]
Description=Coturn TURN/STUN Server
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/bin/turnserver -c /etc/turnserver.conf -o
ExecReload=/bin/kill -HUP $MAINPID
KillMode=mixed
TimeoutStopSec=5
LimitNOFILE=100000
EnvironmentFile=-/etc/default/coturn
[Install]
WantedBy=multi-user.target
b.重新加载systemd管理器配置
sudo systemctl daemon-reload
c.启动coturn服务
sudo systemctl start coturn
d.设置coturn开机自启
sudo systemctl enable coturn
e.检查服务状态
sudo systemctl status coturn
c.启动与管理 coturn 服务
a.启动 coturn 服务
turnserver -v -r ${公网IP}:3478 -a -o -c /usr/local/etc/turnserver.conf
-------------------------------------------------------------------------------------------------
-v: 启用详细输出,方便调试。
-r ${公网IP}:3478: 指定 STUN 服务器的公共地址和端口。
-a: 启用长期凭证机制 (long-term credentials)。
-o: 启用 TURN over TCP。
-c /usr/local/etc/turnserver.conf: 指定使用的配置文件路径。
b.查看服务状态
ps -ef | grep turn
-------------------------------------------------------------------------------------------------
如果看到 `turnserver` 相关的进程信息,则表示服务已启动。
c.关闭单个进程
kill [pid]
d.关闭所有 coturn 进程
killall turnserver
4.4 gost
01.脚本安装
a.安装
wget --no-check-certificate -O gost.sh https://raw.githubusercontent.com/KANIKIG/Multi-EasyGost/master/gost.sh && chmod +x gost.sh && ./gost.sh
b.中转服务器(加密tls)
安装gost -> 新增gost转发配置 -> 加密隧道流量转发 -> tls -> 收127.0.0.1:3333 -> 发193.239.178.153:4444
c.落地服务器(加密tls)
安装gost -> 新增gost转发配置 -> 解密隧道流量转发 -> tls -> 收127.0.0.1:4444 -> 发127.0.0.1:5555
02.手动安装
a.安装
wget -N --no-check-certificate https://github.com/ginuerzh/gost/releases/download/v2.11.0/gost-linux-amd64-2.11.0.gz && gzip -d gost-linux-amd64-2.11.0.gz && mv gost-linux-amd64-2.11.0 gost && chmod +x gost
wget -N --no-check-certificate https://zhujiget.com/wp-content/uploads/sh/gost.gz && gzip -d gost.gz && chmod +x gost
b.中转服务器(加密tls)
nohup ./gost -L udp://:(本地监听公网端口) -L tcp://:(本地监听公网端口) -F relay+tls://(落地国外服务器IP):(落地gost监听端口) >> /dev/null 2>&1 &
c.落地服务器(加密tls)
nohup ./gost -L relay+tls://:(落地gost监听端口)/127.0.0.1:(上网工具端口) >> /dev/null 2>&1 &
03.命令
a.安装lsof命令
yum install lsof
b.利用lsof命令查看端口占用的进程号,此处的8090为端口号
lsof -i:8090
c.停止进程,此处的8888为进程PID号
kill -9 8888
d.注意:Gost普通端口转发模式,无需安装落地服务器,只需安装中转服务器
nohup ./gost -L=tcp://:(本地gost监听端口)/(落地服务器IP):(上网工具端口) -L=udp://:(本地gost监听端口)/(落地服务器IP):(上网工具端口) >> /dev/null 2>&1 &
4.5 derp
01.基本配置
a.Tailnet name
taile5ba8.ts.net
b.Nameservers
taile5ba8.ts.net 100.100.100.100
c.surge dns
*.ts.net 100.100.100.100
02.高级配置
a.配置位置
Access controls
b.配置文件
{
"derpMap": {"OmitDefaultRegions": false, "Regions": {
"901": {
"RegionID": 901,
"RegionCode": "ucloud-sh",
"RegionName": "cn-sh",
"Nodes": [
{
"Name": "ucloud-sh",
"RegionID": 901,
"IPv4": "106.75.216.170",
// "DERPPort": 4430,
"InsecureForTests": true,
},
],
},
"900": {"RegionID": 900, "RegionCode": "hk3-1495", "RegionName": "azhk", "Nodes": [{
"Name": "azhk",
"RegionID": 900,
"HostName": "6789b763e97f6.derps.link",
"DERPPort": 1200,
"STUNPort": 1200,
"InsecureForTests": true,
}]},
}},
// Declare static groups of users. Use autogroups for all users or users with a specific role.
// "groups": {
// "group:example": ["[email protected]", "[email protected]"],
// },
// Define the tags which can be applied to devices and by which users.
// "tagOwners": {
// "tag:example": ["autogroup:admin"],
// },
// Define access control lists for users, groups, autogroups, tags,
// Tailscale IP addresses, and subnet ranges.
"acls": [
// Allow all connections.
// Comment this section out if you want to define specific restrictions.
{"action": "accept", "src": ["*"], "dst": ["*:*"]},
// Allow users in "group:example" to access "tag:example", but only from
// devices that are running macOS and have enabled Tailscale client auto-updating.
// {"action": "accept", "src": ["group:example"], "dst": ["tag:example:*"], "srcPosture":["posture:autoUpdateMac"]},
],
// Define postures that will be applied to all rules without any specific
// srcPosture definition.
// "defaultSrcPosture": [
// "posture:anyMac",
// ],
// Define device posture rules requiring devices to meet
// certain criteria to access parts of your system.
// "postures": {
// // Require devices running macOS, a stable Tailscale
// // version and auto update enabled for Tailscale.
// "posture:autoUpdateMac": [
// "node:os == 'macos'",
// "node:tsReleaseTrack == 'stable'",
// "node:tsAutoUpdate",
// ],
// // Require devices running macOS and a stable
// // Tailscale version.
// "posture:anyMac": [
// "node:os == 'macos'",
// "node:tsReleaseTrack == 'stable'",
// ],
// },
// Define users and devices that can use Tailscale SSH.
"ssh": [
// Allow all users to SSH into their own devices in check mode.
// Comment this section out if you want to define specific restrictions.
{
"action": "check",
"src": ["autogroup:member"],
"dst": ["autogroup:self"],
"users": ["autogroup:nonroot", "root"],
},
],
"nodeAttrs": [
{
// Funnel policy, which lets tailnet members control Funnel
// for their own devices.
// Learn more at https://tailscale.com/kb/1223/tailscale-funnel/
"target": ["autogroup:member"],
"attr": ["funnel"],
},
],
// Test access rules every time they're saved.
// "tests": [
// {
// "src": "[email protected]",
// "accept": ["tag:example"],
// "deny": ["100.101.102.103:443"],
// },
// ],
}
c.配置说明
{
"derpMap": {
"//": "DERP 中继服务器配置:定义 Tailscale 用于中继流量的服务器。当设备之间无法建立直接的点对点连接时,流量会通过这些中继服务器转发。",
"OmitDefaultRegions": false,
"//OmitDefaultRegions": "设置为 false 表示除了自定义的 DERP 节点外,Tailscale 还会使用其默认的全球 DERP 节点。",
"Regions": {
"//Regions": "自定义的 DERP 区域定义。",
"901": {
"//901": "区域 901 (ucloud-sh) 的配置。",
"RegionID": 901,
"RegionCode": "ucloud-sh",
"RegionName": "cn-sh",
"Nodes": [
{
"//Node": "区域 901 中的第一个 DERP 节点。",
"Name": "ucloud-sh",
"RegionID": 901,
"IPv4": "106.75.216.170",
// "DERPPort": 4430, // 这是一个被注释掉的行,表示默认情况下 DERP 使用 443 端口,如果需要指定其他端口,可以在这里取消注释并设置。
"InsecureForTests": true,
"//InsecureForTests": "重要:这表示该节点在测试模式下运行,可能没有有效的 TLS 证书。不建议在生产环境中使用 true,因为它会降低安全性。通常用于自建 DERP 服务器的调试。"
}
]
},
"900": {
"//900": "区域 900 (hk3-1495) 的配置。",
"RegionID": 900,
"RegionCode": "hk3-1495",
"RegionName": "azhk",
"Nodes": [
{
"//Node": "区域 900 中的第一个 DERP 节点。",
"Name": "azhk",
"RegionID": 900,
"HostName": "6789b763e97f6.derps.link",
"DERPPort": 1200,
"STUNPort": 1200,
"InsecureForTests": true,
"//InsecureForTests_hk": "同样,这是一个测试节点,不建议在生产环境中使用。"
}
]
}
}
},
"//groups_comment": "Declare static groups of users. Use autogroups for all users or users with a specific role.",
// "groups": {
// "group:example": ["[email protected]", "[email protected]"],
// },
"//tagOwners_comment": "Define the tags which can be applied to devices and by which users.",
// "tagOwners": {
// "tag:example": ["autogroup:admin"],
// },
"//acls_comment": "Define access control lists for users, groups, autogroups, tags, Tailscale IP addresses, and subnet ranges.",
"acls": [
"//acls_rule_comment": "允许所有连接。如果需要定义特定限制,请注释掉此部分。",
{"action": "accept", "src": ["*"], "dst": ["*:*"]},
"//acls_example_comment": "允许 'group:example' 中的用户访问 'tag:example',但仅限于运行 macOS 且已启用 Tailscale 客户端自动更新的设备。",
// {"action": "accept", "src": ["group:example"], "dst": ["tag:example:*"], "srcPosture":["posture:autoUpdateMac"]},
],
"//defaultSrcPosture_comment": "Define postures that will be applied to all rules without any specific srcPosture definition.",
// "defaultSrcPosture": [
// "posture:anyMac",
// ],
"//postures_comment": "Define device posture rules requiring devices to meet certain criteria to access parts of your system.",
// "postures": {
// // Require devices running macOS, a stable Tailscale
// // version and auto update enabled for Tailscale.
// "posture:autoUpdateMac": [
// "node:os == 'macos'",
// "node:tsReleaseTrack == 'stable'",
// "node:tsAutoUpdate",
// ],
// // Require devices running macOS and a stable
// // Tailscale version.
// "posture:anyMac": [
// "node:os == 'macos'",
// "node:tsReleaseTrack == 'stable'",
// ],
// },
"//ssh_comment": "Define users and devices that can use Tailscale SSH.",
"ssh": [
"//ssh_rule_comment": "允许所有用户以检查模式 SSH 到他们自己的设备。如果需要定义特定限制,请注释掉此部分。",
{
"action": "check",
"src": ["autogroup:member"],
"dst": ["autogroup:self"],
"users": ["autogroup:nonroot", "root"]
}
],
"//nodeAttrs_comment": "Define special attributes that can be applied to Tailnet devices.",
"nodeAttrs": [
{
"//nodeAttrs_rule_comment": "Funnel 策略,允许 tailnet 成员控制其自己设备的 Funnel 功能。了解更多信息请访问 https://tailscale.com/kb/1223/tailscale-funnel/",
"target": ["autogroup:member"],
"attr": ["funnel"]
}
],
"//tests_comment": "Test access rules every time they're saved.",
// "tests": [
// {
// "src": "[email protected]",
// "accept": ["tag:example"],
// "deny": ["100.101.102.103:443"],
// },
// ]
}
d.配置说明
{
"derpMap": {
// DERP 中继服务器配置
// 定义了 Tailscale 用于中继流量的 DERP 服务器。
// 当设备之间无法建立直接的点对点连接时,流量会通过这些中继服务器转发。
"OmitDefaultRegions": false, // 使用默认的全球 DERP 节点
"Regions": {
"901": {
"RegionID": 901, // 自定义区域 ID
"RegionCode": "ucloud-sh", // 区域代码
"RegionName": "cn-sh", // 区域名称
"Nodes": [
{
"Name": "ucloud-sh", // 节点名称
"RegionID": 901, // 所属区域 ID
"IPv4": "106.75.216.170", // DERP 服务器的 IPv4 地址
// "DERPPort": 4430, // 默认情况下 DERP 使用 443 端口
"InsecureForTests": true // 测试模式下运行,生产环境不建议使用
}
]
},
"900": {
"RegionID": 900,
"RegionCode": "hk3-1495",
"RegionName": "azhk",
"Nodes": [
{
"Name": "hk3-1495",
"RegionID": 900,
"HostName": "6789b763e97f6.derps.link",
"DERPPort": 1200,
"InsecureForTests": true // 测试模式下运行,生产环境不建议使用
}
]
}
}
},
// "groups": {
// // 用户组定义
// // 用于定义静态的用户组
// // 当前被注释掉,未启用
// },
// "tagOwners": {
// // 标签所有者定义
// // 定义哪些用户或用户组可以为设备分配特定的标签
// // 当前被注释掉,未启用
// },
"acls": [
{
"action": "accept", // 允许连接
"src": ["*"], // 允许所有来源
"dst": ["*:*"] // 允许所有目的地
}
// {
// "action": "accept",
// "src": ["group:example"],
// // 示例规则,展示如何根据用户组、标签和设备姿态来限制访问
// // 当前被注释掉,未启用
// }
],
// "defaultSrcPosture": [
// // 默认源姿态定义
// // 定义应用于没有特定 srcPosture 定义的所有规则的默认设备姿态
// // 当前被注释掉,未启用
// ],
// "postures": {
// // 设备姿态定义
// // 定义设备必须满足的特定标准才能被允许访问某些资源
// // 当前被注释掉,未启用
// },
"ssh": [
{
"action": "check", // 检查 SSH 连接,但不强制执行
"src": ["autogroup:member"], // 允许所有 Tailnet 成员作为 SSH 客户端
"dst": ["autogroup:self"], // 允许成员 SSH 到他们自己的设备
"users": ["autogroup:nonroot", "root"] // 允许以非 root 用户或 root 用户身份登录
}
],
"nodeAttrs": [
{
"target": ["autogroup:member"], // 将此属性应用于所有 Tailnet 成员
"attr": ["funnel"] // 允许 Tailnet 成员控制其自己设备的 Funnel 功能
}
]
// "tests": [
// // 测试规则
// // 用于在保存 ACL 规则时进行自动化测试
// // 当前被注释掉,未启用
// ]
}
03.derp部署
a.核心思路
1.准备一台公网服务器:作为您的 DERP 中继服务器。
2.安装 Go 环境:`derper` 服务是 Go 语言编写的。
3.编译和安装 `derper` 服务:这是 Tailscale 的 DERP 服务器程序。
4.生成自签名证书:用于 `derper` 的 HTTPS 服务。
5.运行 `derper` 服务:配置端口、证书等。
6.配置防火墙/安全组:允许 DERP 端口的流量。
7.配置 Tailscale ACL:将您的自定义 DERP 服务器添加到 Tailscale 控制面板。
8.验证:检查 DERP 是否正常工作。
b.在您的公网服务器上部署 `derper` 服务
a.准备服务器
公网 IP:确保您的服务器具有公网 IP 地址。
操作系统:通常是 Linux (如 Ubuntu, CentOS)。
防火墙/安全组:提前规划好需要开放的端口(例如:TCP 33445,UDP 3478 或您自定义的端口)。
b.安装 Golang 环境
# 更新软件源 (根据您的Linux发行版选择合适的命令)
# 对于 Debian/Ubuntu:
sudo apt update && sudo apt upgrade -y
# 对于 CentOS/RHEL:
# sudo yum update -y
# 安装必要的依赖
sudo apt install -y wget git openssl curl # 或者 sudo yum install -y wget git openssl curl
# 下载最新版 Go (请访问 https://go.dev/dl/ 获取最新版本链接)
# 示例:go1.23.1.linux-amd64.tar.gz
cd /usr/local/src # 建议下载到 /usr/local/src
wget https://go.dev/dl/go1.23.1.linux-amd64.tar.gz
# 解压 Go 到 /usr/local
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.23.1.linux-amd64.tar.gz
# 清理下载的压缩包
rm go1.23.1.linux-amd64.tar.gz
# 配置 Go 环境变量 (临时生效)
export PATH=$PATH:/usr/local/go/bin
# 验证 Go 安装
go version
go env
# 永久配置 Go 环境变量 (添加到 ~/.bashrc 或 /etc/profile)
echo "export PATH=$PATH:/usr/local/go/bin" | sudo tee -a /etc/profile
source /etc/profile # 立即生效
# 配置 Go 代理 (如果您的服务器在国内,推荐配置)
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
c.编译和安装 `derper` 服务
# 安装 derper
go install tailscale.com/cmd/derper@main
# 安装 derpprobe (用于测试 derper,可选)
go install tailscale.com/cmd/derpprobe@latest
d.创建自签名证书
# 设置 DERP 主机名和端口变量 (请根据实际情况修改)
# 这个 HostName 必须记住,后面证书签名、derper 启动、ACL 配置都会用到。
export DERP_HOST="your-derp-hostname.com" # 例如:myderp.example.com 或者一个简单的名称如 "my-derp"
export DERP_PORT=33445 # DERP HTTPS/TCP 端口
export STUN_PORT=3478 # STUN UDP 端口 (通常是 3478)
# 创建证书存储目录
mkdir -p ~/.certdir && cd ~/.certdir
# 1. 生成私钥
openssl genpkey -algorithm RSA -out ${DERP_HOST}.key
# 2. 生成证书请求 (CSR)
# 一路回车即可,无需填写信息
openssl req -new -key ${DERP_HOST}.key -out ${DERP_HOST}.csr
# 3. 生成自签名证书 (设置过期期限为 100 年)
openssl x509 -req \
-days 36500 \
-in ${DERP_HOST}.csr \
-signkey ${DERP_HOST}.key \
-out ${DERP_HOST}.crt \
-extfile <(printf "subjectAltName=DNS:${DERP_HOST}")
# 4. 查看生成的证书信息 (可选)
openssl x509 -in ${DERP_HOST}.crt -noout -text
e.运行 `derper` 服务
a.方法一:直接运行 (用于测试)
# 确保在正确的路径下运行 derper,或者将其路径添加到 PATH
# 例如:~/go/bin/derper
~/go/bin/derper \
-c ~/.derper.key \
-a :${DERP_PORT} -http-port -1 \
-stun-port ${STUN_PORT} \
-hostname ${DERP_HOST} \
--certmode manual \
-certdir ~/.certdir \
--verify-clients # 推荐启用,要求客户端也是 Tailscale 节点
---
* `-c ~/.derper.key`: 用于存储 DERP 内部状态的密钥文件。
* `-a :${DERP_PORT}`: 指定 DERP HTTPS/TCP 监听地址和端口。
* `-http-port -1`: 禁用 HTTP 监听(只使用 HTTPS)。
* `-stun-port ${STUN_PORT}`: 指定 STUN UDP 监听端口。
* `-hostname ${DERP_HOST}`: 指定 DERP 服务器的主机名,必须与证书中的 `subjectAltName` 匹配。
* `--certmode manual`: 使用手动提供的证书。
* `-certdir ~/.certdir`: 指定证书文件所在的目录。
* `--verify-clients`: **强烈推荐启用**。这会要求连接到此 DERP 的客户端也必须是您的 Tailnet 中的节点,增加了安全性,防止他人滥用您的 DERP 服务器。
b.方法二:使用 systemd 管理 (推荐)
# 确保您已经安装了 tailscaled 并登录认证,如果希望使用 --verify-clients
# sudo curl -fsSL https://tailscale.com/install.sh | sh
# sudo tailscale up
# 创建 systemd service 文件
# 注意:ExecStart 中的 /home/${USER}/go/bin/derper 路径需要根据您的实际情况调整
# 如果您是 root 用户,${USER} 可能是 root。如果 derper 编译在 /usr/local/bin,则修改路径。
sudo tee /etc/systemd/system/tailscale-derp.service <<EOF
[Unit]
Description=Tailscale derp service
After=network.target
[Service]
ExecStart=/home/${USER}/go/bin/derper \\
-c /home/${USER}/.derper.key \\
-a :${DERP_PORT} -http-port -1 \\
-stun-port ${STUN_PORT} \\
-hostname ${DERP_HOST} \\
--certmode manual \\
-certdir /home/${USER}/.certdir \\
--verify-clients
Restart=always
User=${USER} # 确保 derper 以非 root 用户运行,更安全。如果 derper 在 /usr/local/bin,则可以考虑 User=nobody
[Install]
WantedBy=multi-user.target
EOF
# 重新加载 systemd 配置
sudo systemctl daemon-reload
# 启动服务
sudo systemctl start tailscale-derp.service
# 查看服务状态
sudo systemctl status tailscale-derp.service
# 设置开机自启动
sudo systemctl enable tailscale-derp.service
f.配置防火墙和安全组
a.确保您的服务器防火墙和云服务商的安全组允许以下端口的入站流量
* **TCP**: `DERP_PORT` (例如 33445)
* **UDP**: `STUN_PORT` (例如 3478)
b.示例 (使用 `iptables`)
sudo iptables -A INPUT -p tcp --dport ${DERP_PORT} -j ACCEPT
sudo iptables -A INPUT -p udp --dport ${STUN_PORT} -j ACCEPT
# 如果您使用其他端口,请相应修改
# 保存 iptables 规则 (根据您的 Linux 发行版可能不同)
# 对于 Debian/Ubuntu (使用 netfilter-persistent):
# sudo apt install -y iptables-persistent
# sudo netfilter-persistent save
# 对于 CentOS/RHEL (使用 firewalld):
# sudo firewall-cmd --zone=public --add-port=${DERP_PORT}/tcp --permanent
# sudo firewall-cmd --zone=public --add-port=${STUN_PORT}/udp --permanent
# sudo firewall-cmd --reload
c.配置 Tailscale ACL
a.在您的 Tailscale 管理控制台 (`admin.tailscale.com`) 中,修改 ACL 文件
1.登录到您的 Tailscale 管理页面。
2.导航到 "Access controls" 或 "ACLs"。
3.将以下 `derpMap` 部分添加到您的 ACL JSON 配置中。
b.配置
{
"derpMap": {
// OmitDefaultRegions: true 表示只使用您自定义的 DERP 节点,不使用 Tailscale 官方的节点。
// 如果您想同时使用官方和自定义节点,请设置为 false。
"OmitDefaultRegions": true,
"Regions": {
"901": { // RegionID 可以从 900 开始,每个自定义 DERP 节点递增
"RegionID": 901,
"RegionCode": "my-derp-region-code", // 自定义区域代码,例如 "sh-derp"
"RegionName": "My Custom DERP", // 自定义区域名称,例如 "Shanghai DERP"
"Nodes": [
{
"Name": "my-derp-node-1", // 节点名称
"RegionID": 901,
"HostName": "${DERP_HOST}", // 必须与您在服务器上设置的 DERP_HOST 相同
"IPv4": "您的服务器公网IP", // 填写您的服务器公网 IP
"DERPPort": ${DERP_PORT}, // 填写您设置的 DERP TCP 端口
"STUNPort": ${STUN_PORT}, // 填写您设置的 STUN UDP 端口
"InsecureForTests": true // 因为使用了自签名证书,这里必须是 true
}
]
}
// 如果有多个自定义 DERP 节点,可以在这里添加更多 RegionID
/*
,"902": {
"RegionID": 902,
"RegionCode": "my-derp-region-code-2",
"RegionName": "My Custom DERP 2",
"Nodes": [
{
"Name": "my-derp-node-2",
"RegionID": 902,
"HostName": "your-derp-hostname-2.com",
"IPv4": "您的第二台服务器公网IP",
"DERPPort": 33445,
"STUNPort": 3478,
"InsecureForTests": true
}
]
}
*/
}
}
}
c.验证 DERP 中继服务
a.在 Tailscale 客户端上检查:
在任意 Tailscale 客户端设备上,打开终端或命令提示符。
运行 `tailscale netcheck` 命令。
查找 "DERP" 部分。如果您的自定义 DERP 服务器配置正确并运行,您应该能看到它被列出,并且通常延迟会很低。
---------------------------------------------------------------------------------------------
Report:
* UDP: yes
* IPv4: yes
* IPv6: no
* UPnP: no
* PMP: no
* HairPinning: yes
* PortMapping: no
* Nearest DERP: my-derp-node-1 (my-derp-region-code)
* DERP latency:
my-derp-node-1 (my-derp-region-code): 7.4ms
# 其他官方 DERP 节点 (如果 OmitDefaultRegions 为 false)
b.通过浏览器访问 (可选,用于初步检查 HTTPS 服务是否启动):
在浏览器中访问 `https://您的服务器公网IP:${DERP_PORT}` (例如:`https://180.160.3.56:33445`)。
由于是自签名证书,浏览器会提示不安全,选择继续访问。
如果看到 "DERP" 字样的页面,说明 HTTPS 服务已启动。
c.注意事项
`InsecureForTests: true`:由于您使用了自签名证书,这个选项必须设置为 `true`。这意味着连接是不安全的,但在 Tailscale 内部,流量仍然是端到端加密的。对于自建 DERP 来说,这是常见做法。
`--verify-clients`:强烈建议在 `derper` 启动命令中添加此参数,以增加安全性。
HostName 一致性:`DERP_HOST` 变量、证书中的 `subjectAltName`、`derper` 启动命令中的 `-hostname` 参数以及 ACL 配置中的 `HostName` 字段必须完全一致。
端口一致性:`DERP_PORT` 和 `STUN_PORT` 在 `derper` 启动命令、防火墙/安全组以及 ACL 配置中必须保持一致。
Go 版本:确保安装的 Go 版本是最新稳定版,因为 Tailscale 可能会使用 Go 的新特性。
`OmitDefaultRegions`:根据您的需求选择 `true` (只用自定义 DERP) 或 `false` (同时使用官方和自定义 DERP)。
4.6 trans
00.Linux端口转发概述
在Linux系统中,端口转发是一种将网络流量从一个端口重定向到另一个端口或地址的技术。
它常用于网络管理、负载均衡和安全策略实施。以下是几种常见的Linux端口转发方式。
01.使用iptables进行端口转发
a.定义
iptables 是 Linux 内核中用于配置网络流量过滤规则的工具。它可以用于实现端口转发。
b.将本地端口8080的流量转发到远程服务器的80端口
# 转发到远程服务器
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.100:80
iptables -A FORWARD -p tcp -d 192.168.1.100 --dport 80 -j ACCEPT
# 转发到本地端口
iptables -t nat -A POSTROUTING -j MASQUERADE
c.注意事项
确保内核启用了IP转发功能:`echo 1 > /proc/sys/net/ipv4/ip_forward`
iptables规则需要保存以便重启后生效。
02.使用SSH进行端口转发
a.定义
SSH 端口转发(也称为隧道)允许通过SSH连接将流量从一个端口转发到另一个端口。
b.将本地端口8080转发到远程服务器的80端口
ssh -L 8080:localhost:80 user@remote-server
c.将远程服务器的80端口转发到本地端口8080
ssh -R 8080:localhost:80 user@remote-server
d.使用SOCKS代理进行动态端口转发
ssh -D 1080 user@remote-server
03.使用socat进行端口转发
a.定义
socat 是一个多功能的网络工具,可以用于在不同的地址和端口之间转发流量。
b.将本地端口8080转发到远程服务器的80端口
socat TCP-LISTEN:8080,fork TCP:192.168.1.100:80
04.使用ncat进行端口转发
a.定义
ncat 是 nmap 套件中的一个网络工具,类似于 netcat,可以用于端口转发。
b.将本地端口8080转发到远程服务器的80端口
ncat -l 8080 --sh-exec "ncat 192.168.1.100 80"
4.7 caddy
01.安装
http自动签发证书,对应tls配置
---------------------------------------------------------------------------------------------------------
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
---------------------------------------------------------------------------------------------------------
sudo apt update
sudo apt install caddy
02.命令
caddy run --启动
caddy stop --停止
---------------------------------------------------------------------------------------------------------
caddy env --环境
caddy version --版本
---------------------------------------------------------------------------------------------------------
caddy trust --生成自签名证书
---------------------------------------------------------------------------------------------------------
caddy adapt --config /etc/caddy/Caddyfile --pretty --导出JSON配置
caddy run --config caddy.json --从JSON配置运行
---------------------------------------------------------------------------------------------------------
caddy validate --验证Caddyfile
caddy validate --config /etc/caddy/Caddyfile --验证Caddyfile
caddy fmt --格式化Caddyfile
caddy fmt --overwrite /etc/caddy/Caddyfile --格式化Caddyfile
caddy list-running --列出所有正在运行的Caddy实例
---------------------------------------------------------------------------------------------------------
caddy run --config /etc/caddy/Caddyfile --adapter caddyfile --pidfile /var/run/caddy.pid --后台运行
03.命令2
journalctl -u caddy --查看日志
sudo systemctl start caddy --启动
sudo systemctl stop caddy --停止
sudo systemctl status caddy --状态
sudo systemctl reload caddy --重载
sudo systemctl restart caddy --重启
04.配置文件
sudo su
vi /etc/caddy/Caddyfile
---------------------------------------------------------------------------------------------------------
# 静态文件服务器
:80 {
# Set this path to your site's directory.
root * /usr/share/caddy
# Enable the static file server.
file_server
# Another common task is to set up a reverse proxy:
# reverse_proxy localhost:8080
# Or serve a PHP site through php-fpm:
# php_fastcgi localhost:9000
}
# HTTPS的反向代理服务器
# 将所有发送到 gz.pingx241030.me 的请求转发到 100.64.0.4:82 (内网ip 对应 新加坡机器)
gz.pingx241030.me {
tls {
protocols tls1.2 tls1.3
curves x25519
alpn http/1.1 h2
}
reverse_proxy 100.64.0.4:82
}
# 示例:CF域名映射该机器
test82.halavah.us {
tls {
protocols tls1.2 tls1.3
curves x25519
alpn http/1.1 h2
}
reverse_proxy 100.64.0.8:82
}
# 示例:ip+端口
119.91.252.124:882 {
tls {
protocols tls1.2 tls1.3
curves x25519
alpn http/1.1 h2
}
reverse_proxy 100.64.0.8:82
}
# 示例:ip+端口
0.0.0.0:882 {
reverse_proxy 100.64.0.8:82
}
# SSH端口转发
# iptables/Firewalld流量转发
05.更多配置
a.反向代理
example.com {
reverse_proxy localhost:8080
}
b.多个域名
example.com, www.example.com {
root * /var/www/example.com
file_server
}
c.自动HTTPS
example.com {
encode gzip
file_server
}
d.PHP支持
example.com {
root * /var/www/example.com
php_fastcgi localhost:9000
file_server
}
e.重定向
example.com {
redir https://www.example.com{uri}
}
f.错误页面
:80 {
handle_errors {
@404 {
expression {http.error.status_code} == 404
}
respond @404 "Page not found" 404
}
}
g.IP限制
:80 {
@allowedIPs {
remote_ip 192.168.1.0/24 10.0.0.0/8
}
respond @allowedIPs "Access granted"
respond "Access denied" 403
}
h.基本认证
example.com {
basicauth {
user JDJhJDEwJC4uLg== # bcrypt hash of password
}
file_server
}
-----------------------------------------------------------------------------------------------------
:80 {
basicauth /admin/* {
user JDJhJDE0JGJ1V3N4bTBUZy4kNnFqaGVzQmFZcERXbG5yQU93Y2dPQlZ6Q1dIY1dHRW0=
}
}
i.日志配置
example.com {
log {
output file /var/log/caddy/access.log
format json
}
file_server
}
4.8 nginx
00.报错
a.问题
nginx: [error] OpenEvent("Global\ngx_stop_10652") failed (2: The system cannot find the file specified)
Failed to stop Nginx! nginx报错
b.解决
nginx.conf中pid对应logs/nginx.pid
第1步:修改nginx.pid,14920为14985,或者删除nginx.pid(因为下次运行时会自动生成)
第2步:不要使用nginx.bat脚本,而是手动nginx.exe -s reload(重新加载配置)
第3步:不要使用nginx.bat脚本,而是手动nginx.exe -s stop(重新加载配置)
01.说明
a.目录
[root@localhost /]# tree /usr/local/nginx/ -L 2
/usr/local/nginx/
├── conf #存放一系列配置文件的目录
│ ├── fastcgi.conf #fastcgi程序相关配置文件
│ ├── fastcgi.conf.default #fastcgi程序相关配置文件备份
│ ├── fastcgi_params #fastcgi程序参数文件
│ ├── fastcgi_params.default #fastcgi程序参数文件备份
│ ├── koi-utf #编码映射文件
│ ├── koi-win #编码映射文件
│ ├── mime.types #媒体类型控制文件
│ ├── mime.types.default#媒体类型控制文件备份
│ ├── nginx.conf #主配置文件
│ ├── nginx.conf.default#主配置文件备份
│ ├── scgi_params #scgi程序相关配置文件
│ ├── scgi_params.default #scgi程序相关配置文件备份
│ ├── uwsgi_params #uwsgi程序相关配置文件
│ ├── uwsgi_params.default#uwsgi程序相关配置文件备份
│ └── win-utf #编码映射文件
├── html #存放网页文档
│ ├── 50x.html #错误页码显示网页文件
│ └── index.html #网页的首页文件
├── logs #存放nginx的日志文件
├── nginx-1.23.0.tar.gz # 我把压缩包下载到url/local/nginx/目录了,不用管这个
├── sbin #存放启动程序
│ ├── nginx #nginx启动程序
│ └── nginx.old
└── test # 我自己建的目录,不用管这个
├── abc
└── cba
b.命令
nginx --打开服务
nginx -v --查看版本
nginx -t --验证配置文件语法
nginx -p prefix --默认前缀(/usr/share/nginx/)
nginx -c filename --默认配置(/etc/nginx/nginx.conf)
nginx -s reopen --主进程发送信号(重启服务)
nginx -s reload --主进程发送信号(重载配置)
nginx -s stop --主进程发送信号(强制停止)
nginx -s quit --主进程发送信号(优雅退出)
ss -ntlp| grep -i nginx --查看软件是否正常运行
ps -ef | grep nginx --查看nginx进程
systemctl enable | start | stop | restart nginx --systemctl命令
tail -f /var/log/nginx/access.log --访问日志
tail -f /var/log/nginx/error.log --错误日志
c.防火墙
systemctl stop firewalld --关闭防火墙
systemctl disable firewalld --禁止开机自启
systemctl status firewalld --防火墙状态
systemctl start firewalld --开启防火墙
systemctl enable firewalld --开启开机自启
firewall-cmd --reload --重启防火墙
firewall-cmd --zone=public --add-port=3306/tcp --permanent --开放3306端口
firewall-cmd --zone=public --remove-port=3306/tcp --permanent --关闭3306端口
firewall-cmd --zone=public --list-ports --查看开放端口
firewall-cmd --state --查看防火墙状态
yum install net-tools -y && netstat -lnpt --查看当前所有tcp端口
netstat -lnpt | grep 3306 --查看所有3306端口使用情况
ps 3306 --查看进程的详细信息
02.安装
a.方式1
a.安装
yum install -y gcc pcre pcre-devel openssl openssl-devel
cd /usr/local && wget https://nginx.org/download/nginx-1.14.0.tar.gz && tar -zxvf nginx-1.14.0.tar.gz
cd /usr/local/nginx-1.14.0 && ./configure && make && make install
b.配置(负载均衡)
user root; --解决权限
worker_processes 1;
events {
worker_connections 1024;
}
http{
upstream myslayers.com {
server 192.168.2.129:8080 weight=1;
server 192.168.2.130:8081 weight=1;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://myslayers.com;
proxu_redirect default;
}
}
}
c.启动
/usr/local/nginx/sbin/nginx --启动Nginx
/usr/local/nginx/sbin/nginx -s stop --停止Nginx
/usr/local/nginx/sbin/nginx -s reload --重启Nginx
d.开机自启
vi /etc/rc.local --打开文件
/usr/local/nginx/sbin/nginx --追加
chmod 755 /etc/rc.local --设置文件权限
b.方式2
a.安装
yum install -y epel-release && yum install -y nginx
b.配置(HTTP转发)
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
listen [::]:80;
server_name myslayers.cn www.myslayers.cn;
return 301 https://$server_name;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name myslayers.cn www.myslayers.cn;
root /usr/share/nginx/html;
ssl_certificate "/etc/nginx/ssl/fullchain.cer";
ssl_certificate_key "/etc/nginx/ssl/myslayers.cn.key";
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://127.0.0.1:6666;
......
}
location /notifications/hub {
proxy_pass http://127.0.0.1:3012;
......
}
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
03.路由匹配
a.优先级
= 精确匹配
^~ 前缀匹配
~ 和 ~* 正则匹配
空 无修饰符的前缀匹配
/ 通用匹配
b.匹配规则
空 无修饰符的前缀匹配,匹配前缀是你配置的(比如说你配的是/aaa)的url
= 精确匹配
~ 正则表达式模式匹配,区分大小写
~* 正则表达式模式匹配,不区分大小写
^~ ~类型的前缀匹配,类似于无修饰符前缀匹配,不同的是,如果匹配到了,那么就停止后续匹配
/ 通用匹配,任何请求都会匹配到(只要你域名对,所有请求通吃!)
c.前缀匹配(无修饰符)
规则:匹配请求URI的前缀
行为:如果请求的URI以指定的前缀开头,则匹配成功
示例:location /images 将匹配 /images, /images/abc.jpg 等
注意:匹配多个前缀时,选择最长的匹配
配置示例:
location /images {
root /var/www;
}
说明:匹配所有以/images开头的请求URI,如/images/photo.jpg。如果有多个前缀匹配,选择最长的匹配
d.精确匹配(=)
规则:精确匹配请求的URI
行为:只有当请求的URI与指定的字符串完全相同时,才匹配成功
示例:location = /exact 仅匹配 /exact
优先级:精确匹配优先级最高
配置示例:
location = /exact {
return 200 "Exact match!";
}
说明:仅匹配请求URI为/exact的请求。精确匹配优先级最高,匹配成功后立即停止其他匹配
e.前缀匹配(^~)
规则:类似无修饰符的前缀匹配,但匹配成功后不再进行其他匹配
行为:如果匹配成功,则立即停止其他匹配
示例:location ^~ /static 将匹配 /static, /static/css/style.css 等
优先级:高于正则匹配和无修饰符的前缀匹配
配置示例:
location ^~ /static {
root /var/www/static;
}
说明:匹配所有以/static开头的请求URI,如/static/css/style.css。匹配成功后不再进行其他匹配
f.正则匹配(~ 区分大小写)
规则:使用正则表达式进行匹配,区分大小写
行为:根据正则表达式匹配请求的URI
示例:location ~ \.jpg$ 匹配所有以 .jpg 结尾的URI
注意:正则匹配按声明顺序进行,找到第一个匹配的即停止
配置示例:
location ~ \.jpg$ {
root /var/www/images;
}
说明:匹配所有以.jpg结尾的请求URI,如/images/photo.jpg。正则匹配区分大小写
g.正则匹配(~* 不区分大小写)
规则:使用正则表达式进行匹配,不区分大小写
行为:与~类似,但不区分大小写
示例:location ~* \.jpg$ 匹配 .jpg, .JPG, .Jpg 等
配置示例:
location ~* \.jpg$ {
root /var/www/images;
}
说明:匹配所有以.jpg、.JPG、.Jpg等结尾的请求URI。不区分大小写
h.通用匹配(/)
规则:匹配所有请求
行为:如果没有其他匹配规则匹配成功,则使用此规则
示例:location / 通常用于定义默认处理
注意:通常放在配置文件的最后
配置示例:
location / {
root /var/www/html;
index index.html;
}
说明:匹配所有请求URI。通常用于定义默认处理规则,当其他匹配规则均失效时使用
04.反向代理
a.定义
反向代理是一种服务器配置,客户端请求首先到达代理服务器
然后由代理服务器将请求转发到后端服务器进行处理,并将响应返回给客户端
b.原理
客户端请求:客户端向Nginx服务器发送请求
Nginx处理:Nginx根据配置文件中的规则决定将请求转发到哪个后端服务器
后端响应:后端服务器处理请求并将响应返回给Nginx
Nginx返回:Nginx将后端服务器的响应返回给客户端
c.常用API
proxy_pass:用于指定请求转发的目标地址
proxy_set_header:用于设置转发请求时的HTTP头信息
proxy_redirect:用于修改后端服务器返回的重定向响应
d.场景1:简单的HTTP反向代理
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend_server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
说明:将所有请求转发到http://backend_server,并设置一些常用的HTTP头
e.场景2:负载均衡
upstream backend {
server backend1.example.com;
server backend2.example.com;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
}
}
说明:使用upstream指令定义后端服务器组,实现简单的负载均衡
f.场景3:基于路径的反向代理
server {
listen 80;
server_name example.com;
location /app1/ {
proxy_pass http://app1_backend;
}
location /app2/ {
proxy_pass http://app2_backend;
}
}
说明:根据请求路径,将请求分别转发到不同的后端服务器
g.场景4:HTTPS反向代理
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://backend_server;
}
}
说明:配置HTTPS反向代理,需要提供SSL证书和密钥
05.负载均衡
a.定义
负载均衡是指将网络流量分配到多个服务器,以优化资源使用、最大化吞吐量、减少响应时间,并避免单个服务器过载
b.原理
请求分配:Nginx根据配置的负载均衡策略,将客户端请求分配到不同的后端服务器
策略选择:常见的负载均衡策略包括轮询(Round Robin)、最少连接(Least Connections)、IP哈希(IP Hash)等
健康检查:Nginx可以通过配置健康检查来确保请求只被分配到正常运行的服务器
c.常用API
upstream:定义后端服务器组
server:指定后端服务器地址及相关参数
proxy_pass:用于将请求转发到后端服务器组
health_check:用于配置健康检查(需要第三方模块支持)
d.使用步骤
安装Nginx并启动服务
编辑Nginx配置文件(通常是nginx.conf)
使用upstream指令定义后端服务器组
配置负载均衡策略
测试配置文件的正确性
重启Nginx服务以应用配置
e.场景1:轮询(Round Robin)负载均衡
upstream backend {
server backend1.example.com;
server backend2.example.com;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
}
}
说明:默认使用轮询策略,将请求依次分配到backend1和backend2
f.场景2:最少连接(Least Connections)负载均衡
upstream backend {
least_conn;
server backend1.example.com;
server backend2.example.com;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
}
}
说明:使用最少连接策略,将请求分配到当前连接数最少的服务器
g.场景3:IP哈希(IP Hash)负载均衡
upstream backend {
ip_hash;
server backend1.example.com;
server backend2.example.com;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
}
}
说明:使用IP哈希策略,将同一客户端IP的请求分配到同一服务器,适用于需要会话保持的场景
h.场景4:加权轮询(Weighted Round Robin)
upstream backend {
server backend1.example.com weight=3;
server backend2.example.com weight=1;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
}
}
说明:通过设置权重,backend1将接收更多请求(权重为3),而backend2接收较少请求(权重为1)
i.场景5:健康检查(需要第三方模块)
upstream backend {
server backend1.example.com;
server backend2.example.com;
health_check;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
}
}
说明:配置健康检查以确保请求只被分配到正常运行的服务器。需要安装第三方模块支持
06.动静分离
a.定义
动静分离是指将动态请求(如API请求)和静态资源请求(如HTML、CSS、JavaScript、图片等)分开处理
通常动态请求由应用服务器处理,而静态资源由Web服务器(如Nginx)直接提供
b.原理
动态请求:由后端应用服务器处理,如Node.js、Java、Python等
静态资源:由Web服务器直接提供,减少后端服务器的负载,提高响应速度
Nginx配置:通过Nginx配置,将不同类型的请求分发到相应的服务器
c.常用API
location:用于定义请求的匹配规则
proxy_pass:用于将动态请求转发到后端服务器
root或alias:用于指定静态资源的根目录
d.使用步骤
构建Vue项目,生成dist目录
安装并配置Nginx
配置Nginx以实现动静分离
测试配置文件的正确性
重启Nginx服务以应用配置
e.场景1:静态资源直接由Nginx提供
server {
listen 80;
server_name example.com;
# 静态资源
location / {
root /path/to/vue/dist;
try_files $uri $uri/ /index.html;
}
}
说明:将所有请求的静态资源(如HTML、CSS、JS)直接由Nginx提供,try_files用于处理SPA的路由问题
f.场景2:动态请求转发到后端服务器
server {
listen 80;
server_name api.example.com;
# 动态请求
location /api/ {
proxy_pass http://backend_server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
说明:将以/api/开头的请求转发到后端服务器进行处理
g.场景3:动静分离综合配置
server {
listen 80;
server_name example.com;
# 静态资源
location / {
root /path/to/vue/dist;
try_files $uri $uri/ /index.html;
}
# 动态请求
location /api/ {
proxy_pass http://backend_server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
说明:综合配置,将静态资源由Nginx提供,动态请求转发到后端服务器
07.跨域问题
a.定义
跨域资源共享(CORS)是一种机制,允许来自一个域的资源请求访问另一个域的资源
Nginx可以通过设置适当的HTTP头来允许跨域请求
b.原理
浏览器限制:浏览器的同源策略限制了跨域请求
CORS头:通过设置CORS相关的HTTP头,服务器可以指示浏览器允许跨域请求
Nginx配置:在Nginx中配置响应头,以允许特定的跨域请求
c.常用API
add_header:用于添加HTTP响应头
always:确保头信息在所有响应中都被添加
d.使用步骤
确定需要允许跨域的资源路径
编辑Nginx配置文件(通常是nginx.conf)
使用add_header指令配置CORS头
测试配置文件的正确性
重启Nginx服务以应用配置
e.场景1:允许所有来源的跨域请求
server {
listen 80;
server_name example.com;
location /api/ {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept' always;
if ($request_method = 'OPTIONS') {
return 204;
}
proxy_pass http://backend_server;
}
}
说明:允许所有来源的跨域请求,适用于开发环境。注意:在生产环境中,通常不建议使用*,而是指定具体的域
f.场景2:允许特定来源的跨域请求
server {
listen 80;
server_name example.com;
location /api/ {
add_header 'Access-Control-Allow-Origin' 'https://allowed-origin.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept' always;
if ($request_method = 'OPTIONS') {
return 204;
}
proxy_pass http://backend_server;
}
}
说明:仅允许来自https://allowed-origin.com的跨域请求,适用于生产环境
g.场景3:处理复杂请求的预检请求
server {
listen 80;
server_name example.com;
location /api/ {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept, Authorization' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
if ($request_method = 'OPTIONS') {
return 204;
}
proxy_pass http://backend_server;
}
}
说明:处理复杂请求的预检请求,支持更多的HTTP方法和头信息
08.缓存
a.定义
Nginx缓存是指在Nginx服务器上存储请求的响应,以便在后续请求中直接返回缓存的内容,而不必再次请求后端服务器
b.原理
请求缓存:当客户端请求资源时,Nginx首先检查缓存中是否存在该资源
缓存命中:如果缓存中存在且未过期,Nginx直接返回缓存内容
缓存未命中:如果缓存中不存在或已过期,Nginx请求后端服务器获取资源,并将响应存储在缓存中
c.常用API
proxy_cache_path:定义缓存存储路径和相关参数
proxy_cache:启用缓存并指定缓存区域
proxy_cache_key:定义缓存键
proxy_cache_valid:设置缓存的有效期
proxy_cache_bypass:条件性地绕过缓存
d.使用步骤
确定需要缓存的资源路径
编辑Nginx配置文件(通常是nginx.conf)
配置缓存路径和缓存规则
测试配置文件的正确性
重启Nginx服务以应用配置
e.场景1:缓存静态资源
http {
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;
server {
listen 80;
server_name example.com;
location /static/ {
proxy_cache my_cache;
proxy_pass http://backend_server;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
}
}
}
说明:缓存/static/路径下的静态资源,缓存有效期为10分钟
f.场景2:缓存动态内容
http {
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;
server {
listen 80;
server_name example.com;
location /api/ {
proxy_cache my_cache;
proxy_pass http://backend_server;
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_valid 200 1m;
add_header X-Cache-Status $upstream_cache_status;
}
}
}
说明:缓存/api/路径下的动态内容,缓存有效期为1分钟,并通过X-Cache-Status头返回缓存状态
g.场景3:条件性绕过缓存
http {
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;
server {
listen 80;
server_name example.com;
location / {
set $no_cache 0;
if ($request_method = POST) {
set $no_cache 1;
}
proxy_cache my_cache;
proxy_cache_bypass $no_cache;
proxy_pass http://backend_server;
proxy_cache_valid 200 10m;
}
}
}
说明:对于POST请求,绕过缓存,直接请求后端服务器
09.限流
a.定义
Nginx限流是通过限制每个客户端在一定时间内的请求数量来控制流量,从而防止恶意请求或突发流量对服务器造成影响
b.原理
请求计数:Nginx通过计数器记录每个客户端的请求数量
速率限制:根据配置的速率限制规则,判断请求是否超出限制
请求处理:如果请求未超出限制,则正常处理;如果超出限制,则返回错误或延迟处理
c.常用API
limit_req_zone:定义限流的共享内存区域和限流键
limit_req:在特定的location中启用限流
limit_req_log_level:设置限流日志级别
limit_req_status:设置限流时返回的HTTP状态码
d.使用步骤
确定需要限流的资源路径
编辑Nginx配置文件(通常是nginx.conf)
配置限流规则
测试配置文件的正确性
重启Nginx服务以应用配置
e.场景1:基于IP的请求限流
http {
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;
server {
listen 80;
server_name example.com;
location /api/ {
limit_req zone=mylimit burst=5 nodelay;
proxy_pass http://backend_server;
}
}
}
说明:为每个IP地址限制每秒1个请求,允许突发5个请求,超出限制的请求立即返回错误
f.场景2:基于用户ID的请求限流
http {
map $http_authorization $user_id {
default $http_authorization;
"" "";
}
limit_req_zone $user_id zone=userlimit:10m rate=2r/s;
server {
listen 80;
server_name example.com;
location /user/ {
limit_req zone=userlimit burst=10;
proxy_pass http://backend_server;
}
}
}
说明:根据用户ID限制每秒2个请求,允许突发10个请求
g.场景3:限流日志和状态码配置
http {
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;
server {
listen 80;
server_name example.com;
location / {
limit_req zone=mylimit burst=5;
limit_req_log_level warn;
limit_req_status 429;
proxy_pass http://backend_server;
}
}
}
说明:配置限流日志级别为warn,超出限制时返回HTTP状态码429(Too Many Requests)
10.压缩
a.定义
Nginx压缩是指在服务器端对响应内容进行压缩处理,以减少数据传输量,提高客户端的加载速度
b.原理
压缩算法:Nginx使用Gzip或Brotli等压缩算法对响应内容进行压缩
客户端支持:客户端通过HTTP头(如Accept-Encoding)告知服务器支持的压缩格式
压缩响应:Nginx根据客户端支持的压缩格式,对响应内容进行压缩并返回给客户端
c.常用API
gzip:启用或禁用Gzip压缩
gzip_types:指定需要压缩的MIME类型
gzip_comp_level:设置Gzip压缩级别
gzip_min_length:设置启用压缩的最小响应长度
gzip_vary:在响应中添加Vary: Accept-Encoding头
d.使用步骤
确定需要压缩的资源类型
编辑Nginx配置文件(通常是nginx.conf)
配置压缩规则
测试配置文件的正确性
重启Nginx服务以应用配置
e.场景1:启用Gzip压缩
http {
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_comp_level 5;
gzip_min_length 256;
gzip_vary on;
server {
listen 80;
server_name example.com;
location / {
root /var/www/html;
}
}
}
说明:启用Gzip压缩,指定需要压缩的MIME类型,设置压缩级别为5,最小压缩长度为256字节,并在响应中添加Vary: Accept-Encoding头
f.场景2:仅压缩特定类型的文件
http {
gzip on;
gzip_types text/css application/javascript;
gzip_comp_level 6;
server {
listen 80;
server_name example.com;
location / {
root /var/www/html;
}
}
}
说明:仅对CSS和JavaScript文件启用Gzip压缩,设置压缩级别为6
g.场景3:禁用特定路径的压缩
http {
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
server {
listen 80;
server_name example.com;
location / {
root /var/www/html;
}
location /no-compress/ {
gzip off;
}
}
}
说明:全局启用Gzip压缩,但禁用/no-compress/路径下的压缩
11.黑白名单
a.定义
白名单:允许访问的IP地址列表,只有在白名单中的IP地址才能访问服务器资源
黑名单:拒绝访问的IP地址列表,黑名单中的IP地址将被禁止访问服务器资源
b.原理
请求过滤:Nginx根据配置的黑白名单规则,检查客户端的IP地址
访问控制:根据IP地址是否在黑名单或白名单中,决定是否允许访问
优先级:通常白名单优先于黑名单,即如果一个IP在白名单中,即使它也在黑名单中,仍然允许访问
c.常用API
allow:允许指定的IP地址或IP地址范围访问
deny:拒绝指定的IP地址或IP地址范围访问
d.使用步骤
确定需要控制访问的资源路径
编辑Nginx配置文件(通常是nginx.conf)
配置黑白名单规则
测试配置文件的正确性
重启Nginx服务以应用配置
e.场景1:配置白名单
server {
listen 80;
server_name example.com;
location / {
allow 192.168.1.0/24; # 允许192.168.1.0到192.168.1.255的IP访问
allow 10.0.0.1; # 允许特定IP访问
deny all; # 拒绝其他所有IP访问
root /var/www/html;
}
}
说明:仅允许来自192.168.1.0/24网段和10.0.0.1的IP访问,其他IP将被拒绝
f.场景2:配置黑名单
server {
listen 80;
server_name example.com;
location / {
deny 192.168.1.100; # 拒绝特定IP访问
deny 203.0.113.0/24; # 拒绝整个网段访问
allow all; # 允许其他所有IP访问
root /var/www/html;
}
}
说明:拒绝来自192.168.1.100和203.0.113.0/24网段的IP访问,其他IP将被允许
g.场景3:结合黑白名单
server {
listen 80;
server_name example.com;
location / {
allow 192.168.1.0/24; # 允许特定网段访问
deny 192.168.1.100; # 拒绝特定IP访问,即使在允许的网段中
allow 10.0.0.1; # 允许特定IP访问
deny all; # 拒绝其他所有IP访问
root /var/www/html;
}
}
说明:结合使用黑白名单,允许特定网段和IP访问,但拒绝特定IP,即使它在允许的网段中
12.重试策略
a.定义
重试策略是指在请求后端服务器失败时,Nginx自动重新发送请求到同一服务器或其他可用服务器的机制
b.原理
请求失败检测:Nginx检测到请求后端服务器失败(如连接超时、服务器不可达等)
重试机制:根据配置的重试策略,Nginx重新尝试请求
负载均衡结合:在负载均衡配置中,重试机制可以结合使用,将请求发送到其他可用的后端服务器
c.常用API
proxy_next_upstream:定义哪些错误情况下进行重试
proxy_next_upstream_tries:设置最大重试次数
proxy_next_upstream_timeout:设置重试的超时时间
d.使用步骤
确定需要重试的请求类型和条件
编辑Nginx配置文件(通常是nginx.conf)
配置重试策略
测试配置文件的正确性
重启Nginx服务以应用配置
e.场景1:基本重试策略
http {
upstream backend {
server backend1.example.com;
server backend2.example.com;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
}
}
}
说明:当请求后端服务器返回错误(如500、502、503、504)或超时时,Nginx将重试请求
f.场景2:限制重试次数
http {
upstream backend {
server backend1.example.com;
server backend2.example.com;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
proxy_next_upstream_tries 3;
}
}
}
说明:在指定错误情况下,最多重试3次
g.场景3:设置重试超时时间
http {
upstream backend {
server backend1.example.com;
server backend2.example.com;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
proxy_next_upstream_timeout 10s;
}
}
}
说明:在指定错误情况下,重试的总超时时间为10秒
13.https配置
a.定义
HTTPS(HyperText Transfer Protocol Secure)是HTTP的安全版本
通过SSL/TLS协议加密数据传输,提供数据的机密性、完整性和身份验证
b.原理
SSL/TLS握手:客户端和服务器通过SSL/TLS协议进行握手,协商加密算法和密钥
数据加密:使用协商的加密算法和密钥,对传输的数据进行加密
身份验证:通过数字证书验证服务器的身份,确保客户端连接到正确的服务器
c.常用API
ssl:启用SSL/TLS
ssl_certificate:指定SSL证书文件路径
ssl_certificate_key:指定SSL证书密钥文件路径
ssl_protocols:指定支持的SSL/TLS协议版本
ssl_ciphers:指定支持的加密套件
d.使用步骤
获取SSL证书和密钥(可以通过CA机构申请或使用自签名证书)
编辑Nginx配置文件(通常是nginx.conf)
配置HTTPS相关指令
测试配置文件的正确性
重启Nginx服务以应用配置
e.场景1:基本HTTPS配置
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/cert.key;
location / {
root /var/www/html;
index index.html;
}
}
说明:启用HTTPS,指定SSL证书和密钥文件路径
f.场景2:同时支持HTTP和HTTPS
server {
listen 80;
server_name example.com;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/cert.key;
location / {
root /var/www/html;
index index.html;
}
}
说明:HTTP请求自动重定向到HTTPS,确保所有流量通过HTTPS传输
g.场景3:配置SSL协议和加密套件
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/cert.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
root /var/www/html;
index index.html;
}
}
说明:仅支持TLSv1.2和TLSv1.3协议,使用高强度加密套件
h.场景4:自定义示例
server {
listen 80;
server_name yourdomain.com;
# 强制重定向到 HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl; # 监听 HTTPS
server_name yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem; # SSL 证书路径
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem; # SSL 密钥路径
location / {
proxy_pass http://192.168.1.10:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
14.url转发
a.端口转发配置
a.监听8881端口并转发到10.0.0.1:8080
server {
listen 8881;
server_name 负载ip;
root html;
index index.html index.htm;
location / {
proxy_pass http://10.0.0.1:8080/;
proxy_redirect off;
}
}
-------------------------------------------------------------------------------------------------
listen 8881;:Nginx监听8881端口的所有请求
proxy_pass http://10.0.0.1:8080/;:将所有请求转发到10.0.0.1:8080
proxy_redirect off;:关闭自动重定向
b.监听8882端口并转发到10.0.0.2:8080
server {
listen 8882;
server_name 负载ip;
root html;
index index.html index.htm;
location / {
proxy_pass http://10.0.0.2:8080/;
proxy_redirect off;
}
}
-------------------------------------------------------------------------------------------------
listen 8882;:Nginx监听8882端口的所有请求
proxy_pass http://10.0.0.2:8080/;:将所有请求转发到10.0.0.2:80800
b.路径转发配置
a.路径为/test/addblack/1的请求转发到10.0.0.1:8080/test/addblack
server {
listen 8832;
server_name 负载ip;
root html;
index index.html index.htm;
location /test/addblack/1 {
proxy_pass http://10.0.0.1:8080/test/addblack;
proxy_redirect off;
}
}
-------------------------------------------------------------------------------------------------
location /test/addblack/1:匹配路径为/test/addblack/1的请求
proxy_pass http://10.0.0.1:8080/test/addblack;:将请求转发到10.0.0.1:8080/test/addblack
b.路径为/test/addblack/2的请求转发到10.0.0.2:8080/test/addblack
server {
listen 8832;
server_name 负载ip;
root html;
index index.html index.htm;
location /test/addblack/2 {
proxy_pass http://10.0.0.2:8080/test/addblack;
proxy_redirect off;
}
}
-------------------------------------------------------------------------------------------------
location /test/addblack/2:匹配路径为/test/addblack/2的请求
proxy_pass http://10.0.0.2:8080/test/addblack;:将请求转发到10.0.0.2:8080/test/addblack
99.完整示例
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# log_format debug '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#
log_format debug ' $remote_user [$time_local] $http_x_Forwarded_for $remote_addr $request '
'$http_x_forwarded_for '
'$upstream_addr '
'ups_resp_time: $upstream_response_time '
'request_time: $request_time';
access_log /var/log/nginx/access.log debug;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
upstream mybackendserver {
server 172.30.128.64:8081 fail_timeout=60s max_fails=3; # 60秒内 如果请求某一个应用失败3次,则认为该应用宕机 时间到后再有请求进来继续尝试连接宕机应用且仅尝试 1 次,如果还是失败,则继续等待 60 秒...以此循环,直到恢复
server 172.30.128.64:8082;
server 172.30.128.64:8083 backup; # 设置8083位备机
}
# 开启/关闭 压缩机制
gzip on;
# 根据文件类型选择 是否开启压缩机制
gzip_types text/plain application/javascript text/css application/xml text/javascript image/jpeg image/jpg image/gif image/png application/json;
# 设置压缩级别,越高资源消耗越大越耗时,但压缩效果越好
gzip_comp_level 9;
# 设置是否携带Vary:Accept-Encoding 的响应头
gzip_vary on;
# 处理压缩请求的 缓冲区数量和大小
gzip_buffers 32 64k;
# 对于不支持压缩功能的客户端请求 不开启压缩机制
gzip_disable "MSIE [1-6]\."; # 比如低版本的IE浏览器不支持压缩
# 设置压缩功能所支持的HTTP最低版本
gzip_http_version 1.1;
# 设置触发压缩的最小阈值
gzip_min_length 2k;
# off/any/expired/no-cache/no-store/private/no_last_modified/no_etag/auth 根据不同配置对后端服务器的响应结果进行压缩
gzip_proxied any;
# 指定缓存存放目录为/usr/local/nginx/test/nginx_cache_storage,并设置缓存名称为mycache,大小为64m, 1天未被访问过的缓存将自动清除,磁盘中缓存的最大容量为1gb
proxy_cache_path /usr/local/nginx/test/nginx_cache_storage levels=1:2 keys_zone=mycache:64m inactive=1d max_size=1g;
# 对请求速率限流
#limit_req_zone $binary_remote_addr zone=myRateLimit:10m rate=5r/s;
# 对请求连接数限流
limit_conn_zone $binary_remote_addr zone=myConnLimit:10m;
# --------------------HTTP 演示 配置---------------------
server {
listen 80 default;
charset utf-8;
server_name www.hzznb-xzll.xyz hzznb-xzll.xyz;
#location /static/ {
# root /usr/local/nginx/test; # /usr/local/nginx/test/static/xxx.jpg
#}
location /static { # 注意一般 alias的 url都不带后边的/
alias /usr/local/nginx/test/; # 使用alias时 这里的目录最后边一定要加/ 否则就404
}
# 测试autoindex效果
location /book/ {
root /usr/local/nginx/test;
autoindex on; # 打开 autoindex,,可选参数有 on | off
autoindex_format html; # 以html的方式进行格式化,可选参数有 html | json | xml
autoindex_exact_size on; # 修改为off,会以KB、MB、GB显示文件大小,默认为on以bytes显示出⽂件的确切⼤⼩
autoindex_localtime off; # 显示⽂件时间 GMT格式
}
# 临时重定向
location /temp_redir {
rewrite ^/(.*) https://www.baidu.com redirect;
}
# 永久重定向
location /forever_redir {
rewrite ^/(.*) https://www.baidu.com permanent;
}
# rewrite last规则测试
location /1 {
rewrite /1/(.*) /2/$1 last;
}
location /2 {
rewrite /2/(.*) /3/$1 last;
}
location /3 {
alias '/usr/local/nginx/test/static/';
index location_last_test.html;
}
}
# --------------------HTTP配置---------------------
server {
listen 80;
charset utf-8;
#server_name www.xxxadminsystem.com;
server_name www.hzznbc-xzll.xyz hzznbc-xzll.xyz;
# 重定向,会显示跳转的地址server_name,如果访问的地址没有匹配会默认使用第一个,即www.likeong.icu
return 301 https://$server_name$request_uri;
# # 指定 username 参数中只要有字母 就不走nginx缓存
# if ($arg_username ~ [a-z]) {
# set $cache_name "no cache";
# }
# # 前端页面资源
# location /page {
# alias '/usr/local/nginx/test/static/';
# index index_page.html;
# allow all;
# }
# # 后端服务
# location /interface {
# proxy_pass http://mybackendserver/;
# # 使用名为 mycache 的缓存空间
# proxy_cache mycache;
# # 对于200 206 状态码的数据缓存2分钟
# proxy_cache_valid 200 206 1m;
# # 定义生成缓存键的规则(请求的url+参数作为缓存key)
# proxy_cache_key $host$uri$is_args$args;
# # 资源至少被重复访问2次后再加入缓存
# proxy_cache_min_uses 3;
# # 出现重复请求时,只让其中一个去后端读数据,其他的从缓存中读取
# proxy_cache_lock on;
# # 上面的锁 超时时间为4s,超过4s未获取数据,其他请求直接去后端
# proxy_cache_lock_timeout 4s;
# # 对于请求参数中有字母的 不走nginx缓存
# proxy_no_cache $cache_name; # 判断该变量是否有值,如果有值则不进行缓存,没有值则进行缓存
# # 在响应头中添加一个缓存是否命中的状态(便于调试)
# add_header Cache-status $upstream_cache_status;
# limit_conn myConnLimit 12;
# limit_req zone=myRateLimit burst=5 nodelay;
# limit_req_status 520;
# limit_req_log_level info;
#}
}
# --------------------HTTPS 配置---------------------
server {
#SSL 默认访问端口号为 443
listen 443 ssl;
#填写绑定证书的域名
server_name www.hzznb-xzll.xyz hzznb-xzll.xyz;
#请填写证书文件的相对路径或绝对路径
ssl_certificate /usr/local/nginx/certificate/hzznb-xzll.xyz_bundle.crt;
#请填写私钥文件的相对路径或绝对路径
ssl_certificate_key /usr/local/nginx/certificate/hzznb-xzll.xyz.key;
#停止通信时,加密会话的有效期,在该时间段内不需要重新交换密钥
ssl_session_timeout 5m;
#服务器支持的TLS版本
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
#请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
#开启由服务器决定采用的密码套件
ssl_prefer_server_ciphers on;
# 指定 username 参数中只要有字母 就不走nginx缓存
if ($arg_username ~ [a-z]) {
set $cache_name "no cache";
}
# 前端页面资源
location /page {
alias '/usr/local/nginx/test/static/';
index index_page.html;
allow all;
}
# 后端服务
location /interface {
proxy_pass http://mybackendserver/;
# 指定哪些错误状态才执行 重试
proxy_next_upstream error timeout http_500 http_502 http_503 http_504 http_404;
# 使用名为 mycache 的缓存空间
proxy_cache mycache;
# 对于200 206 状态码的数据缓存2分钟
proxy_cache_valid 200 206 1m;
# 定义生成缓存键的规则(请求的url+参数作为缓存key)
proxy_cache_key $host$uri$is_args$args;
# 资源至少被重复访问2次后再加入缓存
proxy_cache_min_uses 3;
# 出现重复请求时,只让其中一个去后端读数据,其他的从缓存中读取
proxy_cache_lock on;
# 上面的锁 超时时间为4s,超过4s未获取数据,其他请求直接去后端
proxy_cache_lock_timeout 4s;
# 对于请求参数中有字母的 不走nginx缓存
proxy_no_cache $cache_name; # 判断该变量是否有值,如果有值则不进行缓存,没有值则进行缓存
# 在响应头中添加一个缓存是否命中的状态(便于调试)
add_header Cache-status $upstream_cache_status;
limit_conn myConnLimit 12;
# limit_req zone=myRateLimit burst=5 nodelay;
# limit_req_status 520;
# limit_req_log_level info;
}
# 后端服务
location /interface2 {
proxy_pass http://mybackendserver;
# 使用名为 mycache 的缓存空间
proxy_cache mycache;
# 对于200 206 状态码的数据缓存2分钟
proxy_cache_valid 200 206 1m;
# 定义生成缓存键的规则(请求的url+参数作为缓存key)
proxy_cache_key $host$uri$is_args$args;
# 资源至少被重复访问2次后再加入缓存
proxy_cache_min_uses 3;
# 出现重复请求时,只让其中一个去后端读数据,其他的从缓存中读取
proxy_cache_lock on;
# 上面的锁 超时时间为4s,超过4s未获取数据,其他请求直接去后端
proxy_cache_lock_timeout 4s;
# 对于请求参数中有字母的 不走nginx缓存
proxy_no_cache $cache_name; # 判断该变量是否有值,如果有值则不进行缓存,没有值则进行缓存
# 在响应头中添加一个缓存是否命中的状态(便于调试)
add_header Cache-status $upstream_cache_status;
limit_conn myConnLimit 12;
# limit_req zone=myRateLimit burst=5 nodelay;
# limit_req_status 520;
# limit_req_log_level info;
}
}
# include /etc/nginx/conf.d/*.conf;
}
4.9 ngrok
01.常用命令
a.分类1
ngrok http [port] --启动 HTTP 隧道
ngrok tcp [port] --启动 TCP 隧道
ngrok tls [port] --启动一个 TLS 隧道,用于 HTTPS 流量
b.分类2
ngrok config add-authtoken [token] --配置身份验证令牌
ngrok status --查看当前隧道状态
ngrok start [tunnel-name] --根据配置文件启动预定义的隧道
ngrok config list --列出所有在配置文件中定义的隧道
02.常用选项
a.分类1
ngrok http -config=ngrok.yml 8080 --指定配置文件路径
ngrok http -region=us 8080 --指定隧道所在的区域(如 us、eu、ap、au、sa、jp、in)
ngrok http -subdomain=myapp 8080 --指定自定义子域名(需要付费账户)
ngrok http -hostname=myapp.example.com 8080 --指定自定义域名(需要付费账户)
b.分类2
ngrok http -inspect=false 8080 --启用或禁用请求检查界面
ngrok http -log=ngrok.log 8080 --指定日志文件路径
ngrok http -log-level=info 8080 --设置日志级别(debug、info、warn、error)
4.10 firewalld
01.Firewalld流量转发
a.如果firewall-cmd --state输出不是running,请安装firewalld并开启
yum install -y firewalld
systemctl enable firewalld
systemctl start firewalld
b.配置流量转发,国内VPS端口8080 -> 国外VPS端口443
echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
sysctl -p
firewall-cmd --permanent --add-masquerade
# 8080可以改成其他端口
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --permanent --add-port=8080/udp
# 8080和上面保持一致,国外ip改成你国外vps的ip,443改成国外ss/ssr/v2ray等软件的端口
firewall-cmd --permanent --add-forward-port=port=8080:proto=tcp:toaddr=国外ip:toport=443
firewall-cmd --permanent --add-forward-port=port=8080:proto=udp:toaddr=国外ip:toport=443
firewall-cmd --reload
02.Nginx流量转发
a.安装
yum install -y epel-release && yum install -y nginx
b.配置
vi /etc/nginx/nginx.conf --打开配置文件
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
# 增加的配置
stream {
server {
listen 端口号; # 1-65535的任意一个数字,无需与境外服务器的端口号相同
proxy_pass 境外ip:境外端口号; # 用境外ip和端口号替换
}
}
# 转发配置结束
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
...
}
nginx -t --检查配置有没有错误
c.启动
systemctl enable nginx && systemctl start nginx --开机启动并启动
ss -ntlp| grep -i nginx --查看软件是否正常运行
sed -i 's/SELINUX=enforcing/SELINUX=permissive/g' /etc/selinux/config && setenforce 0
d.防火墙
firewall-cmd --permanent --add-port=nginx中配置的端口号/tcp
fireawll-cmd --reload
04.国外服务器:除SSH的22端口、正常服务的443、80端口,其他端口只允许国内服务器连接
a.检测防火墙
firewall-cmd --state
b.启动防火墙
systemctl enable firewalld && systemctl start firewalld
c.删除之前放行过的ss/ssr/v2ray等端口
firewall-cmd --permanent --remove-port=端口/tcp
d.仅允许国内ip连接该服务器
firewall-cmd --permanent --add-source=国内ip/32
fireawll-cmd --reload
05.注意
a.Firewalld流量转发、Nginx流量转发
配置客户端时,IP和端口填国内服务器,其他信息(密码、加密方式等)和国外服务器保持一致
b.NAT流量转发(端口映射)
配置客户端时,IP和端口填NAT映射的公网IP和端口号
5 git
5.1 常见命令
01.常用信息
a.使用1
https://github.com/halavah.gpg --查看GPG keys
https://github.com/halavah.keys --查看SSH keys
-----------------------------------------------------------------------------------------------------
https://gitmcp.io/halavah/vilgoboot-his
https://github.dev/halavah/vilgoboot-his
https://github1s.com/halavah/vilgoboot-his
https://kkgithub.com/halavah/vilgoboot-his
https://sourcegraph.com/users/halavah/settings/repositories/manage?filter=halavah%2Fvilgoboot-his
b.使用2
build:更新版本
docs:更新ui文档
fix:美化文档格式
feat:添加路由/状态模版
-----------------------------------------------------------------------------------------------------
git tag v1.0 && git push origin v1.0 --标签
git add . && git commit -m 'v1.0' && git push --提交
-----------------------------------------------------------------------------------------------------
文件:忽略 -> 脱离忽略规则、检查文件是否被管理 --管理历史提交点
文件:回滚 -> 3种情况 --管理历史提交点
rebase:变基 -> 删除drop、修改edit、合并squash --管理历史提交点
c.使用3
git status --查看状态
git branch -av --查看分支
-----------------------------------------------------------------------------------------------------
git log --oneline --查看提交日志
git log --oneline origin/master..master --查看本地相对于远程的提交记录
-----------------------------------------------------------------------------------------------------
git commit --amend --修改最近一次的commit
git reset --soft HEAD"^" --返回上一个commit状态,并保留当前修改的文件
-----------------------------------------------------------------------------------------------------
git pull origin master --更新内容
git push --force origin master --忽略远程版本,强制提交
d.forgit
ga --git add 选择器
glo --git log 查看器
gi --.gitignore 生成器
gd --git diff 查看器
gcb --git checkout <branch>
gs --git stash
-----------------------------------------------------------------------------------------------------
grh --reset HEAD
gcf --checkout file
gbd --branch delete
gct --checkout tag
gco --checkout commit
grc --revert commit
gclean --clean
gsp --stash push
gcp --cherry-pick
grb --rebase
gbl --blame
gfu --fixup
e.常用命令
git config --配置
git init --初始化
git clone --将存储库克隆到新目录中
git remote --管理远程主机
git fetch --从另一个存储库下载对象和引用
-----------------------------------------------------------------------------------------------------
git add --将文件内容添加到暂存区
git commit --提交
git reset --将当前HEAD复位到指定状态,用于撤消之前的一些操作
git rm --从工作区和暂存区中删除文件
git mv --移动或重命名文件,目录或符号链接
-----------------------------------------------------------------------------------------------------
git diff --显示提交和工作树等之间的更改
git status --查看状态
git branch --列出,创建或删除分支
git checkout --切换分支或恢复工作树文件
git merge --将两个或两个以上的开发历史加入(合并)一起
git mergetool --运行合并冲突解决工具来解决合并冲突
git stash --将更改储藏在脏工作目录中
git rebase --合并分支
git cherry-pick --摘樱桃模式
-----------------------------------------------------------------------------------------------------
git pull --从另一个存储库或本地分支获取并集成(整合)
git push --将本地分支的更新,推送到远程主机
git submodule --初始化,更新或检查子模块
-----------------------------------------------------------------------------------------------------
git log --显示提交日志信息
git reflog --GIT操作历史记录
git shortlog --汇总git日志输出
-----------------------------------------------------------------------------------------------------
git tag --创建,列出,删除或验证使用GPG签名的标签对象
git show --用于显示各种类型的对象
git describe --显示离当前提交最近的标签
f.常用分支名
master
master分支代码只能被release分支分支合并,且合并动作只能由特定管理员进行此操作
master分支是保护分支,开发人员不可直接push到远程仓库的master分支
-----------------------------------------------------------------------------------------------------
release
命名规则:release/*,“*”一般是标识项目、第几期、日期等
该分支是保护分支,开发人员不可直接push,一般选定某个人进行整体的把控和push
该分支是生产投产分支
该分支每次基于master分支拉取
-------------------------------------------------------------------------------------------------
dev
这个是作为开发分支,大家都可以基于此分支进行开发
这个分支的代码要求是本地启动没问题,不影响其他人的代码
-------------------------------------------------------------------------------------------------
hotfix
这个分支一般是作为紧急修复分支,当前release发布后发现问题后需要该分支
该分支一般从当前release分支拉取
该分支开发完后需要合并到release分支以及dev分支
-------------------------------------------------------------------------------------------------
feat
该分支一般是一个长期的功能需要持续开发或调整使用
该分支基于release创建或者基于稳定的dev创建也可以
一般开发完后需要合并到dev分支
02.常见信息
a.git config 配置
git config --global user.name 'hello' --设置全局用户名hello
git config --global user.email '[email protected]' --设置全局邮箱[email protected]
git config user.name --查看配置中的配置项(用户名)
git config user.email --查看配置中的配置项(邮箱)
git config --global core.editor emacs --配置默认的文本编辑器
git config --global merge.tool vimdiff --配置比较工具用来解决冲突
git config --list --列出Git可以在该处找到的所有的设置
git config -–add site.name hello --默认是添加在 local配置中的新配置项
git config [--local | --global | --system] –unset site.name --删除配置项中的site.name配置值
git config --global alias.别名 命令 --给命令设置别名,例如给git status 设置别名为s,git config --global alias.s status
b.git help 显示有关Git的帮助信息
git --help --在git窗口查看命令
git help config/git config --help/git --help config --查看git config如何使用
git help git/git --help git --显示git手册页
git help help/git --help help --查看help命令如何使用
c.git init 初始化
git clone https://[email protected]/jh4j/jh4j-ui.git --J057983指定用户名
git init --创建一个空的Git仓库或重新初始化一个现有仓库
--------------------------------------------------------------------
echo "# vilgoboot" >> README.md
git init
git add .
git commit -m "first commit"
git branch -M master
git remote add origin https://github.com/halavah/vilgoboot.git
git push -u origin master
--------------------------------------------------------------------
git remote add origin https://github.com/halavah/vilgoboot.git
git branch -M master
git push -u origin master --u代表跟踪master分支,默认git push就是master
git push -f origin master --f代表强制推送到master分支
--------------------------------------------------------3------------
git init && git add . && git commit -m "first commit" && git branch -M master
git remote add origin [email protected]:halavah/vilgob.git && git push -u origin master
d.git add 将文件内容添加到暂存区
git add <path> --把path中的文件或者目录添加到暂存区
git add ./git add */git add -A --把所有的修改都添加到暂存区中
git add -u <path>
git add -i
e.git clone 将存储库克隆到新目录中
git clone <版本库的网址>
git clone <版本库的网址> <本地目录名>
git clone --bare
git clone -l
git clone -s
git clone -n
git clone --reference
git clone -o jQuery https://github.com/jquery/jquery.git --克隆远程主机到本地,并将远程主机重命名为jQuery,默认是origin
git clone -o jQuery https://github.com/jquery/jquery.git --克隆远程主机到本地,并将远程主机重命名为jQuery,默认是origin
git clone -b dev https://github.com/jquery/jquery.git --指定分支为dev,-o jQuery 选项将远程仓库命名为jQuery,而不是默认的origin
git clone --recursive [email protected]:rbind/yihui.git --克隆库的时候要初始化子模块,加 --recursive 参数
f.git status 查看状态
git status 显示工作目录和暂存区的状态
git status -uno
g.git diff 显示提交和工作树等之间的更改
git diff --查看working tree与暂存区文件的差异
git diff <file> --比较某文件和暂存区文件差异
git diff --cached/git diff --staged/ --比较暂存区和上次commit的HEAD的差异
git diff HEAD --显示工作版本(Working tree)和上次commit的HEAD的差异
git diff HEAD^ HEAD --比较上次提交和上上次提交的差异
git diff HEAD -- ./lib --显示当前目录下的lib目录和上次提交之间的差别(更准确的说是在当前分支下)
git diff commitID1 commitID2 --比较两个历史版本之间的差异
git diff topic --比较当前分支与topic分支的差别
git diff topic dev /git diff topic..dev --在dev和topic两个分支之间比较变更
git diff --stat --仅仅比较统计信息(简单结果)
h.git commit 提交
git commit --将暂存区中的文件、描述、更改用户、日志消息一起提交到存储库
git commit -a/git commit --all --将所有已跟踪文件中的执行修改或删除操作的文件都提交到本地仓库,即使它们没有经过git add添加到暂存区,新加的文件(即没有被git系统管理的文件)是不能被提交到本地仓库的。(建议一般不要使用-a参数)
git commit -m 'message' /git commit --message 'message' --简要说明提交的信息
git commit --amend --追加提交,它可以在不增加一个新的commit-id的情况下将新修改的代码追加到前一次的commit-id中
git commit -v --查看要提交的内容与版本库中的比较,然后进行提交
03.常见信息
a.git reset 将当前HEAD复位到指定状态,用于撤消之前的一些操作
git reset --将暂存区里的所有文件恢复到工作树中
git reset <path> --将暂存区里的指定文件恢复到工作树中
git reset -- README.md --将暂存区的单独一个文件恢复到工作树中。
git reset --soft HEAD^ --commit之后取消本地提交,回到没有提交之前的暂存区中。
git reset --hard commit_id
git reset --hard HEAD~3 --永久删除最后几个提交
git reset --hard ORIG_HEAD --执行git pull完后,发现这次拉取下来的修改不满意,想要回滚到git pull之前的状态,并清空本地没有加入暂存区的内容。
git reset --merge ORIG_HEAD --执行git pull完后,发现这次拉取下来的修改不满意,想要回滚到git pull之前的状态,可以避免在回滚时清除工作区,保留暂存区和工作树的内容。
git reset --soft
git reset --keep start
b.git rm 从工作区和暂存区中删除文件
git rm test.txt --删除test.txt文件,并把它从git仓库管理系统中删除,需要执行git commit才能真正提交到git 仓库
git rm -r mydir --删除mydir文件夹,并把它从git的仓库管理系统中删除
git rm --cache test.txt --从暂存区中移除test.txt文件,对文件本身不进行改变。
git rm -f --取消rm操作
c.git mv 移动或重命名文件,目录或符号链接
git mv <source> <destination> --例如:git mv test.txt mydir 将test.txt文件移动到mydir目录下
git mv test.txt test1.txt --将test.txt文件重命名为test1.txt
-----------------------------------------------------------------------------------------------------
此操作必须要在暂存区或者文件commit之后才能进行rename,此时不需要再git add, 否则会报错
fatal: not under version control, source=home/test.txt, destination=home/test1.txt )
git mv -f
git mv -k
d.git branch 列出,创建或删除分支
git branch --查看本地分支和当前分支
git branch test --新建test分支(还在当前分支中)
git branch -a --查看本地分支和远程分支
git branch -r --查看远程分支
git branch -m test test1 --修改本地分支名称
git branch -d test --删除本地分支
git branch -D test --强制删除本地test分支,有时候-d的时候回提示没有完全合并
git branch --set-upstream dev origin/test --将本地dev分支与远程主机的test分支建立追踪关系
-----------------------------------------------------------------------------------------------------
Git会自动在本地分支与远程分支之间,建立一种追踪关系(tracking)。
比如,在git clone的时候,所有本地分支默认与远程主机的同名分支,建立追踪关系,
也就是说,本地的master分支自动"追踪"origin/master分支。
e.git checkout 切换分支或恢复工作树文件
git checkout dev --切换新分支(没有commit的文件会跟随新分支切换)
git checkout -b hello --创建并切换到新分支hello
git checkout -B hello --强制创建并切换到新分支,如果当前目录有这个分支,进行覆盖操作
git checkout [commitID] --切换到某一个提交版本的分支
git checkout --detach hello --切换到hello分支的最后一次提交的commitID版本的分支
git checkout --orphan <branch>
git checkout --merge <branch>
git checkout -p <branch>
git checkout <tagName> --切换到tagName标签的分支中
f.git merge 将两个或两个以上的开发历史加入(合并)一起
git merge hello --合并hello分支到当前分支
Fast-forward信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。这种合并看不出来曾经做过合并。
-----------------------------------------------------------------------------------------------------
git merge hello1 hello2 --合并hello1和hello2分支的东西到当前分支,多个分支合并。
git merge --abort --放弃合并
git merge --continue --合并继续,这个命令后是修改合并生成的commit信息
git merge -s ours obsolete
git merge --no-ff -m "merge with no-ff" dev --普通模式合并,合并后历史上有分支,能看出来曾经做过合并,表示禁用Fast forward,准备合并dev分支,因为要创建一个新的commit,所以加上-m参数,把commit的表述写进去
g.git mergetool 运行合并冲突解决工具来解决合并冲突
git mergetool --git设置 mergetool 可视化工具。可以设置BeyondCompare,DiffMerge等作为git的比较和合并的可视化工具,方便操作。
04.常见信息
a.git log 显示提交日志信息
git log --显示提交日志信息
git log --no-merges --显示整个提交历史记录,但跳过合并记录
git log dev home --显示home子目录中的任何文件的所有提交
git log --graph --可以看到分支合并图
git log -3 --查看最近三次提交
-----------------------------------------------------------------------------------------------------
git log --author=csf --查看csf作者的提交记录
git log --after={2019-03-01}/git log --since={2019-03-01} --查看2018-03-01日之后的提交记录,包括当前日期
git log --until={2019-03-01}/git log --before={2019-03-01} --查看2018-03-01日之前的提交记录,不包括当前日期
git log --until={2019-03-07} --after={2019-03-05} --查看2018-03-05到2018-03-06两天的提交记录
-----------------------------------------------------------------------------------------------------
git log commitID --查看包含commitID之前的历史记录
*git log commitID1 commitID2 --查询commit1与commit2之间的记录,包括commit1和commit2
*git log commitID1..commitID2 --查询commit1与commit2之间的记录,不包括commit1
-----------------------------------------------------------------------------------------------------
git log HEAD^ --HEAD代表最后一次提交,HEAD^为最后一个提交的父提交,等同于HEAD~1
git log HEAD~2 HEAD~2 --代表倒数第二次提交
git log --pretty=oneline --按指定格式显示日志信息(显示一行,可选项有:oneline,short,medium,full,fuller,email,raw以及format:,默认为medium)
git log --pretty=oneline --abbrev-commit --按指定格式显示日志信息,显示一行,commitID使用7位数
git log --pretty=format:"%an %ae %ad %cn %ce %cd %cr %s" --graph --自定义格式图文形式输出
-----------------------------------------------------------------------------------------------------
选项说明
%H —— 提交对象(commit)的完整哈希字串
%h —— 提交对象的简短哈希字串
%T —— 树对象(tree)的完整哈希字串
%t —— 树对象的简短哈希字串
%P —— 父对象(parent)的完整哈希字串
%p —— 父对象的简短哈希字串
%an —— 作者(author)的名字
%ae —— 作者的电子邮件地址
%ad —— 作者修订日期(可以用 -date= 选项定制格式)
%ar —— 作者修订日期,按多久以前的方式显示
%cn —— 提交者(committer)的名字
%ce —— 提交者的电子邮件地址
%cd —— 提交日期
%cr —— 提交日期,按多久以前的方式显示
%s —— 提交说明
b.git stash 将更改储藏在脏工作目录中
如果你储藏了一些工作,暂时不去理会,然后继续在你储藏工作的分支上工作,你在重新应用工作时可能会碰到一些问题。
如果尝试应用的变更是针对一个你那之后修改过的文件,你会碰到一个归并冲突并且必须去化解它。
如果你想用更方便的方法来重新检验你储藏的变更,你可以运行 git stash branch,
这会创建一个新的分支,检出你储藏工作时的所处的提交,重新应用你的工作,如果成功,将会丢弃储藏。
这是一个很棒的捷径来恢复储藏的工作然后在新的分支上继续当时的工作。
-----------------------------------------------------------------------------------------------------
git stash/git stash save --将更改储藏在脏工作目录中(只是会将git跟踪的文件(unstaged changes)和暂存区中的文件(staged changes)进行修改)
git stash -u --将更改储藏在脏工作目录中(git跟踪的文件(unstaged changes)、暂存区中的文件(staged changes)、工作目录中的新文件(untracked files))
git stash -a/git stash --all --将当前目录的所有文件都进行储藏(git跟踪的文件(unstaged changes)、暂存区中的文件(staged changes)、工作目录中的新文件(untracked files)、被忽略的文件(ignored files))
git stash list --查看现有的储藏
git stash apply --应用最新一次储藏的内容,不删除赃工作目录
git stash apply stash@{2} --应用指定储藏版本的内容
git stash apply --index
git stash drop stash@{0} --删除指定储藏版本的内容,之后的名称1会变成从0开始
git stash pop --应用最新一次储藏版本的内容,并将其从堆栈中移走,此时运行git stash list将没有这个储藏的记录
git stash show/git stash show stash@{0} --查看最新一个stash的diff统计信息
git stash show -p/git stash show -p stash@{0} --查看最新一个stash的展开diff
git stash clear --删除所有缓存的stash
git stash branch testNew --从stash创建分支,如果成功,将会丢弃储藏。
c.git tag 创建,列出,删除或验证使用GPG签名的标签对象
git tag/git tag -l/git tag -l <tagName> --查看所有标签、查看指定标签
git tag <name> --当前分支的最新HEAD打新标签
git tag <name> <commitID> --给对应的某个commitID打标签
git tag <name>-light --创建轻量标签
git tag -a <name> -m "message" --创建带有说明的标签,即注释标签,用-a指定标签名,-m指定说明文字
git tag -d <name> --删除本地标签
git tag start ?
d.git remote 管理远程主机
git remote --列出所有远程主机
git remote -v --查看远程主机的网址
git remote show <主机名> --查看主机的详细信息
git remote add <主机名> <网址> --添加远程主机
git remote rm <主机名> --删除远程主机
git remote rename <原主机名> <新主机名> --重命名远程主机
e.git fetch 从另一个存储库下载对象和引用
通常是将远程主机的版本库有了新的commit的时候,将这些更新取回本地,
这个命令通常用来查看其他人的进程,因为它取回的代码对本地的开发代码没有影响。
-----------------------------------------------------------------------------------------------------
可以使用git merge和git rebase命令,在本地分支合并远程分支。
这个命令主要是在合并之前可以看看有哪些地方进行了修改
-----------------------------------------------------------------------------------------------------
git fetch <远程主机名> --将远程主机的更新全部取回本地,默认是所有分支的更新
git fetch <远程主机名><分支名> --取回远程主机中的特定分支的更新(git fetch origin dev)
*git fetch origin branch1:branch2
-----------------------------------------------------------------------------------------------------
首先执行上面的fetch操作,使用远程branch1分支在本地创建branch2(但不会切换到该分支),
如果本地不存在branch2分支, 则会自动创建一个新的branch2分支,
如果本地存在branch2分支, 并且是`fast forward', 则自动合并两个分支, 否则, 会阻止以上操作.
-----------------------------------------------------------------------------------------------------
git fetch origin :branch2 等价于: git fetch origin master:branch2
f.git pull 从另一个存储库或本地分支获取并集成(整合)
取回远程主机某个分支的更新,再与本地的指定分支合并,它的完整格式稍稍有点复杂。
默认模式下,git pull 是git fetch 和git merge FETCH_HEAD的缩写
-----------------------------------------------------------------------------------------------------
git pull <远程主机名> --将远程主机的全部分支取回并与本地分支合并,如果当前分支和远程分支有追踪关系,git pull就可以省略远程分支名。
git pull <远程主机名><远程分支名> --将远程主机的某一个分支取回和本地当前分支合并
git pull <远程主机名><远程分支名>:<本地分支名> --将远程的某一分支取回和本地某一分支进行合并(git pull dev:test)
git pull --rebase <远程主机名><远程分支名>:<本地分支名> --将远程某一分支取回和本地某个分支进行rebase合并,不写默认是merge
*git pull -p --如果远程主机删除了某个分支,就会在本地删除远程已经删除的分支 (等同git fetch --prune origin → git fetch -p)
g.git push 将本地分支的更新,推送到远程主机
git push --如果远程主机和当先分支有追踪关系,那么主机名可以忽略,默认是将所有的分支都取回
git push <远程主机名><远程分支名>:<本地分支名> --将本地某一分支推送到远程主机的某一分支上
git push <远程主机名> --delete <远程分支名> / git push <远程主机名> :<远程分支名> --删除远程某一分支(第二种相当于推送一个空的本地分支到远程分支,也是删除远程分支的)
-----------------------------------------------------------------------------------------------------
git push origin --如果远程主机和当先分支有追踪关系,将本地当前分支推送到origin远程主机的对应分支
git push origin test --将本地的当前分支推送到远程主机的test分支,如果test分支不存在,则会被新建
git push origin test:test1 --将本地的test分支推送到origin远程主机的test1分支上
git push origin --delete test /git push origin :test --删除远程test分支
git push --all origin --将所有本地分支都推送到origin远程主机(当远程主机的版本bii本地版本更新的时候,推送时git会报错,要求先在本地做git pull合并差异)
git push --force origin/git push -f origin --将本地分支强推送到origin远程主机,结果导致在远程主机产生一个”非直进式”的合并(non-fast-forward merge)。除非你很确定要这样做,否则应该尽量避免使用–-force选项。
git push -f origin dev:student --将本地的dev分支强覆盖origin远程主机的远程student分支
git push -u origin master --如果当前分支与多个主机存在追踪关系,使用-u指定一个默认主机,这样就可以不加任何参数的使用git push(这个是指定了origin主机的master为默认选项)
git push origin <tagName> --推送某个标签到远程分支
git push origin --tags --一次性推送全部尚未推送到远程的本地标签
git push origin :<tagname> / git push origin :refs/tags/<tagname> --删除一个远程标签
h.git submodule 初始化,更新或检查子模块
git submodule add http://github.com/chaconinc/DbConnector --添加一个名为 “DbConnector” 的库。默认情况下,子模块会将子项目放到一个与仓库同名的目录中,如果你想要放到其他地方,看下面。
git submodule add <版本库的网址> <本地目录名> --把某版本库添加到本地的某个目录中。
git submodule update --init --recursive --已经克隆了主库但没初始化子模块
git submodule update --recursive --remote --已经克隆并初始化子模块,而需要从子模块的源更新这个子模块.更新之后主库的,git 差异中会显示新的 SHA 码,把这个差异选中提交即可。
git submodule --查看子模块
git submodule update --更新项目内子模块到最新版本
git submodule update --remote --更新子模块为远程项目的最新版本
git submodule init --初始化子模块
05.常见信息
a.git show 用于显示各种类型的对象
git show tagName --看到说明文字
b.git shortlog 汇总git日志输出
git shortlog --汇总每个人的commit记录,进行简单输出
git shortlog -s --参数省略每次 commit 的注释,仅仅返回一个简单的统计。
git shortlog -n --参数按照 commit 数量从多到少的顺利对用户进行排序
git shortlog -sn/git shortlog -s -n --按照commit的数量从多到少进行排序,并简单的统计数量。
git shortlog -2 --查看最近两次的commit记录
c.git describe 显示离当前提交最近的标签
该命令查找从提交可访问的最新标记。如果标签指向提交,则只显示标签。
否则,它将标记 名称与标记对象之上的其他提交数量 以及 最近提交的缩写对象名称后缀。
git describe 如果最新一次提交没有注释标签,那么会显示
-----------------------------------------------------------------------------------------------------
fatal: No annotated tags can describe 'daa38004d76012c77029727096b9e4ef724030a7'.
However, there were unannotated tags: try --tags.
-----------------------------------------------------------------------------------------------------
git describe --tags 显示离当前提交最近的标签,不限于只是注释标签, 如果tag之后没有提交,就只显示名字,如果之后有提交,就显示下面的
-----------------------------------------------------------------------------------------------------
merge1this-1-g84a2cd7说明:"最新一次tagName" — "打tagName以来有两次提交commit" — "最新一个g+commitID" ,g表示git
如果之后没有提交,后面两个参数不会写。
git describe --all
git describe --contains
git describe --always
d.git rebase 合并分支
git rebase --将合并分支合并到当前分支,并将当前分支的代码合并到后面,获取干净整洁的班版本树
git rebase --continue --git遇到冲突会停下要求解决冲突,冲突解决完之后会继续应用(apply)余下的补丁
git rebase --skip --跳过当前合并的冲突,进入下一个提交的diff
git rebase --abort --任何时候都可以用这个命令终止rebase操作,分支会回到rebase开始的状态
e.git reflog GIT操作历史记录
一般用于维护和数据恢复。当你在一个仓库下工作时,你的每一步操作都会记录下来,
包括checkout,rebase,merge,commit操作。所以这个也是一个很好的回滚方式。
-----------------------------------------------------------------------------------------------------
git reflog / git reflog show --显示所有的git操作历史记录
git reflog dev --显示在dev分支上面的操作历史记录 git reset --hard git@{1} 回滚到那个位置
git reflog --date=local | grep merge1 --根据本地时间查看merge1分支的git操作记录
git reflog delete HEAD@{1} --删除对应步骤的git操作历史记录
f.git cherry-pick 摘樱桃模式
git cherry-pick commitID
-----------------------------------------------------------------------------------------------------
可以选择某个分支的一个或几个commit合并到另一个分支上。
假设有一个稳定版本,现在要升级版本,如果将两个版本的分支合并,那么会造成版本混乱,不利于维护,一般会将要增加的功能单独提交一个分支,然后增加到新版本上,就可以使用cherry-pick了。
记住cherry-pick是一个本地操作。假如你在pull代码之后有人又提交了代码,那么需要先pull代码,再进行cherry-pick
5.2 配置ssh
00.配置
a.gitconfig
[user]
email = [email protected]
name = halavah
[commit]
gpgsign = false
[pull]
rebase = true
[core]
longpaths = true
[branch]
autosetuprebase = always
[rebase]
autoStash = true
[credential "https://git.jggroup.cn"]
provider = generic
[filter "lfs"]
clean = git-lfs clean -- %f
smudge = git-lfs smudge -- %f
process = git-lfs filter-process
required = true
b.ssh/config
Host github.com
Hostname ssh.github.com
Port 443
Host git.jggroup.cn
HostKeyAlgorithms +ssh-rsa
PubkeyAcceptedKeyTypes +ssh-rsa
c.ssh/config示例
Host workhost0 # 远程主机别名
HostName 192.168.63.8 # 远程主机ip
User zhangsan # 你在远程主机的用户名
Port 22
IdentityFile ~/.ssh/id_ssh # 你的ssh秘钥文件
Host workhost1
HostName 192.168.63.9
User zhangsan
Port 22
IdentityFile ~/.ssh/id_ssh
d.ssh/config示例
# desc: github ([email protected])
Host github.com
Hostname github.com
User git
PreferredAuthentications publickey
Identityfile ~/.ssh/github
# desc: my_server_user ([email protected])
Host your_domain_name_or_ip
HostName your_domain_name_or_ip
User git
IdentityFile ~/.ssh/custom_rsa
# 以上各字段说明:
# Host:主机名字,不能重名
# HostName:主机所在域名或IP
# User:服务器上的用户名
# PreferredAuthentications:不填此行的话,如果pubkey验证不通过可以用密码方式;填了`publickey`只能通过公钥验证的方式
# IdentityFile:私钥路径
01.配置SSH
a.测试
| 特性 | authorized_keys | known_hosts
|----------|-------------------------------------------|----------------------------
| 作用对象 | 控制谁可以登录到本地服务器 | 确认远程主机的身份
| 存储内容 | 被授权登录本地服务器的用户公钥 | 已知远程主机的公钥
| 作用场景 | 公钥认证无密码登录 | 防止连接到不可信的主机,防止中间人攻击
| 配置位置 | 服务器端用户目录下的 .ssh/authorized_keys | 客户端用户目录下的 .ssh/known_hosts
| 安全性 | 控制谁能登录服务器 | 确保连接到正确的服务器
b.ohmyzsh说明
master ⇣2 !3077 ?1 ❯
master: 当前所在的 Git 分支名称。在这个例子中,你在 master 分支上。
⇣2: 表示当前分支落后于远程分支 2 次提交。你需要执行 git pull 来同步更新。
!3077: 表示当前有一个未提交的更改,文件的状态码是 3077。具体的状态码可能因插件配置而异,通常表示有冲突或其他需要解决的问题。
?1: 表示有一个未跟踪的文件。你可以使用 git add 来将其添加到暂存区。
❯: 这是提示符的结束符,表示你可以在这里输入命令。
-----------------------------------------------------------------------------------------------------
master *1 ~6 +3071
master: 当前所在的 Git 分支名称。在这个例子中,你在 master 分支上。
*1: 表示有一个文件已经被修改并暂存(staged),准备提交。
~6: 表示有六个文件被修改但尚未暂存(unstaged)。
+3071: 表示有 3071 个新增的行或文件已经被暂存。
c.配置.gitconfig
git config --global user.email "[email protected]" --必选
git config --global user.name "myslayers" --必选
git config --global branch.autosetuprebase always --必选(让所有新创建的分支默认启用rebase模式,而不是merge模式)
git config --global pull.rebase true --必选(解决pull时,默认使用 rebase 而不是 merge)
git config --global rebase.autoStash true --必须(解决pull时,在 rebase 时自动 stash 未提交的更改)
git config --global push.autoSetupRemote always (废弃)--必选(自动设置远程跟踪分支)
git config --global core.excludesfile ~/.gitignore_global --必选(全局上传忽略文件)
git config --global core.longpaths true --必选(允许长文件拉取)
-----------------------------------------------------------------------------------------------------
branch.autosetuprebase always:
默认值:branch.autosetuprebase 的默认值是 false。
效果:如果设置为 always,则在创建新分支时,Git 会自动将该分支配置为在执行 git pull 时使用变基。
这意味着所有新分支在拉取远程更改时会默认使用变基而不是合并。
-----------------------------------------------------------------------------------------------------
pull.rebase true:
默认值:pull.rebase 的默认值是 false。
效果:如果设置为 true,则在执行 git pull 时,Git 会默认使用变基而不是合并。
这会使你的提交历史更线性,但可能需要更多的冲突解决
-----------------------------------------------------------------------------------------------------
rebase.autoStash true:
默认值:rebase.autoStash 的默认值是 false。
效果:如果设置为 true,在执行变基操作时,Git 会自动暂存未提交的本地更改,并在变基完成后自动恢复这些更改。
这可以防止未提交的更改在变基过程中丢失。
d.配置.gitconfig
git config --global gpg.program "C:\software\gunpg\bin\gpg.exe"
git config --global commit.gpgsign false
git config --global http.proxy 'http://127.0.0.1:7890'
git config --global https.proxy 'http://127.0.0.1:7890'
-----------------------------------------------------------------------------------------------------
git config --global --list --查看.gitconfig
git config --list --show-origin --查看.gitconfig
e.生成新的SSH密钥
ssh-keygen -t rsa -C "[email protected]" --方式1:带邮箱信息
ssh-keygen -t rsa -b 4096 --方式2:随机id
ssh-keygen -t ed25519 -C "[email protected]" --方式2:git 2.47.0
cat ~/.ssh/id_rsa --查看id_rsa私钥
cat ~/.ssh/id_rsa.pub --查看id_rsa.pub公钥
f.方式1(github):将id_rsa.pub公钥至SSH Key
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDAwun --示例
ssh -T [email protected] --验证github.com
ssh -T [email protected] --验证gitlab.com
ssh -T [email protected]:10443 --验证git.nantian.com.cn
ssh -T [email protected] --验证10.10.41.51
git remote -v --查看远程分支
g.方式2(win -> linux):id_rsa.pub公钥至authorized_keys
ssh [email protected] -p 64953 --known_hosts确认远程主机的身份
h.方式3(linux -> linux):ssh-copy-id
ssh-keygen -t rsa -b 4096 --第1步:id_rsa私钥、id_rsa.pub公钥
ssh-copy-id localhost --第2步:发送私钥(本机)
ssh-copy-id bigdata02 --第3步:发送公钥(其他计算机)
ssh bigdata02 --第4步:测试免密钥登陆
02.Gogs私服
a.查看算法
cat C:\Users\mysla\.ssh\id_rsa.pub --为rsa算法
Git 的新版本默认禁用了 ssh-rsa 算法,而服务器【Gogs】只提供 ssh-rsa
b.算法不一致
a.测试
用户名+密码
生成不带邮箱
邮箱一致性,算法一致性
b.方式1
a.说明
继续使用当前的 RSA 密钥,但需要配置 SSH
b.配置
touch C:\Users\mysla\.ssh\config
Host git.jggroup.cn
HostKeyAlgorithms +ssh-rsa
PubkeyAcceptedKeyTypes +ssh-rsa
c.方式2
a.说明
生成一个新的,更安全的 Ed25519 密钥(推荐)
b.仅支持ed25519
Host git.jggroup.cn
HostKeyAlgorithms +ssh-ed25519
PubkeyAcceptedKeyTypes +ssh-ed25519
IdentityFile ~/.ssh/id_ed25519
c.支持ed25519、rsa
Host git.jggroup.cn
HostKeyAlgorithms +ssh-ed25519,ssh-rsa
PubkeyAcceptedKeyTypes +ssh-ed25519,ssh-rsa
IdentityFile ~/.ssh/id_ed25519
IdentityFile ~/.ssh/id_rsa
c.测试命令
a.ssh -T [email protected] -p 9022
测试 SSH 连接到 Git 服务器
-T禁用伪终端分配,用于测试纯 SSH 连接
默认使用 22 端口
用于验证 SSH 密钥认证是否正常工作
b.ssh -T [email protected] -p 9022 -v
-p 9022 指定使用 9022 端口(而不是默认的 22 端口)
-v 表示 verbose(详细)模式,显示详细的连接过程信息
用于调试 SSH 连接问题时查看具体细节
c.git remote -v
查看远程分支
d.使用命令
ssh -T [email protected] -p 9022 -v
-----------------------------------------------------------------------------------------------------
OpenSSH_for_Windows_8.1p1, LibreSSL 3.0.2
debug1: Reading configuration data C:\\Users\\mysla/.ssh/config
debug1: C:\\Users\\mysla/.ssh/config line 4: Applying options for git.jggroup.cn
debug1: Connecting to git.jggroup.cn [198.18.0.8] port 9022.
debug1: Connection established.
debug1: identity file C:\\Users\\mysla/.ssh/id_rsa type 0
debug1: identity file C:\\Users\\mysla/.ssh/id_rsa-cert type -1
debug1: identity file C:\\Users\\mysla/.ssh/id_dsa type -1
debug1: identity file C:\\Users\\mysla/.ssh/id_dsa-cert type -1
debug1: identity file C:\\Users\\mysla/.ssh/id_ecdsa type -1
debug1: identity file C:\\Users\\mysla/.ssh/id_ecdsa-cert type -1
debug1: identity file C:\\Users\\mysla/.ssh/id_ed25519 type -1
debug1: identity file C:\\Users\\mysla/.ssh/id_ed25519-cert type -1
debug1: identity file C:\\Users\\mysla/.ssh/id_xmss type -1
debug1: identity file C:\\Users\\mysla/.ssh/id_xmss-cert type -1
debug1: Local version string SSH-2.0-OpenSSH_for_Windows_8.1
debug1: Remote protocol version 2.0, remote software version Go
debug1: no match: Go
debug1: Authenticating to git.jggroup.cn:9022 as 'git'
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: algorithm: [email protected]
debug1: kex: host key algorithm: ssh-rsa
debug1: kex: server->client cipher: aes128-ctr MAC: [email protected] compression: none
debug1: kex: client->server cipher: aes128-ctr MAC: [email protected] compression: none
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: ssh-rsa SHA256:z5dewbji7WqMHXJmkgRzoFgM3twbkakuien9BNF2iPs
debug1: Host '[git.jggroup.cn]:9022' is known and matches the RSA host key.
debug1: Found key in C:\\Users\\mysla/.ssh/known_hosts:10
debug1: rekey out after 4294967296 blocks
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: rekey in after 4294967296 blocks
debug1: pubkey_prepare: ssh_get_authentication_socket: No such file or directory
debug1: Will attempt key: C:\\Users\\mysla/.ssh/id_rsa RSA SHA256:t/i7iu7i7Z7FI6xLl2iUIxVqXunKS9TTnyI+L5U3ECM
debug1: Will attempt key: C:\\Users\\mysla/.ssh/id_dsa
debug1: Will attempt key: C:\\Users\\mysla/.ssh/id_ecdsa
debug1: Will attempt key: C:\\Users\\mysla/.ssh/id_ed25519
debug1: Will attempt key: C:\\Users\\mysla/.ssh/id_xmss
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Offering public key: C:\\Users\\mysla/.ssh/id_rsa RSA SHA256:t/i7iu7i7Z7FI6xLl2iUIxVqXunKS9TTnyI+L5U3ECM
debug1: Server accepts key: C:\\Users\\mysla/.ssh/id_rsa RSA SHA256:t/i7iu7i7Z7FI6xLl2iUIxVqXunKS9TTnyI+L5U3ECM
debug1: Authentication succeeded (publickey).
Authenticated to git.jggroup.cn ([198.18.0.8]:9022).
debug1: channel 0: new [client-session]
debug1: Entering interactive session.
debug1: pledge: network
-------------------------------------------------------------------------------------------------
debug1: Authentication succeeded (publickey). --认证成功
03.常见报错
a.报错1
a.问题
git各种命令执行很慢是什么原因导致的?
项目是放在 github 上的,在 windows 环境下,执行各种 git 命令很慢
比如:git status 、git log 等各种命令,基本上要等接近 1s 左右才返回。但是在 Linux 下却是瞬间就返回了,什么原因导致的?
然后我用 fork 这个 ui 工具,看 local changes 的时候点一个文件也要半天才加载出来
或者我点某个 commit 的时候,也要加载至少 1s 才能把这个 commit 的完整信息显示出来
还有就最近在编译 golang 项目的时候也要编译很久(至少分钟级),电脑配置是 64G i7-1365HX 。以前都是几秒就编译完成了。 编译的时候看电脑 CPU 和内存都不高
这咋办? 重装系统?
b.解决
windows上的git突然坏了,git特别慢,git用不了了,罪魁祸首竟然是微软电脑。
pycharm重启了五六次,vscode重启了两三次,电脑重启了一次,git重装了一次我尝试了所有我能想到的问题比如网络问题等等,
最后不经意在评论区看到了一个解决犯法提到了电脑管家,刚好这个进程我之前经常看那个任务管理器发现有个mspc manager,
我当时看他一直占着资源还去网上搜了知道他是微软电脑管家。
vscode安装完git,别点vscode里面的重启,要手动关掉再打开,否则vscode永远识别不到git,
pycharm也不行的,cmd也卡半天,就是那个mspc manager的问题。
b.报错2
a.问题
C:\Users\mysla>ssh -T [email protected]
kex_exchange_identification: Connection closed by remote host
-------------------------------------------------------------------------------------------------
D:\software_ware\99.Directory99\quartz-end>git push
fatal: unable to access 'https://github.com/halavah/quartz-end/': Failed to connect to github.com port 443 after 21070 ms: Could not connect to server
b.解决
终端默认不走Clash代理,需要开启TUN模式
-------------------------------------------------------------------------------------------------
C:\Users\mysla\.ssh\config -> 添加
Host github.com
Hostname ssh.github.com
Port 443
c.报错3
a.问题
D:\software_ware\99.Directory02>git push origin master
fatal: unable to access 'https://github.com/halavah/valut2.git/':
Failed to connect to github.com port 443 after 21106 ms: Could not connect to server
b.解决
1721013384645.yml:Clash跳过防火墙(该yml已配置TUN模式,已添加【私人DNS,172.16.10.130】到DNS服务器)
1721808749745.yml:默认配置
d.报错4
a.问题
D:\software_ware\99.Directory99\vilgoboot-plus>git add ydsz-cloud-parent/ydsz-module-system-cloud/ydsz-visual/
error: open("ydsz-cloud-parent/ydsz-module-system-cloud/ydsz-visual/ydsz-cloud-test/ydsz-cloud-test-seata/ydsz-cloud-test-seata-account/src/main/java/org/jeecg/modules/test/seata/account/service/impl/SeataAccountServiceImpl.java"): Filename too long
error: unable to index file 'ydsz-cloud-parent/ydsz-module-system-cloud/ydsz-visual/ydsz-cloud-test/ydsz-cloud-test-seata/ydsz-cloud-test-seata-account/src/main/java/org/jeecg/modules/test/seata/account/service/impl/SeataAccountServiceImpl.java'
fatal: adding files failed
b.说明
Windows 系统对文件路径长度有限制(通常是 260 个字符)
c.方式1:启用 Windows 长路径支持(推荐)
# 以管理员身份运行 PowerShell 或命令提示符,执行:
git config --system core.longpaths true
d.方式2:配置 Git 支持长路径
# 在项目目录下执行
git config core.longpaths true
e.方式3:修改 Windows 注册表
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem
将 LongPathsEnabled 值设为 1
e.报错5
a.问题
Cloning into 'jh4j-cloud-page'...
remote: Enumerating objects: 1981, done.
remote: Counting objects: 100% (1981/1981), done.
remote: Compressing objects: 100% (1618/1618), done.
error: RPC failed; curl 18 transfer closed with outstanding read data remaining
error: 24935 bytes of body are still expected
fetch-pack: unexpected disconnect while reading sideband packet
fatal: early EOF
fatal: fetch-pack: invalid index-pack output
b.说明
经过查询发现主要原因是因为git clone的远程仓库的项目过大导致项目拉取失败。
c.解决
当推送大量数据时(初始推送大型存储库,使用非常大的文件进行更改)可能需要 http.postBuffer
在 git 客户端 (而不是服务器)上设置更高的 设置 ;将 Git 缓冲区大小增加到 repo 的最大单个文件大小:
d.解决2
方案一:增大 Git 的 HTTP 缓冲区(最推荐)
# 设置500MB
git config --global http.postBuffer 524288000
# 设置1GB
git config --global http.postBuffer 1073741824
# 设置3GB
git config --global http.postBuffer 3221225472
-------------------------------------------------------------------------------------------------
方案二:使用浅克隆(Shallow Clone)
git clone --depth 1 https://[email protected]/JinGangIntegrate/jingangintegrate-ui.git jh4j-cloud-page
git clone --depth 1 [email protected]:JinGangIntegrate/jingangintegrate-ui.git jh4j-cloud-page
克隆成功后,如果你需要获取完整的历史记录,可以进入项目目录,然后执行
git fetch --unshallow
-------------------------------------------------------------------------------------------------
20250808:后经验证,内网git网络导致http下载失败,jingangintegrate-ui.zip大小有153.6MB
5.3 传输大文件
01.上传限制
a.Gogs
使用SSH传输无限制,ssh://[email protected]:9022/server/ydsz-boot-starter.git
git remote set-url origin [email protected]:halavah/vilgoboot.git --切换为ssh
git remote -v --查看远程分支
b.Github
D:\software_ware\03.Directory03>git push origin master
Enumerating objects: 1322, done.
Counting objects: 100% (1322/1322), done.
Delta compression using up to 8 threads
Compressing objects: 100% (1320/1320), done.
error: RPC failed; HTTP 400 curl 22 The requested URL returned error: 400
send-pack: unexpected disconnect while reading sideband packet
Writing objects: 100% (1322/1322), 413.18 MiB | 4.98 MiB/s, done.
Total 1322 (delta 4), reused 0 (delta 0), pack-reused 0 (from 0)
fatal: the remote end hung up unexpectedly
Everything up-to-date
因为推送的文件太大导致的。
-----------------------------------------------------------------------------------------------------
GitHub 有以下限制:
单个文件不能超过 100MB
建议仓库总大小不超过 1GB
推送限制约为 2GB
这个错误通常是因为推送的文件太大导致的。
c.Git LFS
处理github不允许上传超过100MB文件的问题
如果超过每个文件5GB的限制,Git LFS 将拒绝该文件,并显示错误消息;LFS每月1GB的流量额度
d.解决办法
a.方法1:增大 Git 缓冲区大小
增大 http.postBuffer 的大小(单位为字节):git config --global http.postBuffer 524288000
-------------------------------------------------------------------------------------------------
git config --global http.postBuffer 524288000
git config --global http.maxRequestBuffer 524288000
git config --global core.packedGitLimit 512m
git config --global core.packedGitWindowSize 512m
git config --global pack.deltaCacheSize 512m
git config --global pack.packSizeLimit 512m
git config --global pack.windowMemory 512m
b.方法2:降低压缩级别
降低压缩级别以减少本地 CPU 压力:git config --global core.compression 2
c.方法3:分次推送(拆分提交推送)
如果推送的内容非常大,可以分批次推送:
推送部分提交:git push origin master --max-pack-size=20M,将单个数据包限制为 10MB,逐步推送剩余部分。
手动分批提交文件:git add <部分文件>
git commit -m "Partial commit"
git push origin master
d.方法4:上传大文件到 Git LFS
对于包含大文件(如图片、视频或压缩包)的仓库,可以将这些大文件转移到 Git LFS(Git Large File Storage):
安装 Git LFS:git lfs install
添加大文件到 Git LFS:git lfs track "*.zip" # 以 .zip 文件为例
提交并推送:git add .gitattributes
git commit -m "Add LFS tracking for large files"
git push origin master
02.使用LFS
a.正确操作
a.安装 Git LFS 根据系统安装 Git LFS
git lfs install
b.跟踪大文件 指定要使用 LFS 跟踪的文件
git lfs track "ydsz-boot-starter-demo/lib/ydsz-module-system.jar"
c.提交文件 重新提交大文件
git add .gitattributes
git add ydsz-boot-starter-demo/lib/ydsz-module-system.jar
git commit -m "Add large file to Git LFS"
d.推送到远程仓库 推送更改
git push origin master
b.操作gitattributes
a.操作
# 重新创建 .gitattributes
echo "*.zip filter=lfs diff=lfs merge=lfs -text" > .gitattributes
# 提交更改
git add .gitattributes
git commit -m "Fix .gitattributes format"
b.修改 .gitattributes 文件
运行 git lfs track "*.jar" 来开始追踪 .jar 文件
提交更改:git add .gitattributes 和 git commit -m "track jar files with Git LFS"
c.默认规则
a.对于新添加的 zip 文件:
直接使用普通的 git add 和 git commit 即可
Git LFS 会自动处理这些文件
git add new-file.zip
git commit -m "Add new zip file"
git push
b.git lfs migrate import 命令只需要在以下情况使用:
处理历史提交中的旧文件
需要将已经在 Git 历史中的大文件转换为 LFS 格式
c.验证 LFS 是否正常工作:
# 查看 LFS 追踪的文件
git lfs ls-files
# 查看文件状态
git lfs status
d.总结一下
新文件:直接 git add 和 git commit
历史文件:需要 git lfs migrate import
.gitattributes 配置已经生效,新添加的 zip 文件会自动被 LFS 处理,不需要额外的 migrate 命令。
03.Git历史报错
a.报错1
a.问题
Total 5011 (delta 754), reused 4481 (delta 522), pack-reused 0 (from 0)
remote: Resolving deltas: 100% (754/754), completed with 16 local objects.
remote: warning: File ydsz-cloud-starter-final/backup/ydsz-cloud-starter-final_v1.7_正式发布_发布到gogs_v1.0.0_单体架构.zip is 57.43 MB; this is larger than GitHub's recommended maximum file size of 50.00 MB
remote: warning: File ydsz-boot-starter-final/backup/ydsz-boot-starter-final_v1.6_正式版本_发布到final_仅更改readme发布 到gogs_交换web与web2.zip is 73.58 MB; this is larger than GitHub's recommended maximum file size of 50.00 MB
remote: error: Trace: bc439367f167cae5c72092242a00182cae978448e174d3f01db72c09ee8cdf0a
remote: error: See https://gh.io/lfs for more information.
b.提问
为什么我这次提交删除了ydsz-boot-example/lib/ydsz-module-system.jar,但是push还是报错
c.操作
a.首先,清理 Git 历史中的大文件
# 使用 BFG Repo Cleaner(推荐)
java -jar bfg.jar --strip-blobs-bigger-than 100M .git/
# 或者使用 git filter-branch(较慢)
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch ydsz-boot-example/lib/ydsz-module-system.jar" \
--prune-empty --tag-name-filter cat -- --all
b.清理和压缩仓库
git reflog expire --expire=now --all
git gc --prune=now --aggressive
c.强制推送更改
git push origin --force --all
b.报错2
a.问题
D:\software_ware\99.Directory99\vilgoboot>git push origin --force --all
Enumerating objects: 5309, done.
Counting objects: 100% (5309/5309), done.
Delta compression using up to 8 threads
Compressing objects: 100% (4273/4273), done.
Writing objects: 100% (5285/5285), 126.49 MiB | 783.00 KiB/s, done.
Total 5285 (delta 957), reused 4535 (delta 731), pack-reused 0 (from 0)
remote: Resolving deltas: 100% (957/957), completed with 17 local objects.
remote: warning: See https://gh.io/lfs for more information.
remote: warning: File ydsz-cloud-starter-final/backup/ydsz-cloud-starter-final_v1.7_正式发布_发布到gogs_v1.0.0_单体架构.zip is 57.43 MB; this is larger than GitHub's recommended maximum file size of 50.00 MB
remote: warning: File ydsz-boot-starter-final/backup/ydsz-boot-starter-final_v1.6_正式版本_发布到final_仅更改readme发布 到gogs_交换web与web2.zip is 73.58 MB; this is larger than GitHub's recommended maximum file size of 50.00 MB
remote: warning: GH001: Large files detected. You may want to try Git Large File Storage - https://git-lfs.github.com.
To github.com:halavah/vilgoboot.git
e1e74ae0..6eb0f10c master -> master
b.提问
这个日志显示 push 操作基本成功了,但还有两个大文件的警告:
ydsz-cloud-starter-final/backup/ydsz-cloud-starter-final_v1.7_正式发布_发布到gogs_v1.0.0_单体架构.zip (57.43 MB)
ydsz-boot-starter-final/backup/ydsz-boot-starter-final_v1.6_正式版本_发布到final_仅更改readme发布 到gogs_交换web与web2.zip (73.58 MB)
c.使用 Git LFS 来处理这些文件
a.安装并配置 Git LFS:
# 安装 Git LFS
git lfs install
# 创建 .gitattributes 文件
echo "*.zip filter=lfs diff=lfs merge=lfs -text" > .gitattributes
b.将现有大文件转换为 LFS
# 追踪 zip 文件
git lfs track "*.zip"
# 将现有文件转换为 LFS
git lfs migrate import --include="*.zip"
c.提交更改
git add .gitattributes
git commit -m "Add Git LFS configuration for zip files"
git push origin --force --all
c.报错3
a.问题
D:\software_ware\99.Directory99\vilgoboot>echo "*.zip filter=lfs diff=lfs merge=lfs -text" > .gitattributes
D:\software_ware\99.Directory99\vilgoboot>git lfs track ".zip"
Tracking ".zip"
D:\software_ware\99.Directory99\vilgoboot>git lfs migrate import --include="*.zip"
migrate: override changes in your working copy? All uncommitted changes will be lost! [y/N]
b.操作
a.保存当前更改
git add .
git commit -m "Save current changes before LFS migration"
b.执行 LFS 迁移
git lfs migrate import --include="*.zip"
c.推送更改
git push origin
d.报错4
a.问题
D:\software_ware\99.Directory99\vilgoboot-plus>git push
To github.com:halavah/vilgoboot-plus.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'github.com:halavah/vilgoboot-plus.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. If you want to integrate the remote changes,
hint: use 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
b.说明
因为本地仓库和远程仓库出现了分叉
c.方案1:变基
# 1. 先拉取远程并变基
git pull --rebase origin master
# 2. 如果有冲突,解决冲突后
git add .
git rebase --continue
# 3. 推送到远程
git push origin master
d.方案2:合并
# 1. 拉取并合并
git pull origin master
# 2. 如果有冲突,解决冲突后
git add .
git commit -m "merge: 解决冲突"
# 3. 推送到远程
git push origin master
e.报错5
a.问题
如果你在本地将文件夹名称从大写改为小写,但在上传到远程仓库后仍然显示为大写
b.分析
由于文件系统的大小写敏感性问题。某些文件系统(如 Windows 的 NTFS)对文件和文件夹名称不区分大小写,
而 Git 和大多数远程仓库(如 GitHub)是区分大小写的。
c.解决1(废弃)
第1步,将文件夹名称更改为一个临时名称
第2步,再将其更改为你想要的小写名称
d.解决2(20250227实战)
第1步,备份Chapter01,并改名为chapter01
第2步,删除Chapter01,然后deploy.bat
第3步,放入chapter01,然后deploy.bat
f.报错6
a.问题
D:\software_ware\02.Directory02>git push Enumerating objects: 1265, done.
Counting objects: 100% (1265/1265), done. Delta compression using up to 8
threads Compressing objects: 100% (1264/1264), done. error: RPC failed;
HTTP 400 curl 22 The requested URL returned error: 400 Wsend-pack:
unexpected disconnect while reading sideband packet Writing objects:
100% (1264/1264), 443.93 MiB | 1.02 MiB/s, done. Total 1264 (delta 17),
reused 0 (delta 0), pack-reused 0 (from 0) fatal: the remote end hung
up unexpectedly Everything up-to-date
b.分析
文件大小限制:
远程仓库(如 GitHub、GitLab 等)通常对单个文件或整个推送的大小有一定的限制。
你提到的推送大小为 443.93 MiB,这可能超过了远程仓库的限制。
解决方案:检查远程仓库的文件大小限制,并考虑使用 Git LFS(Large File Storage)来管理大文件。
c.解决
我只是提交了某个文件夹,git add chapter01/,为什么同级目录的其他文件夹也添加到git了
重置暂存区:git reset
仅添加特定文件夹:git add chapter011/
检查状态:git status
提交更改:git commit -m "Add all contents of chapter011"
g.报错7
a.问题
D:\software_ware\02.Directory02>git status
On branch master
Your branch and 'origin/master' have diverged,
and have 2 and 1 different commits each, respectively.
(use "git pull" if you want to integrate the remote branch with yours)
nothing to commit, working tree clean
b.分析
当你看到“Your branch and 'origin/master' have diverged”时,
这意味着你的本地 master 分支和远程 origin/master 分支各自有不同的提交。
为了将它们合并,你需要将远程分支的更改合并到你的本地分支中,然后再推送合并后的结果。
c.解决
a.拉取远程更改并合并,使用--no-rebase选项来确保使用合并而不是变基
git pull --no-rebase origin master
b.解决合并冲突(如果有)
git add <conflicted-file>
git commit
c.推送合并后的更改
git push origin master
5.4 项目:管理/脱管,工作区/暂存区/对象区
00.汇总
| 主题 | 常用命令
|-----------|-------------------------------------------------------------
| 管理/脱管 | git init、git add、git rm、git clean、编辑.gitignore、rm -rf .git
| 查看状态 | git status、git diff、git diff --staged
| 添加和提交 | git add、git commit、git commit -am
| 撤销操作 | git restore、git checkout、git reset
| 查看历史 | git log、git show、git blame
| 回滚操作 | git reset、git revert
01.管理/脱管
a.管理
git init --将某个目录纳入Git管理
b.脱管
rm -rf .git --删除版本库(暂存区、对象区)
rm -rf * --删除当前目录中的全部文件(不包括隐藏文件)
rm -rf / --不要执行,会删除整个计算机中的全部文件
c.清理未跟踪文件
git clean -f --删除未被跟踪的文件
git clean -fd --删除未被跟踪的文件和目录
02.工作区/暂存区/对象区
a.创建/添加/提交
git add . --全部文件(符合git语法, .gitignore忽略文件不上传)
git add * --全部文件(不符合git语法, .gitignore忽略文件也会上传)
git add hello.txt --单个文件
git commit --提交,暂不写注释
git commit -m "xx" --提交,少量注释
git commit -am 'xx' --add同时commit,第一次创建文件,不能使用
b.本地工作区状态
git status --本地工作区状态
c.“暂存区” -> “工作区”:删除暂存区
git rm --cached hello.txt --方式一
git reset head world.txt --方式二
git restore --staged hello.txt --方式三
d.“对象区” -> “工作区”:修改文件后,需要再次重新提交
vi hello.txt
git add .
git commit
e.“对象区” -> “工作区”:不用退回工作区,可以放弃修改
git checkout -- hello.txt --方式一
git restore hello.txt --方式二
5.5 文件:添加、移动、重命名、删除、恢复、忽略、查看、比较、清理、回滚、提交点管理
00.汇总
| 操作类型 | 命令
|------------|-----------------------------------------------------
| 添加文件 | git add
| 移动文件 | git mv
| 重命名文件 | git mv
| 删除文件 | git rm、git rm --cached
| 恢复文件 | git restore、git checkout --
| 忽略文件 | 编辑 .gitignore 文件
| 查看状态 | git status、git diff
| 比较历史 | git log -- <file>、git blame
| 清理文件 | git clean -f、git clean -fd
| 回滚文件 | git reset --soft、git reset --mixed、git reset --hard
01.添加文件
a.将新文件添加到 Git 暂存区
git add <file>
git add . --添加当前目录下的所有文件
git add -A --添加工作区中所有的文件(包括删除和修改)
b.示例
git add README.md --添加单个文件
git add . --添加当前目录的所有文件
02.移动文件
a.将文件移动到新的位置
git mv <file> <new_location>
-----------------------------------------------------------------------------------------------------
等价于以下两步操作:第1步(手动重命名文件)
第2步(使用 git add 和 git rm 告知 Git 文件已被重命名)
b.示例
git mv src/main.java src/utils/main.java
03.重命名文件
a.Git重命名“对象区文件”
git mv hello.txt hello222.txt --重命名
git commit -m 'rename' --提交到"对象区"
-----------------------------------------------------------------------------------------------------
等价于以下两步操作:第1步(手动重命名文件)
第2步(使用 git add 和 git rm 告知 Git 文件已被重命名)
b.操作系统重命名“对象区文件”
mv hello2.txt hello22.txt --重命名
git add . --两个文件都添加到"暂存区"
git commit -m 'rename' --两个文件都提交到"对象区"
04.删除文件
a.Git删除“对象区文件”:彻底删除
git rm b.txt --删除至“暂存区”
git commit -m "彻底删除b" --commit删除指令至“对象区”
b.Git删除“对象区文件”:后悔删除操作
a.方式一
git rm world.txt --删除至“暂存区”
git restore --staged world.txt --恢复到“工作区”
git restore world.txt --撤销“delete”指令
b.方式二
git rm world.txt --删除至“暂存区”
git reset HEAD world.txt --恢复到“工作区”
git checkout -- world.txt --撤销“delete”指令
c.操作系统删除“对象区文件”
rm a.txt --删除文件后,被放到“工作区”
git add . --add至“暂存区”
git commit -m "彻底删除" --commit至“对象区”
05.恢复文件
a.恢复被修改的文件(从暂存区或上一次提交中恢复)
git restore <file>
git checkout -- <file> --Git 2.23+ 中推荐使用 `git restore` 替代
b.恢复被删除的文件
git checkout -- <file>
git restore <file>
06.忽略文件
a.通过 .gitignore 忽略文件
确保路径分隔符使用 / 而不是 \,因为 .gitignore 是跨平台的,只支持正斜杠 /
如果父目录(如 ydsz-boot-starter_1.0.0/ 或 ydsz-boot-aaaaaaa/)被忽略,Git 将不会处理子目录中的文件,即使有 ! 规则例外。
-------------------------------------------------------------------------------------------------
在 .gitignore 中,规则按顺序解析。为了让 ! 生效,确保其对应的文件已经被一个更广泛的忽略规则覆盖(例如 *.jar)
!ydsz-boot-starter_1.0.0/ydsz-boot-aaaaaaa/jeecg-boot-encrypt/*.jar
*.jar
这里的 *.jar 在 ! 规则之后,因此忽略了所有 .jar 文件,导致 ! 规则无效。
-------------------------------------------------------------------------------------------------
正确示例:
*.jar
!ydsz-boot-starter_1.0.0/ydsz-boot-aaaaaaa/jeecg-boot-encrypt/*.jar
-------------------------------------------------------------------------------------------------
检查父目录规则
git check-ignore -v ydsz-boot-starter_1.0.0/ydsz-boot-aaaaaaa/jeecg-boot-encrypt/codegenerate-1.4.3.jar
如果发现父目录被忽略,则需要取消忽略父目录。例如:
# 假设父目录被忽略
ydsz-boot-starter_1.0.0/
# 添加以下规则取消忽略父目录
!ydsz-boot-starter_1.0.0/
!ydsz-boot-starter_1.0.0/ydsz-boot-aaaaaaa/
!ydsz-boot-starter_1.0.0/ydsz-boot-aaaaaaa/jeecg-boot-encrypt/
b.应用忽略规则
git add .gitignore
git commit -m "Add .gitignore file"
c.脱离忽略规则
git rm -r --cached "build"
git rm -r --cached "**/.xcodemap"
git rm -r --cached "**/.xcodemap"
git rm -r --cached ".husky" && git rm -r --cached ".xcodemap"
-----------------------------------------------------------------------------------------------------
git rm -r --cached "Chapter01/Quick.assets/" --文件夹
git rm -r --cached ydsz-boot-starter-demo/lib/ydsz-module-system.jar --文件
d.检查文件是否被管理
git check-ignore -v build/ --文件夹
git check-ignore -v build/output.log --文件
-----------------------------------------------------------------------------------------------------
$ git rm -r --cached ydsz-boot-starter_1.0.0/ydsz-boot-aaaaaaa/
fatal: pathspec 'ydsz-boot-starter_1.0.0/ydsz-boot-aaaaaaa/' did not match any files
$ git check-ignore -v ydsz-boot-starter_1.0.0/ydsz-boot-aaaaaaa/jeecg-boot-encrypt/specific-file.jar
.gitignore:80:!ydsz-boot-starter_1.0.0/ydsz-boot-aaaaaaa/jeecg-boot-encrypt/*.jar ydsz-boot-starter_1.0.0/ydsz-boot-aaaaaaa/jeecg-boot-encrypt/specific-file.jar
-------------------------------------------------------------------------------------------------
git rm -r --cached 的错误提示表明 ydsz-boot-starter_1.0.0/ydsz-boot-aaaaaaa/ 并未被 Git 索引过,可能因为这个目录及文件从一开始就被 .gitignore 忽略。
git check-ignore 的结果显示 .gitignore 的排除规则已正确匹配(.gitignore 第 80 行的规则生效)
解决:未被git管理过,直接修改完.gitignore后,提交上传
e.全局忽略文件
touch ~/.gitignore_global
echo ".DS_Store" >> ~/.gitignore_global
git config --global core.excludesfile ~/.gitignore_global
07.查看文件状态
a.显示文件的状态
git status --查看文件状态:显示哪些文件已被修改、哪些文件未被跟踪、哪些文件已被暂存等
b.显示文件的差异
git diff --查看工作区和暂存区的差异
git diff --staged --查看暂存区和上一次提交的差异
08.比较文件历史
a.查看文件的修改历史
git log -- <file> --显示指定文件的提交历史
b.查看文件的每一行修改记录
git blame <file> --显示文件的每一行是由谁、在什么时候修改的
09.清理文件
a.删除未跟踪的文件
git clean -f
b.删除未跟踪的文件和目录
git clean -fd
10.回滚文件
a.git commit后未push,撤销commit操作
a.场景
修改了本地的代码,然后使用:
1、git add file
2、git commit -m ‘提交信息’
执行commit后,还没push到远程仓库时,想要撤销这次提交本地仓库的commit,该怎么办?
b.解决
git reset --soft HEAD"^":可成功撤销最近一次commit到本地仓库的提交,所有撤销的代码修改进入暂存区
git reset --hard HEAD"^":如果想要连着add也撤销的话,删除工作空间的改动代码,慎用
-------------------------------------------------------------------------------------------------
HEAD~ 表示上一个版本,即上一次的commit,也可以写成HEAD~1
如果进行两次的commit,想要都撤回,可以使用HEAD~2
--soft 不删除工作空间的改动代码 ,撤销commit,不撤销git add file
--hard 删除工作空间的改动代码,撤销commit且撤销add(慎用)
b.3种情况
a.回退最后一次提交到暂存区(已提交 -> 待提交)
git reset --soft HEAD"^" --Windows系统
git reset --soft HEAD^ --Linux/Mac系统
-------------------------------------------------------------------------------------------------
撤销最后一次 commit
保留文件修改
保留暂存区状态(文件仍然是 staged)
b.回退最后一次提交到工作区(已提交 -> 未暂存)
git reset HEAD"^" --Windows系统
git reset HEAD^ --Linux/Mac系统
-------------------------------------------------------------------------------------------------
撤销最后一次 commit
保留文件修改
清空暂存区(文件变成 unstaged)
c.取消暂存文件(待提交 -> 未暂存)
git reset HEAD <file> --取消暂存单个文件
git reset HEAD -- . --取消暂存所有文件
-------------------------------------------------------------------------------------------------
不影响 commit 历史
保留文件修改
将文件从暂存区移出(staged -> unstaged)
11.提交点管理
a.三种方式
a.git reset
永久删除提交、改变历史、危险操作
b.git revert
创建新提交、保雷历史、安全操作
c.git checkout
临时切换、不改变历史、查看专用
b.方式1:git reset(直接删除最近的两个提交点,需要使用 git push --force 更新远程)
a.假设当前分支有以下提交历史(HEAD 指向最新的提交)
A --- B --- C --- D --- E (HEAD)
b.操作
删除最近的两个提交点 D 和 E
c.回退到提交点C
git reset --hard HEAD~2
d.现在本地分支的提交历史变为:
A --- B --- C (HEAD)
e.强制推送到远程
git push --force
f.远程分支的提交历史也会同步更新为:
A --- B --- C (HEAD)
c.方式2:git revert(通过创建新的提交来撤销更改,不影响远程历史)
a.撤销最近的两个提交
git revert HEAD
git revert HEAD~1
b.推送到远程
git push
c.结果
通过 git revert,Git 会创建新的提交来撤销指定的提交,而不会删除提交历史。
原始提交历史(包括 D 和 E)仍然存在,但它们的内容被新的提交所撤销。
d.图示
| 操作 | 提交历史
|--------------|-----------------------------------------------
| 原始历史 | A --- B --- C --- D --- E (HEAD)
| 撤销 E | A --- B --- C --- D --- E --- E' (HEAD)
| 撤销 E 和 D | A --- B --- C --- D --- E --- E' --- D' (HEAD)
5.6 分支:查看、创建、切换、重命名、删除、跟踪、对比、回滚、同步、合并、变基
00.汇总
a.开发分支顺序
dev:开发分支,频繁改变
test:基本开发完毕后,交给测试实施人员的分支
master:生产阶段,很少变化
bugfix:临时修复bug分支
dev -> test (merge dev) -> master (merge test ) -> ....
b.连接成功会,git会产生一个新分支origin/master
git会在本地维护origin/master分支,通过该分支会感知远程github内容,origin/master一个只读分支,不建议修改
c.压缩(objects、refs中记录了很多commit的sha1值,如果执行gc,将多个sha1值存放到一个压缩文件中packed-refs)
git gc
d.没有“工作区”的工作仓库 ,存在于服务端
git init --bare
e.注释重写(重写提交说明)
git commit --amend -m '修正' --默认,修改最近一次的注释
f.忽略文件:.gitignore
dir/ --忽略dir目录中的所有文件
dir/*.txt
dir/*/*.txt
dir/**/*.txt: --任意级别目录
g.命令汇总
| 操作 | 作用 | 常用命令
|-----------|------------------------------------|------------------------------------------------------------------------------------------------
| 查看分支 | 列出本地和远程分支 | git branch、git branch -r、git branch -a
| 创建分支 | 创建新的分支 | git branch <branch_name>、git checkout -b <branch_name>、git switch -c <branch_name>
| 切换分支 | 切换到指定分支 | git checkout <branch_name>、git switch <branch_name>
| 重命名分支 | 修改分支名称 | git branch -m <new_name>、git branch -m <old_name> <new_name>
| 删除分支 | 删除本地或远程分支 | git branch -d <branch_name>、git branch -D <branch_name>、git push origin --delete <branch_name>
| 跟踪分支 | 设置本地分支与远程分支的跟踪关系 | git branch --set-upstream-to=origin/<remote_branch> <local_branch>
| 分支对比 | 查看两个分支之间的差异 | git diff <branch_1>..<branch_2>、git log <branch_1>..<branch_2>
| 分支回滚 | 将分支重置到特定提交点 | git reset --soft <commit_hash>、git reset --hard <commit_hash>
| 分支同步 | 更新本地分支以匹配远程分支的最新状态 | git pull、git fetch、git reset --hard origin/<branch_name>
01.查看分支
a.分类1
git branch --列出所有本地分支
git branch -r --列出所有远程分支
git branch -a --列出本地和远程分支
git branch -v --查看分支(sha1值)
git branch -av --查看分支(追踪分支)
b.分类2
git branch --show-current --显示当前所在的分支
02.创建分支
a.分类1
git branch <branch_name> --创建新分支,但不会切换到新分支
git checkout -b <branch_name> --创建新分支并切换到该分支
git switch -c <branch_name> --创建新分支并切换到该分支;同上,推荐使用
b.分类2
git branch <branch_name> <commit_hash> --基于特定提交创建分支
03.切换分支
a.分类1
git checkout <branch_name> --切换到指定分支
git switch <branch_name> --推荐使用,从 Git 2.23 开始支持
b.分类2
git checkout <commit_hash> --切换到特定提交(游离状态)
04.重命名分支
a.分类1
git branch -m <new_name> --重命名当前分支
git branch -m <old_name> <new_name> --重命名指定分支
b.分类2
git push origin -u <new_name> --推送新名称到远程
git push origin --delete <old_name> --删除旧分支名称
05.删除分支
a.建议,删除分支前合并:分支A进行写操作,仅在"对象区"
a.在master分支,删除new_branch,报错:new_branch还没有合并
git branch -d new_branch
b.将new_branch增加/删除的操作合并到master主分支,保护分支中修改的文件,短的分支点"合并"长的分支点
git merge new_branch
c.合并后,再次删除new_branch分支
git branch -d new_branch
b.操作
a.第1步“删除本地分支
git branch -d <branch_name> --安全删除(如果分支未完全合并会报错)
git branch -D <branch_name> --强制删除(即使分支未合并也会删除)
b.第2步:删除远程分支
git push origin --delete <branch_name> --简写:git push origin :<branch_name>
git push origin --delete dev --实战:20250324
c.综合命令:一次性删除本地和远程分支的组合命令
git branch -d <branch_name> && git push origin --delete <branch_name>
c.注意事项
a.第1点
删除分支前确保你不在要删除的分支上(先切换到其他分支)
b.第2点
其他人也需要更新他们的本地仓库,他们需要运行 git fetch --all --prune 同步远程分支的删除信息
06.跟踪分支
a.介绍
设置本地分支与远程分支之间的跟踪关系
b.命令
git branch --set-upstream-to=origin/<remote_branch> <local_branch>
git clone <repository_url> --克隆仓库时自动设置跟踪
git branch -vv --查看跟踪分支
07.分支对比
a.介绍
比较两个分支之间的差异
b.命令
git diff <branch_1>..<branch_2> --比较两个分支的差异
git diff origin/<branch_name> --查看当前分支与远程分支的差异
git log <branch_1>..<branch_2> --查看分支提交差异
08.分支回滚
a.介绍
将分支重置到特定的提交点
b.命令
git reset --soft <commit_hash> --回滚到指定提交:保留工作区和暂存区更改
git reset --mixed <commit_hash> --回滚到指定提交:保留工作区更改
git reset --hard <commit_hash> --回滚到指定提交:丢弃所有更改
git push --force --如果已经推送到远程,需要强制推送
09.分支同步
a.介绍
更新本地分支以匹配远程分支的最新状态
b.命令
git pull --拉取并合并远程分支
git pull --rebase --拉取远程分支并变基
git fetch --仅拉取远程分支更新,不合并
git merge origin/<branch_name> --手动合并远程分支
git reset --hard origin/<branch_name> --强制同步远程分支
5.7 pull拉取
01.git pull = git fetch + git merge
a.clone
git clone [email protected]:wohenguaii/git2020.git mygit2
b.pull
a.原理
pull/push:推送、改变origin/master指针
Fast-forward:更新,如果发现更新的内容比自己先一步(commit的sh1值在自己之前),则会自动合并
b.本地分支与远程分支的冲突问题
git pull = git fetch + git merge
git pull --rebase = git fetch + git rebase
c.说明
git config --global pull.rebase true --使pull命令变成rebase而不是merge
git config --global branch.autosetuprebase always --自动对所有新建分支都配置成rebase方式
02.git pull --rebase = git fetch + git rebase
a.场景
假设有3次提交A,B,C
在远程分支origin的基础上创建一个名为"mywork"的分支并提交了,同时有其他人在"origin"上做了一些修改并提交了。
其实这个时候E不应该提交,因为提交后会发生冲突。
b.方法1:git merge
用git pull将"origin"分支上的修改pull下来与本地提交合并(merge)成版本M,但这样会形成图中的菱形,让人很困惑。
c.方法2:git rebase
创建一个新的提交R,R的文件内容和上面M的一样,但我们将E提交废除,当它不存在(图中用虚线表示)。
由于这种删除,小李不应该push其他的repository.rebase的好处是避免了菱形的产生,保持提交曲线为直线,让大家易于理解。
-----------------------------------------------------------------------------------------------------
在rebase的过程中,有时也会有conflict,这时Git会停止rebase并让用户去解决冲突,
解决完冲突后,用git add命令去更新这些内容,然后不用执行git-commit,
直接执行git rebase --continue,这样git会继续apply余下的补丁。
在任何时候,都可以用git rebase --abort参数来终止rebase的行动,并且mywork分支会回到rebase开始前的状态。
5.8 push推送
01.配置地址
a.方式一:直接修改本地仓库所关联的远程仓库的地址
git remote --查看远程仓库名称:origin
git remote get-url origin --查看远程仓库地址
git remote set-url origin [url] --【设置新的远程URL】
b.方式二:命令修改,先删除后添加新地址
git remote -v --查看git对应的远程仓库地址
git remote rm origin --删除
-------------------------------------------------------------------------------------------------
git remote -v --查看git对应的远程仓库地址
git remote add origin [url] --添加
c.方式三:直接修改配置文件
vi .git/config
-------------------------------------------------------------------------------------------------
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
[remote "origin"]
url = http://【更新的地址】 --修改此处
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
02.远程分支
a.查看远程服务器的信息
a.本地工作区状态
git status
b.远程服务器的信息:
git remote show --查看有哪些远程服务器
git remote show origin --查看origin
b.查看远程分支的日志
a.本地日志
git reflog
git log
b.远程日志
git log origin/master
git log remotes/origin/master
git log refs/remotes/origin/master
c.查看远程分支的状态
git branch --查看分支
git branch -a --查看分支
git branch -v --查看分支(sha1值)
git branch -av --查看分支(追踪分支)
d.删除远程分支
a.删除本地分支:
git branch -D new_branch2
b.删除远程分支:
git push origin :test --方式一
git push origin --delete dev --方式二
e.删除无效的追踪分支
a.场景
本地没有a分支,但本地却感知远端的a分支
b.检测
git remote prune origin --dry-run
c.清理无效的追踪分支(本地中感知的远程分支)
git remote prune origin
f.其他操作
a.感知远程分支的配置文件
git fetch origin master:refs/remotes/origin/helloworld
b.给checkout命令起别名
git config --global alias.ch checkout
03.上传分支1
c.操作1:本地分支与远程分支的手动关联操作
a.本地分支 -> 追踪分支 -> 远程分支
a.创建新分支
git checkout -b dev
b.远程分支 -> 追踪分支 -> 本地分支
git push -u origin dev --方式一:Push推送,同时dev分支手动关联origin分支
git push --set-upstream origin dev --方式二
b.远程分支 -> 追踪分支 -> 本地分支
a.远程分支 -> 追踪分支
git pull,可以将远端分支更新到本地origin/xxxx,但是不会再创建本地分支
b.追踪分支 -> 本地分支
git checkout -b dev origin/dev --方式一:创建并切换dev新分支,dev手动关联origin
git checkout -b test --track origin/test --方式二
git checkout --track origin/test --方式三
d.操作2:本地分支与远程分支的自动关联操作
a.Push推送 + 创建本地新分支 + 分支自动关联
a.创建本地新分支
git checkout -b ccc
b.Push推送 + 分支自动关联
git push origin ccc:ccc2 或 git push origin HEAD:ccc2
b.Pull拉取 + 创建本地新分支+ 分支自动关联
git pull origin ccc2:ccc3
04.上传分支2
a.方式一:本地初始化一个仓库,设置远程仓库地址后再做push(推荐)
a.创建本地仓库、远程仓库
git init --创建本地仓库
[email protected]:im_very_strange/blog.git --创建远程仓库
b.关联本地仓库与远程仓库地址
git remote add origin [email protected]:im_very_strange/blog.git
c.保留线上的readme文件(如果本地分支版本大于远程版本,则强制提交)
git pull origin master
d.关联本地分支与远程分支地址
git add .
git commit -m "my first commit"
git push origin master -f --强制提交:舍弃线上文件进行强制推送(不推荐)
git push origin master --正常提交:保留线上的readme文件
b.方式二:先将仓库clone到本地,修改后再push到Gitee的仓库
a.克隆仓库到本地
git clone [email protected]:im_very_strange/blog.git mygit2
b.关联本地仓库与远程仓库地址
无
c.保留线上的readme文件
无
c.关联本地分支与远程分支地址
git add .
git commit -m "my first commit"
git push origin master --正常提交:保留线上的readme文件
05.上传分支3
a.方式1:克隆远程后,再覆盖本地.git文件夹
a.第1步
github -> Create a new repository
b.第2步
git clone https://github.com/halavah/xxx.git
c.第3步
xxx的.git文件夹 -> 04.Directory04的根目录 -> git pull origin master 或 git pull --force origin master
b.方式2:本地仓库关联远程仓库
a.命令操作
a.步骤1:create a new repository on the command line
echo "# vilgoboot" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M master
git remote add origin https://github.com/halavah/vilgoboot.git
git push -u origin master
b.步骤2:push an existing repository from the command line
git remote add origin https://github.com/halavah/vilgoboot.git
git branch -M master
git push -u origin master
b.文字操作
a.步骤1: 确认旧项目未初始化 Git
打开旧项目目录,确认是否有 .git 文件夹。
如果有 .git 文件夹,说明项目已经是一个 Git 仓库,可以直接关联到新的远程仓库(跳到 步骤 3)。
如果没有 .git 文件夹,继续下一步。
b.步骤2: 初始化 Git 仓库
进入你的项目目录:cd <旧项目目录>
初始化 Git 仓库:git init
添加项目文件到 Git 的暂存区:git add .
提交文件到本地仓库:git commit -m "Initial commit"
c.步骤3: 创建远程仓库
登录你的 Git 托管平台(如 GitHub、GitLab 或 Gitee)。
创建一个新的空仓库,不需要添加 README 文件或任何其他内容。
复制新仓库的 HTTPS 或 SSH URL。
d.步骤4: 关联远程仓库
替换新远程仓库地址:git remote set-url origin https://github.com/username/new-repo.git
关联到新的远程仓库:git remote remove origin && git remote add origin https://github.com/username/new-repo.git
验证是否关联成功:git remote -v
e.步骤5: 推送代码到远程仓库
如果你的默认分支是 master 而不是 main,则使用:git push -u origin master
如果远程仓库已有内容并需要合并,可能需要先拉取远程分支:git pull origin main --allow-unrelated-histories
然后再推送:git push origin master
6 git
6.1 tag标签
00.总结
a.说明1
在 Git 中,tag 是全局的,不属于某个具体的分支。
也就是说,无论你是在 master 分支还是 dev 分支上创建 tag,这些 tag 都是属于整个仓库的,而不是特定分支。
因此,如果你在 dev 分支上创建了一个与 master 分支上已有的标签同名的 tag,就会产生冲突。
b.说明2
tag 是全局唯一的
你不能在不同的分支上创建同名的 tag,否则会报错,例如:
git tag v1.0
git tag v1.0 # 再次创建同名的 tag 会失败
c.如何避免冲突?
使用唯一命名的 tag,比如添加分支前缀:
在 master 分支上:master-v1.0
在 dev 分支上:dev-v1.0
或者使用特定的版本号规则
01.创建标签
a.简单标签,只存储当前的commit的sha1值
git tag v1.0 v1.0 : 8c3512547
b.(创建一个新对象,会产生一个新的commit/sha1)存储信息,其中包含了当前的commit的sha1值
git tag -a v1.0 -m 'release Tag' v2.0 : 61fb09fd(8c3512547)
02.查看标签
git tag -d v1.0 --删除标签
git tag --查看所有标签
git tag -l 'v*' --查看标签,模糊查询
git show v1.0 --查看标签v1.0
03.推送标签
git push origin v1.0 --推送标签
git push origin v1.0 v2.0 --推送多个标签
git push origin --tags --推送全部标签
git push origin refs/tags/v1.0:refs/tags/v1.0 --推送标签,完整写法
04.拉取标签
a.如果远端新增标签,则pull可以将新增的标签拉取到本地;如果远程是删除标签,则pull无法感知
git pull --拉取全部,包括全部标签,
b.只拉取标签
git fetch orgin tag v4.0
c.删除标签,注意:如果将远程标签删除,其他用户无法直接感知
git push origin v1.0
git push origin :refs/tags/v1.0
c.一次性删除本地和远程标签的组合命令
git tag -d v1.0.0 && git push origin --delete tag v1.0.0
05.删除标签
a.删除本地标签
git tag -d <tag_name> # 删除单个标签
# 或
git tag -d $(git tag -l) # 删除所有本地标签
b.删除远程标签
git push origin --delete tag <tag_name> # 方式1
# 或
git push origin :refs/tags/<tag_name> # 方式2
c.一次性删除本地和远程标签的组合命令
git tag -d <tag_name> && git push origin --delete tag <tag_name>
d.批量删除远程标签
# 删除所有远程标签
git push origin --delete $(git tag -l)
# 或
git push origin --delete refs/tags/*
e.注意事项
删除标签前建议先备份或确认标签信息
删除远程标签后,其他开发者需要运行 git fetch --prune-tags 来同步删除信息
标签删除后无法恢复,请谨慎操作
f.如果其他人也需要更新他们的本地仓库,他们需要运行
git fetch --all --prune-tags # 同步远程标签的删除信息
6.2 diff差异性
01.操作系统:diff比较的是文件本身
a.比较(A为参照,对比B)
diff a.txt b.txt
diff -u a.txt b.txt
b.比较结果
@@ -4,4 +4,6 @@
4:从第4行开始
6:比较6行
-:原文件
+:对比的文件
c.显示文件的差异
git diff --查看工作区和暂存区的差异
git diff --staged --查看暂存区和上一次提交的差异
02.常见命令
a.比较区中文件,暂存区为参照,对比工作区
git diff --暂存区为参照,对比工作区
b.比较区中文件,对象区为参照,对比工作区
git diff commit的sha1值 --对象区为参照,对比工作区
c.比较区中文件,"最新"对象区为参照,对比工作区
git diff commit的sha1值 --"最新"对象区为参照,对比工作区
git diff head --"最新"对象区为参照,对比工作区
d.比较区中文件,对象区为参照,对比暂存区
git diff --cached commit的sha1值 --对象区为参照,对比暂存区
e.对比区中文件,"最新"对象区为参照,对比暂存区
git diff --cached commit的sha1值 --"最新"对象区为参照,对比暂存区
git diff --cached HEAD --"最新"对象区为参照,对比暂存区
6.3 subtree双向
00.说明
a.介绍
subtree 是 Git 中的一种子仓库管理方式,允许你将一个子项目的代码直接嵌入到主仓库中。
子项目的代码实际上是主仓库的一部分,但保留了子项目的独立性,可以从子项目仓库中拉取更新或推送更改。
b.优点
子项目的代码直接嵌入主仓库,易于管理。
支持双向同步,子项目和主项目的代码可以相互更新。
不需要额外的初始化或依赖(如 git submodule 需要手动初始化)。
c.缺点
操作可能稍显复杂(需要指定路径和子仓库地址)。
如果子项目的规模很大,可能会导致主仓库的历史记录变得庞大。
d.双向操作的含义
双向操作 指的是,subtree 支持:
从主仓库推送更改到子仓库。
从子仓库拉取更新到主仓库。
这意味着主仓库和子仓库之间的代码可以自由同步。
01.基础知识
a.准备本地仓库parent和subtree,远程仓库parent和subtree
a.仓库parent的连接:
第一次:关联本地仓库与远程仓库地址
git remote add origin [email protected]:wohenguaii/parent.git
第二次:关联本地分支与远程分支地址
git push -u origin master
b.仓库subtree的连接:
第一次:关联本地仓库与远程仓库地址
git remote add origin [email protected]:wohenguaii/subtree.git
第二次:关联本地分支与远程分支地址
git push -u origin master
b.父子工程建立联系
a.父工程(parent)
a.给远程仓库起名字
git remote add subtree-origin [email protected]:wohenguaii/subtree.git
b.第一种方式:父工程添加子工程subtree1
git subtree add -P subtree subtree-origin master
等价于git subtree add --prefix subtree subtree-origin master
c.第二种方式:父工程添加子工程subtree2
git subtree add -P subtree2 subtree-origin master --squash
b.修改子工程 -> 父工程(subtree pull,修改子工程中的内容,GitHub同步子工程内容更新成功)
a.修改子工程并推送
vi -> add -> commit -> push
b.(本地)将GitHub中的子工程 更新到 父中子模块
git subtree pull -P subtree subtree-origin master
c.父中子模块的更新情况 推送到 对应GitHub的父工程上
git push
c.修改父工程中子模块 -> 子工程
a.常规push,修改本地父工程中子模块,会使GitHub对应父工程中子模块更新成功,但真正的子工程未更新
git push
b.subtree push,修改本地父工程中子模块,不经过GitHub对应父工程中子模块,直接推送到真正的子模块
git subtree push -P subtree subtree-origin master
d.squash的使用
是否修改同一行、是否同一祖先;squash要么都加,要么都不加;squash只加一边,容易造成冲突
02.实战操作(定)
a.添加子仓库
git subtree add --prefix=<子目录> <子仓库地址> <分支>
b.从子仓库拉取更新
git subtree pull --prefix=<子目录> <子仓库地址> <分支>
c.推送主仓库的更改到子仓库
git subtree push --prefix=<子目录> <子仓库地址> <分支>
6.4 submodule单向
01.基础知识
a.准备本地仓库A和B,远程仓库A和B(submodule:子模块;应用场景:在一个仓库中引用另一个仓库的代码)
a.仓库A的连接:
第一次:关联本地仓库与远程仓库地址
git remote add origin [email protected]:wohenguaii/A.git
第二次:关联本地分支与远程分支地址
git push -u origin master
给当前仓库A配置邮箱、地址:
git config --local user.name '我很怪i'
git config --local user.email '[email protected]'
b.仓库B的连接
第一次:关联本地仓库与远程仓库地址
git remote add origin [email protected]:wohenguaii/B.git
第二次:关联本地分支与远程分支地址
git push -u origin master
给当前仓库B配置邮箱、地址:
git config --local user.name '我很萌i'
git config --local user.email '[email protected]'
b.submodule:在A仓库中引用B仓库
a.本地仓库:在A仓库中引用B仓库
git submodule add [email protected]:wohenguaii/B.git
b.推送给远程仓库
git add .
git commit -m '加入B库'
git push
c.A中有B,但B库修改并Push之后,A库无法直接感知,A库需要主动Pull
a.进入A/B中pull到本地,并在A中同步push到远程
a.进入A/B中pull到本地
git pull
b.在A中同步push到远程
git add .
git commit -m 'xx'
git push
b.直接在A中迭代pull到本地,并在A中同步push到远程
a.直接在A中迭代pull到本地,一次性搞定多个
git submodule foreach git pull
b.在A中同步push到远程
git add .
git commit -m 'xx'
git push
d.clone(A库含B库),如果clone的项目包含submodule,则clone方法
git clone [email protected]:wohenguaii/A.git --recursive
e.删除B库,并同步到远程
a.删除暂存区,“暂存区”退回"工作区"
git rm --cached B
b.删除对象区(操作系统删除)
rm -rf B
rm -rf .gitmodules
删除对象区,退回工作区,需要重新提交
git add .
git commit -m '删除'
c.同步到远程
git push
02.实战操作(定)
a.查看子模块列表
git submodule status
1234567 content (heads/main)
b.查看子模块配置
a.查看配置1:.gitmodules
cat .gitmodules
[submodule "content"]
path = content
url = https://github.com/halavah/Directory01.git
-------------------------------------------------------------------------------------------------
path 表示子模块在主仓库中的路径。
url 是子模块的远程仓库地址。
b.查看配置2:.git/config
cat .git/config
[submodule "content"]
url = https://github.com/halavah/01.Directory01.git
-------------------------------------------------------------------------------------------------
如果仍然是旧的 URL,手动修改为:
[submodule "content"]
url = https://github.com/halavah/Directory01.git
c.查看配置3:检查子模块自身的Git配置
cd content
git remote -v
-------------------------------------------------------------------------------------------------
如果显示错误的 URL,使用以下命令修正:
git remote set-url origin https://github.com/halavah/Directory01.git
c.操作子模块
a.删除原子模块
rm -rf content
rm -rf .git/modules/content --清理缓存的错误配置
git submodule deinit -f content
b.重新使用已存在的content目录
git submodule add --force https://github.com/halavah/Directory01.git content
git submodule add --force -b master https://github.com/halavah/Directory01.git content --指定分支
git submodule add --force [email protected]:halavah/Directory02.git content
-------------------------------------------------------------------------------------------------
使用 --force 强制添加子模块
c.同步子模块
git submodule sync
git submodule update --init --recursive
git submodule update --remote
git submodule update --remote --merge --忽略子模块的当前状态,强制更新
git submodule update --force --recursive --init --remote --建议该版本
-------------------------------------------------------------------------------------------------
stackoverflow执行顺序
git submodule update --init --recursive
git pull --rebase --recurse-submodules
git submodule update --force --recursive --init --remote
git submodule sync
git submodule update --init --recursivevercel-submodule-workaround
d.提交更改
git add .gitmodules content
git commit -m "Add content as submodule"
git commit -m "Update submodule content to the latest version"
git push origin master
e.还可以尝试如下操作
由于本地.git配置有问题,但是origin没有问题
rm -rf content,提交代码后,删除本地仓库,从origin拉取新的代码
6.5 [0]codekit:汇总
01.五种合并
a.merge:合并
a.场景
适用于:希望保留完整历史记录,特别是在团队协作中。
优点:保留了分支的历史,操作简单。
缺点:可能会导致历史记录复杂,特别是在频繁合并的情况下。
-------------------------------------------------------------------------------------------------
"将传入变更合并到当前分支" 指的是将一个分支的更改与当前分支的更改合并在一起。
这将在两个分支的更改之间创建一个合并节点,以维护它们之间的关系。
如果在合并过程中出现冲突,则需要解决这些冲突,然后再提交合并。
b.命令
# 1.普通方式
git checkout master # 切换到master分支
git merge dev # 将dev分支合并到当前分支(master)
-------------------------------------------------------------------------------------------------
# 2.--no-ff方式合并(保留分支信息)
git checkout master
git merge --no-ff dev # 创建一个新的合并提交
b.rebase:变基
a.场景
适用于:希望保持线性的提交历史,使项目历史更清晰。
优点:产生一个更清晰的项目历史。
缺点:改变了项目历史,如果在共享分支上使用需要团队协调。
-------------------------------------------------------------------------------------------------
"在传入变更上变基当前分支" 指的是将当前分支的历史更改“重构”为基于另一个分支的更改。
这样做将导致当前分支的历史记录发生变化,从而对其他分支造成影响。
在选择这种方法时,需要谨慎考虑,因为它可能破坏其他人的工作。
b.命令
# 1. 在dev分支上rebase
git checkout dev
git rebase master
git checkout master
git merge dev
-------------------------------------------------------------------------------------------------
# 2. 或直接在master分支上操作
git checkout master
git rebase dev
c.cherry-pick:选择性合并
a.场景
适用于:只需要合并特定的几个提交,而不是整个分支。
优点:非常灵活,可以精确控制要合并的内容。
缺点:如果需要合并的提交较多,操作可能会比较繁琐。
b.命令
# 如果只想合并dev分支上的某些特定提交
git checkout master
git cherry-pick <commit-hash> # 合并特定的提交
git cherry-pick A..B # 合并一系列连续的提交
d.patch:补丁
a.场景
适用于:需要通过邮件或其他方式共享代码修改,或在没有直接仓库访问权限的情况下。
适用于:通过补丁操作,可以高效地管理跨分支或跨仓库的代码变更
优点:可以在离线环境下工作,便于代码审查。
缺点:对于大量修改可能不太方便。
b.命令
# 在dev分支创建补丁
git checkout dev
git format-patch master -o patches/ # 创建补丁文件
-------------------------------------------------------------------------------------------------
# 在master分支应用补丁
git checkout master
git am patches/*.patch # 应用补丁
e.stash:暂存区
a.场景
适用于:临时需要切换分支,但又不想提交半成品代码的情况。
优点:操作简单,可以快速切换上下文。
缺点:不适合长期存储或复杂的修改管理。
b.命令
# 在dev分支
git stash # 暂存修改
git checkout master
git stash pop # 在master应用暂存的修改
git add .
git commit -m "apply changes from dev"
02.Rebase和Merge区别
a.事故现场还原
a.场景描述
你在 feature 分支上开发新功能,同事在 main 分支上修了一个紧急 bug。
提交历史如下:
main: A --- B --- C (bug 修复)
\
feature: D --- E (你的新功能)
使用 git rebase main 的操作:
git checkout feature
git rebase main
b.rebase 后的结果
main: A --- B --- C
\
feature: D' --- E'
c.可能踩的坑
如果本地 feature 分支没有先拉取同事的最新提交,或者在 rebase 过程处理中手滑丢掉了同事的改动时,push 到远程之后会直接覆盖远程历史,导致同事的代码消失。
b.rebase 和 merge 的区别
a.git merge —— 历史完整,简单安全
a.特点
1.会创建一个新的 merge commit。
2.不会改动已有提交历史。
3.适合多人协作,需要保留所有分支的提交轨迹。
b.示例操作
git checkout feature
git merge main
c.结果展示
A --- B --- C ------ M (merge commit)
\ /
D --- E -----
d.特性总结
1.提交历史可能“分叉”较多,但安全。
2.解决冲突只发生一次。
b.git rebase —— 历史干净,但会改动历史
a.特点
1.会把当前分支的提交“搬到”目标分支的最新提交之后。
2.会生成新的提交 ID,即使内容相同。
3.适合本地分支整理历史,但不要在公共分支上随意使用。
b.示例操作
git checkout feature
git rebase main
c.结果展示
A --- B --- C --- D' --- E'
d.特性总结
1.历史简洁、一条直线,干净美观。
2.改动提交历史可能导致冲突甚至丢失代码,尤其是在已经 push 后被别人基于此开发的情况下。
c.各自的安全使用场景
a.本地分支开发,还没 push 给别人
推荐方式:rebase
原因:整理历史,方便以后合并。
b.拉取远程更新并保持历史干净
推荐方式:pull --rebase
原因:避免多余的 merge commit。
c.已经 push,且有同事基于此分支开发
推荐方式:merge
原因:避免改写历史,减少冲突。
d.大型团队的主分支合并
推荐方式:merge
原因:保留历史,方便追溯。
e.个人项目或短期功能分支
推荐方式:rebase
原因:使历史整洁且美观。
d.避免 rebase 导致代码丢失的方法
a.公共分支上避免使用 rebase
不建议对公共分支(例如 main、dev)使用 rebase。
b.确保拉取远程最新代码
示例操作:
git fetch origin
git rebase origin/main
c.解决冲突时仔细检查
确保同事的提交没有被覆盖。
d.rebase 出错时使用回退命令
可使用以下命令:
git rebase --abort
e.推送前检查差异
养成以下习惯:
git log --oneline --graph --decorate
git diff
e.经验总结
a.关于 merge
merge 像是在账本上追加记录,不动旧账,安全可靠。
b.关于 rebase
rebase 像是改账本,让账单更漂亮,但改错了可能让账本混乱。
c.团队协作建议
在公共分支上使用 merge,在本地分支上使用 rebase,基本上可以避免大部分事故。
6.6 [1]merge:合并
00.汇总
a.基本类型
a.Fast-forward 合并
这种合并方式在目标分支没有新的提交时,将目标分支的 HEAD 指针直接移动到源分支的最新提交。
不会创建新的合并提交。
使用场景:目标分支完全落后于源分支时。
b.非 Fast-forward 合并
这种合并方式会创建一个新的合并提交,即使可以通过 Fast-forward 合并。
保留了分支的分叉和合并历史。
使用场景:需要保留分支信息,或合并多个特性分支。
b.常用选项
a.--no-ff
git merge --no-ff dev
-------------------------------------------------------------------------------------------------
强制进行非 Fast-forward 合并,即使可以 Fast-forward。
保留了分支的历史,创建一个新的合并提交。
b.--squash
git merge --squash dev
git commit -m "Squashed commit message"
-------------------------------------------------------------------------------------------------
合并但不自动创建合并提交,将所有提交压缩成一个。
使用场景:希望将多个提交合并为一个提交进行提交。
c.--abort
git merge --abort
-------------------------------------------------------------------------------------------------
在合并冲突后,放弃合并,恢复到合并前的状态。
c.合并策略
a.ours
git merge -s ours dev
-------------------------------------------------------------------------------------------------
选择当前分支的更改,忽略被合并分支的更改。
b.theirs
选择被合并分支的更改,忽略当前分支的更改。
需要在解决冲突时手动应用。
c.recursive
默认合并策略,适用于两条分支有共同祖先的情况。
支持三方合并
01.两种情况
a.图示
A---B---C (master)
\ /
D---E (dev)
-----------------------------------------------------------------------------------------------------
保留所有分支信息,可能会形成菱形结构
b.情况1:合并不冲突
a.merge时,默认fast-forward,丢失分支信息(短追长,查看短master的分支信息)
master短,dev长,短追长,则在master中,使用git merge dev
b.merge时,禁止git merge --no-ff dev,分支信息完整(短追长,查看短master的分支信息)
master短,dev长,短追长,禁长,则在master中,使用禁止git merge --no-ff dev
c.不禁止/禁止--no-ff,对比图
merge时,git merge dev,丢失分支信息(短追长,查看短master的分支信息)
merge时,禁止git merge --no-ff dev,分支信息完整(短追长,查看短master的分支信息)
c.情况2:合并冲突
a.修改冲突:修改文件、add、commit
vi修改文件
git add . --告知git,冲突已解决,此时add不代表在工作区,是标志
git commit -m 'xx'
b.修改冲突后,再次进行合并,不会发生冲突
git checkout dev --切换到dev分支
git merge master --合并到master分支
02.处理合并冲突
a.查看冲突文件:
在合并冲突时,Git 会在冲突的文件中标记冲突区域。
可以使用文本编辑器(如 vi、nano)打开文件进行手动解决。
b.解决冲突步骤:
编辑冲突文件,手动解决冲突。
使用 git add <file> 标记冲突已解决。
使用 git commit 完成合并提交。
c.冲突文件标记示例
<<<<<<< HEAD
当前分支的内容
=======
被合并分支的内容
>>>>>>> dev
03.从远程 master 分支拉取最新更改,然后提交到远程的 dev_troyekk 分支
a.切换到本地 dev_troyekk 分支
git checkout dev_troyekk
b.拉取远程 master 分支的更改,在本地 dev_troyekk 分支上,将远程 master 分支的更改合并到当前分支
git pull origin master
这将把 origin 远程仓库中的 master 分支的更改拉取下来,并合并到当前的 dev_troyekk 分支。
c.解决合并冲突(如果有)
1.打开冲突文件并手动编辑,解决冲突标记(<<<<<<, ======, >>>>>>)。
2.标记冲突已解决并更新暂存区:git add <file_with_conflicts>
3.一旦所有冲突解决,完成合并:git commit -m "Merge master into dev_troyekk"
4.将合并后的更改推送到远程的 dev_troyekk 分支:git push origin dev_troyekk
6.7 [2]rebase:变基
00.汇总
a.reabase分支在本机操作,不要推送GitHub,不要在master上直接rebase
a.远程分支的变基
如果本地分支已经推送到远程,且在远程有其他人基于此分支进行开发,使用 rebase 可能会导致他人本地分支失效。
避免直接对远程分支进行变基:变基会重写提交历史,导致远程和本地分支的提交不一致。
解决方案:如果需要变基,建议使用 git pull --rebase 拉取远程分支的最新提交,然后再进行变基操作。
b.本地开发分支推荐使用 rebase
在本地开发过程中,为了保持提交历史整洁,可以使用 rebase 代替 merge。
c.变基时谨慎操作公共分支
变基适用于个人分支,不推荐对公共分支(如 master 或 main)进行变基。
b.可以在任意分支下,指定从 dev分支 变基到 master分支 吗?不能
a.回答
不能
b.原因
Git 的 rebase 命令是基于当前分支执行的,不能直接通过 git rebase 指定从一个分支变基到另一个分支。
因此,无法在不切换到目标分支的情况下直接指定从某个分支变基到另一个分支。
c.正确操作
git rebase 操作始终是以当前分支为基准进行的。
直接指定从一个分支变基到另一个分支的功能在 git rebase 中是不可行的,你需要切换到需要变基的目标分支来进行操作。
使用 git checkout 切换分支后再执行 rebase 是最常见和标准的操作方式。
c.其他命令
a.忽略冲突
# 放弃rebase所在分支的修改,直接使用其他分支
git rebase --skip
b.还原rebase之前的场景
git rebase --abort
01.两种情况
a.图示
A---B---C---D'---E' (dev)
-----------------------------------------------------------------------------------------------------
将提交历史线性化,避免菱形结构,使历史更加简洁易读
b.情况1:变基不冲突
a.普通变基(无冲突)
a.描述
使用 git rebase 时,将当前分支的提交从目标分支的最新提交开始重新应用,形成线性提交历史。
b.操作:短分支追长分支
git checkout dev # 切换到 dev 分支
git rebase master # 将 dev 分支基于 master 的最新提交进行变基
效果:历史提交变为线性,不产生新的合并提交(与 merge 的 fast-forward 效果类似)。
b.禁止自动应用,手动控制每次提交的变基
a.描述
使用 git rebase -i(交互式变基),可以手动选择哪些提交需要保留、修改或合并。
b.操作
git checkout dev # 切换到 dev 分支
git rebase -i master # 基于 master 进行交互式变基
c.交互式变基窗口说明:
pick:保留该提交(默认选项)。
reword:修改提交信息。
edit:修改提交内容。
squash:将当前提交与上一个提交合并。
drop:删除该提交。
c.情况2:变基冲突
a.解决冲突
a.描述
在变基过程中,如果两个分支的提交修改了相同的文件,可能会发生冲突。
b.操作
1.当冲突发生时,Git 会停止变基,并提示冲突文件。
2.手动修改冲突的文件:vi <冲突文件>
3.标记冲突已解决:git add <冲突文件>
4.继续变基:git rebase --continue
5.如果放弃变基,可以使用:git rebase --abort
c.操作
git checkout dev
git rebase master
# 发生冲突
vi <冲突文件>
git add <冲突文件>
git rebase --continue
b.冲突解决后,变基不会重复产生冲突
a.描述
冲突解决后,Git 会记录冲突的解决状态,变基完成后,不会再次触发相同的冲突。
b.操作
git checkout dev
git rebase master
02.交互模式
a.图示
| 功能 | git rebase master | git rebase -i master
|----------|-------------------------------------|-----------------------
| 交互性 | 非交互式,自动变基 | 交互式,允许用户自定义操作
| 操作粒度 | 提交按时间顺序自动重新应用 | 可以修改提交顺序、合并提交、修改提交信息等
| 适用场景 | 简单地将当前分支基于目标分支的最新提交 | 整理提交历史,优化提交记录,清理无用的提交
| 复杂性 | 简单,自动完成 | 需要用户手动干预
| 结果 | 提交历史线性化,保持原有提交顺序 | 提交历史线性化,提交顺序、内容可能被调整
b.git rebase master
a.非交互式变基
这是普通的变基操作。
会将当前分支的提交,基于 master 分支的最新提交重新应用。
提交历史会被自动重新排列,按照提交的时间顺序应用,不需要用户参与操作。
b.适用场景
当你只需要简单地把当前分支的提交重新基于目标分支(如 master)的最新提交。
不需要修改提交的顺序、内容或合并提交。
c.操作流程:
将 master 的最新提交作为基准。
按照提交顺序,将当前分支的提交一个一个地重新应用
d.示例:
a.初始状态:
master: A---B---C
dev: D---E---F
b.执行 git rebase master 后:
master: A---B---C
dev: D'---E'---F'
c.git rebase -i master
a.交互式变基
-i 表示交互式(interactive),会打开一个编辑器,让你可以对当前分支的提交进行操作,比如:
修改提交顺序。
合并提交(squash)。
修改提交信息(reword)。
删除提交(drop)。
用户可以在变基过程中对提交进行更多的控制。
b.适用场景
当你需要整理提交历史,比如:
删除无用的提交。
合并多个提交为一个(squash)。
修改提交的内容或信息。
通常在提交到公共分支之前,用来清理和优化提交历史。
c.操作流程
执行 git rebase -i master 后,Git 会打开一个交互式编辑器,列出当前分支的所有提交。
你可以在编辑器中指定如何处理这些提交(pick、reword、edit、squash、drop 等)。
根据你的操作,Git 会按指定的方式重新整理提交历史。
d.示例:
a.初始状态:
master: A---B---C
dev: D---E---F
b.执行 git rebase -i master 后,可以对提交进行如下操作:
合并 D 和 E 为一个提交。
修改 F 的提交信息。
c.结果可能是:
master: A---B---C
dev: D'---E+F'
03.提交点-删除-drop
a.汇总
a.总结
使用 git rebase -i 删除无意义的提交,同时保留有意义的提交和时间点。
完成变基后,强制推送到远程仓库以同步历史。
这种方式不会破坏提交的时间戳,是清理提交历史的推荐方法。
b.为什么需要强制推送?
历史重写:
git rebase 会重写提交历史,包括更改提交的顺序、合并提交、删除提交等。
这些更改会导致新的提交 ID(SHA-1),从而使本地分支的提交历史与远程分支不同。
-------------------------------------------------------------------------------------------------
提交 ID 改变:
在 Git 中,提交是通过 SHA-1 哈希来唯一标识的。当你对提交历史进行任何修改(如删除提交),都会导致新的提交 ID。
因此,Git 会认为本地和远程分支是两个不同的历史,这需要强制推送来覆盖远程分支的旧历史。
-------------------------------------------------------------------------------------------------
同步本地和远程历史:
强制推送是为了让远程仓库的提交历史与本地一致。
b.使用 git rebase -i 可以让你选择哪些提交需要保留、合并或删除
a.查看提交历史
git log --oneline
-------------------------------------------------------------------------------------------------
假设当前提交历史如下:
e5f6d78 (HEAD -> main) Meaningful commit 3
c3d2a41 Useless commit 2
a1b3c4d Meaningful commit 2
f6e7a89 Useless commit 1
d4c5b6a Meaningful commit 1
b.启动交互式变基
git rebase -i HEAD~5
HEAD~5 表示对最近的 5 次提交进行交互式变基。
c.编辑提交列表
a.Git 会打开一个文本编辑器,显示类似以下内容:
pick d4c5b6a Meaningful commit 1
pick f6e7a89 Useless commit 1
pick a1b3c4d Meaningful commit 2
pick c3d2a41 Useless commit 2
pick e5f6d78 Meaningful commit 3
b.修改操作:
将无意义的提交(如 Useless commit 1 和 Useless commit 2)的 pick 替换为 drop,表示删除这些提交。
修改后列表如下:
pick d4c5b6a Meaningful commit 1
drop f6e7a89 Useless commit 1
pick a1b3c4d Meaningful commit 2
drop c3d2a41 Useless commit 2
pick e5f6d78 Meaningful commit 3
d.保存并退出编辑器
Git 会根据你的修改重新整理提交历史。
e.完成变基
如果过程中没有冲突,Git 会自动完成变基。
如果有冲突,Git 会提示你解决冲突,并使用以下命令继续:
git rebase --continue
c.检查新的提交历史,完成变基后,提交历史会被重新整理,删除掉那些无意义的提交。
a.查看提交历史
git log --oneline
b.新的历史可能如下
e5f6d78 (HEAD -> main) Meaningful commit 3
a1b3c4d Meaningful commit 2
d4c5b6a Meaningful commit 1
d.推送到远程
a.如果你已经将原来的提交历史推送到了远程仓库,你需要使用 --force 强制推送新的提交历史
git push --force
b.注意
强制推送会覆盖远程分支的提交历史。如果其他人基于这些提交点工作,请提前沟通,以免影响他们的工作。
e.保留时间点的注意事项
a.git rebase 会保留原始提交的时间戳(作者日期)
即使删除无意义的提交,保留的提交仍然会保持原来的时间点。
b.如果你希望修改时间戳,可以通过以下方式更新:
GIT_COMMITTER_DATE="2025-02-14T14:30:00" git commit --amend --no-edit --date "2025-02-14T14:30:00"
04.提交点-修改-edit
a.启动交互式
git rebase -i HEAD~n
b.编辑提交
在打开的编辑器中,找到包含 CursorPro.exe 文件的提交,将其前面的 pick 改为 edit,然后保存并关闭编辑器
c.移除文件
Git 会暂停在你标记为 edit 的提交点,此时,你可以移除文件:
git rm --cached cursor-register1/V1.5.2/CursorPro.exe
git commit --amend --no-edit
这会从该提交中移除文件,并更新提交
d.继续变基
git rebase --continue
e.推送更改,由于历史记录被修改,你需要强制推送更改到远程仓库
git push origin master --force
05.提交点-合并-squash
a.启动交互式
git rebase -i HEAD~n
b.编辑提交
pick abcdef1 Commit message 1
pick abcdef2 Commit message 2
pick abcdef3 Commit message 3
将你想要合并的提交的 pick 改为 squash(或缩写 s),只保留第一个提交的 pick。例如,要将第二个和第三个提交合并到第一个提交中
pick abcdef1 Commit message 1
squash abcdef2 Commit message 2
squash abcdef3 Commit message 3
c.保存并关闭编辑器
保存文件并关闭编辑器,Git 会开始合并这些提交
d.编辑合并后的提交信息
Git 会再次打开编辑器,允许你编辑合并后的提交信息。你可以根据需要修改提交信息,然后保存并关闭编辑器
e.推送更改,由于历史记录被修改,你需要强制推送更改到远程仓库
git push origin master --force
6.8 [3]cherry-pick:选择性合并
00.汇总
a.cherry-pick 的使用原则
a.在本地分支使用 cherry-pick
cherry-pick 允许你从一个分支中选择特定的提交,并将其应用到当前分支。
注意事项:在本地使用 cherry-pick 时,确保目标分支是最新的,避免在公共分支上随意操作。
如果在远程仓库中执行 cherry-pick,可能会导致其他开发者的分支与历史不一致。
b.避免在公共分支上随意使用
原因:cherry-pick 会将指定的提交应用到当前分支,可能会导致重复的提交历史。
解决方案:使用 cherry-pick 时,最好在本地开发分支操作,避免影响主分支(如 master 或 main)。
b.可以在任意分支下,指定从 dev 分支选择性合并到 master 分支吗
a.回答
可以,cherry-pick 可以在任何分支中选择特定的提交应用到当前分支。
b.原因
git cherry-pick 是基于当前分支执行的,可以指定任意提交进行选择性合并。
c.正确操作
切换到目标分支后,使用 git cherry-pick 来应用特定提交。
c.其他命令
a.忽略冲突
git cherry-pick --abort --放弃 cherry-pick 操作
b.继续 cherry-pick 操作
git cherry-pick --continue --解决冲突后继续
d.命令汇总
| 操作 | 描述 | 常用命令
|-----------------|---------------------------------------|-----------------------------------------------------
| 选择性合并 | 将指定提交应用到当前分支 | git cherry-pick <commit_hash>
| 交互式选择性合并 | 手动选择哪些提交需要保留、修改或合并 | git cherry-pick <commit1_hash> <commit2_hash>
| 解决冲突 | 在 cherry-pick 过程中手动解决冲突并继续 | vi <冲突文件>、git add <冲突文件>、git cherry-pick --continue
| 放弃选择性合并 | 取消当前的 cherry-pick 操作 | git cherry-pick --abort
| 应用多个提交 | 同时选择多个提交进行 cherry-pick | git cherry-pick <commit1_hash> <commit2_hash>
01.两种情况
a.图示
a.基本流程
A---B---C---D (master)
\
E---F---G (dev)
b.cherry-pick 应用后的效果
A---B---C---D---F' (master)
\
E---F---G (dev)
-------------------------------------------------------------------------------------------------
F' 是 F 在 master 上的副本
b.情况1:选择性合并不冲突
a.普通选择性合并(无冲突)
a.描述
使用 git cherry-pick <commit> 将指定的提交应用到当前分支。
b.选择性合并 dev 分支的某个提交到 master
git checkout master --切换到 master 分支
git cherry-pick <commit_hash> --将指定的提交应用到 master
c.效果
指定的提交被应用到当前分支,不会影响其他提交
b.多个提交选择性合并
a.描述
可以同时选择多个不连续的提交进行 cherry-pick
b.操作示例
git cherry-pick <commit1_hash> <commit2_hash>
c.效果
多个指定提交被顺序应用到当前分支
c.情况2:选择性合并冲突
a.解决冲突
a.描述
在 cherry-pick 过程中,如果两个分支的提交修改了相同的文件,可能会发生冲突。
b.操作
1.当冲突发生时,Git 会停止 cherry-pick 并提示冲突文件
2.手动修改冲突的文件:vi <冲突文件>
3.标记冲突已解决:git add <冲突文件>
4.继续cherry-pick:git cherry-pick --continue
5.如果放弃 cherry-pick:git cherry-pick --abort
c.操作示例
git checkout master
git cherry-pick <commit_hash>
# 发生冲突
vi <冲突文件>
git add <冲突文件>
git cherry-pick --continue
b.冲突解决后,选择性合并不会重复产生冲突
a.描述
冲突解决后,Git 会记录冲突的解决状态,cherry-pick 完成后,不会再次触发相同的冲突。
b.继续选择性合并
git checkout master
git cherry-pick <commit_hash>
02.交互模式
a.与变基的对比
| 功能 | git rebase master | git cherry-pick
|---------|-------------------------------|-----------------
| 操作范围 | 重新整理整个分支的提交历史 | 仅选择特定的提交
| 历史改动 | 会重写提交历史 | 仅新增提交,不修改原历史
| 适用场景 | 整理提交历史、线性化历史 | 选择性合并特定提交
| 冲突处理 | 需要解决冲突后继续变基 | 需要解决冲突后继续合并
03.使用git cherry-pick
a.查看提交历史
a.在操作前,先查看目标分支的提交历史,找到需要 cherry-pick 的提交
git log --oneline
b.示例历史记录
e5f6d78 (main) Fix bug in module A
c3d2a41 Refactor module B
a1b3c4d Add feature X
f6e7a89 Update README
d4c5b6a Initial commit
b.选择性合并提交
a.在当前分支上使用 git cherry-pick,选择指定的提交
git cherry-pick <commit-id>
b.示例操作
git cherry-pick e5f6d78 a1b3c4d
c.解决冲突(如果有)
a.如果在 cherry-pick 过程中发生冲突,Git 会暂停操作并提示冲突。此时需要手动解决冲突,并继续操作。
# 解决冲突后,标记为已解决
git add <file>
# 继续 cherry-pick
git cherry-pick --continue
b.如果想中止当前操作,可以使用以下命令:
git cherry-pick --abort
d.批量选择性合并
a.如果需要一次性 cherry-pick 多个连续的提交,可以使用提交范围。
git cherry-pick <start-commit>^..<end-commit>
b.从 d4c5b6a 到 a1b3c4d 的所有提交,并将它们应用到当前分支
git cherry-pick d4c5b6a^..a1b3c4d
e.检查新的提交历史
a.完成操作后,查看当前分支的提交历史,确认提交是否已成功应用。
git log --oneline
b.示例历史记录(在 cherry-pick 之后)
a1b3c4d Add feature X
e5f6d78 Fix bug in module A
<other commits in current branch>
f.推送到远程仓库
a.如果当前分支已经推送到远程仓库,完成 cherry-pick 后,需要将新的提交推送到远程。
git push
b.如果分支历史被重写(例如其他提交被修改或删除),可能需要强制推送:
git push --force
g.注意事项
a.时间戳
默认情况下,git cherry-pick 会保留原始提交的作者日期(Author Date)。
提交日期(Committer Date)会更新为 cherry-pick 操作的时间。
-------------------------------------------------------------------------------------------------
如果需要修改时间戳,可以在 cherry-pick 后使用以下命令:
GIT_COMMITTER_DATE="2025-02-14T14:30:00" git commit --amend --no-edit --date "2025-02-14T14:30:00"
b.冲突处理
在处理冲突时,确保你仔细检查并解决所有文件中的冲突。
如果你不确定是否要继续,可以使用 git cherry-pick --abort 放弃当前操作。
c.避免误操作
确保目标分支的提交历史是干净的,避免引入不必要的提交。
如果当前分支已经推送到远程仓库,操作前与团队成员沟通,确保不会影响其他人的工作。
04.IDEA使用cherry-pick
a.切换到目标分支
1.点击 IDEA 右下角的分支名称(当前显示的分支)
2.在弹出的分支列表中找到 `onboard-J057117`
3.点击并选择 `Checkout`
4.确认切换
b.查看提交历史
1.在 Git 工具窗口中,点击 `Log` 标签页
2.在上方的分支筛选器中:点击 `Branch` 下拉框,选择 `onboard-J057240`
3.现在可以看到该分支的所有提交
c.Cherry-pick操作
a.单个提交
在 Log 中找到需要的提交(如 `57ef805ab`)
右键点击该提交
选择 `Cherry-Pick`
在弹出的确认对话框中点击 `Cherry-Pick`
b.多个提交
按住 `Ctrl` (Windows/Linux) 或 `Cmd` (Mac)
点击选中多个提交
右键 → `Cherry-Pick`
确认应用
c.处理冲突
如果出现冲突,IDEA 会弹出 `Merge` 对话框
使用三方合并工具解决冲突:左侧:目标分支版本;中间:合并结果;右侧:源提交版本
解决后点击 `Apply`
6.9 [4]patch:补丁
00.汇总
a.概念
补丁文件(Patch):是一个包含代码改动的文件,通常以 .patch 或 .diff 结尾。
git format-patch 用于生成补丁文件,包含指定提交的代码变更。它会为每个提交生成一个独立的补丁文件。
b.用途
在不同的分支或仓库之间传递代码修改。
保存某些提交的变更记录,用于后续应用。
解决协作中的代码同步问题。
c.使用场景
需要从一个分支提取特定的提交,并在其他分支中应用这些改动。
在没有直接访问权限的仓库中,通过补丁共享代码改动。
将代码改动保存为文件,便于后续审查或归档。
d.注意事项
a.补丁的适用性
补丁只能应用到与原始分支代码结构类似的分支。如果代码差异较大,可能会导致冲突。
b.时间戳与作者信息
使用 git am 应用补丁时,会保留原始提交的作者信息和时间戳。
如果使用 git apply,则不会创建提交,也不会保留原始信息。
c.补丁命名
git format-patch 会根据提交信息自动生成文件名。如果需要更改补丁文件名,可以手动修改文件名。
e.总结
a.生成补丁
使用 git format-patch 生成补丁文件,可以指定提交范围或单个提交。
b.应用补丁
使用 git apply 应用补丁,只更新代码变更,不生成提交。
使用 git am 应用补丁,同时生成提交并保留原始信息。
c.解决冲突
如果补丁冲突,手动解决后继续操作。
d.适用场景
在不同分支或仓库之间传递代码修改。
保存代码变更,用于后续应用或共享。
通过补丁操作,可以高效地管理跨分支或跨仓库的代码变更
01.生成补丁
a.介绍
用于生成补丁文件,包含指定提交的代码变更。它会为每个提交生成一个独立的补丁文件。
b.基本语法
a.命令
git format-patch <start-point> [options]
b.参数说明
<start-point>:指定从哪个提交开始生成补丁(不包括该提交)。
[options]:可以指定输出目录、文件名格式等。
c.生成从某个提交之后的补丁
a.假设你的分支提交历史如下:
e5f6d78 (HEAD -> dev) Add feature Z
a1b3c4d Fix bug in module X
d4c5b6a Initial commit
b.你希望从 d4c5b6a 之后生成补丁(即包含 a1b3c4d 和 e5f6d78)
git format-patch d4c5b6a
c.结果
生成两个补丁文件:
0001-Fix-bug-in-module-X.patch
0002-Add-feature-Z.patch
d.指定补丁输出目录
a.默认情况下,补丁文件会保存在当前目录。你可以指定输出目录:
git format-patch d4c5b6a -o patches/
-------------------------------------------------------------------------------------------------
结果:补丁文件会保存在 patches/ 目录下。
b.生成单个补丁
如果只需要某个特定提交的补丁,可以直接指定提交 ID:
git format-patch -1 a1b3c4d
-------------------------------------------------------------------------------------------------
生成一个补丁文件:0001-Fix-bug-in-module-X.patch
02.方式1:应用补丁(git apply)
a.介绍
生成的补丁可以通过 git apply 命令应用到目标分支
b.基本语法
git apply <patch-file>
c.应用单个补丁
假设你有一个补丁文件 0001-Fix-bug-in-module-X.patch,可以使用以下命令应用补丁:
git apply 0001-Fix-bug-in-module-X.patch
d.应用多个补丁
如果有多个补丁文件,可以使用通配符批量应用:
git apply patches/*.patch
e.检查补丁是否可应用
在实际应用补丁之前,可以先检查补丁是否可以成功应用:
git apply --check 0001-Fix-bug-in-module-X.patch
03.方式1:应用补丁并提交(git am)
a.介绍
git apply只会将补丁的代码变更应用到工作区,而不会自动创建提交。
如果希望同时创建提交,可以使用 git am
b.基本语法
git am <patch-file>
c.应用单个补丁并创建提交
git am 0001-Fix-bug-in-module-X.patch
-----------------------------------------------------------------------------------------------------
补丁的代码变更会被应用,同时生成一个新的提交,保留原始提交的信息(如提交作者、提交时间等)。
d.应用多个补丁
git am patches/*.patch
04.解决补丁冲突
a.检查冲突
当冲突发生时,Git 会提示类似以下信息:
Applying: Fix bug in module X
error: patch failed: file.c:10
error: file.c: patch does not apply
b.解决冲突
a.手动修改冲突文件
略
b.标记冲突已解决
git add <conflict-file>
c.继续应用补丁
git am --continue
c.放弃补丁应用
git am --abort
05.IDEA使用patch
a.创建Patch
a.打开 Git Log
`View` → `Tool Windows` → `Git` → `Log`
b.选择提交
切换到 `onboard-J057240` 分支视图
选中需要导出的提交(可多选)
c.创建Patch
右键选中的提交
选择 `Create Patch...`
在弹出的对话框中:
选择保存位置:`~/patches/j057240/`
文件名:`j057240_changes.patch`
格式:选择 `Git format`
点击 `OK`
b.应用Patch
a.切换到目标分支
确保当前在 `onboard-J057117` 分支
b.应用Patch
菜单栏:`VCS` → `Apply Patch...`
或使用快捷键:`Ctrl+Shift+V` (Windows/Linux) / `Cmd+Shift+V` (Mac)
选择之前保存的 patch 文件
c.预览和确认
IDEA 会显示 patch 的预览
查看将要修改的文件
点击 `OK` 应用
d.处理冲突
如有冲突,使用 IDEA 的合并工具解决
6.10 [5]stash:暂存区
00.总结
建议在同一commit时间点,进行操作
如果不是同一commit时间点,你可能看到应用stash后的内容,不仅有dev的修改,还混入了master的一些改动,或者产生冲突。
01.保存现场(前提:不在同一个commit阶段)
a.前提:不在同一个commit阶段
git checkout dev
git stash save 'mystash' --保存现场
git stash list --查看现场
b.还原内容,同时将原来保存的现场删除
git stash pop
c.还原内容,但不删除原保存的现场
git stash apply
02.保存现场(前提:同一个commit阶段)
a.前提:同一个commit阶段
git checkout master --master分支
b.如果不同的分支在同一个commit阶段,则在commit之前,可以chekcout切换分支
git checkout dev --dev分支
vi a.txt
git add .
git checkout master --虽然dev分支未commit,但可以切换到master分支
c.场景:修改同一行,还原冲突
a.修改A文件第四行,未commit,此时保存现场
vi a.txt
git stash
b.再次修改A文件第四行,同时commit,此时还原现场会造成"修改同一行,冲突"
vi a.txt
git add .
git commit -m 'dev4'
git stash pop --还原现场会造成"修改同一行,冲突"
03.stash与commit的时间点关系
a.独立于提交时间点
git stash 操作与 commit 操作是独立的。stash 的目的是临时保存未提交的更改,不涉及实际的提交历史。
你可以在任何时间点使用 git stash,无论当前是否有未提交的更改,或者是否刚刚进行了提交。
b.使用场景
当你正在进行一些工作但需要切换到另一个分支,或者需要在不提交当前工作的情况下处理其他任务时,可以使用 git stash 暂存这些更改。
stash 后,你可以自由地切换分支或进行其他操作,而不会丢失未提交的更改。
04.stash的工作机制
a.暂存更改
使用 git stash 命令将当前的工作目录和暂存区的更改保存到栈中。
这会清理工作目录,使其恢复到上一次提交的状态。
b.恢复更改
使用 git stash apply 或 git stash pop 恢复 stash 中的更改。
git stash apply 会应用暂存的更改但不删除 stash 记录。
git stash pop 会应用暂存的更改并删除 stash 记录。
c.查看 stash
使用 git stash list 查看当前所有的 stash 记录。
05.当你从 dev 分支切换到 master 分支后,应用 stash 的内容时,会出现一些“意料之外”的结果
a.stash 的内容与当前分支的差异相关
git stash 保存的是当前工作目录的改动,包括未提交的文件改动和暂存区的改动。但当你切换到另一个分支
(比如从 dev 切到 master),原本在 dev 分支上保存的改动可能与 master 分支的代码有冲突或上下文差异。
-----------------------------------------------------------------------------------------------------
stash pop 会尝试将 stash 中保存的改动应用到当前分支(master)的代码上。
如果 master 和 dev 有不同的文件或代码上下文(比如某些代码在 master 中已被修改或删除),git stash pop 会尝试“合并”这些改动,但可能会引入 master 的部分内容,甚至导致冲突。
-----------------------------------------------------------------------------------------------------
结果:你可能看到应用 stash 后的内容,不仅有 dev 的修改,还混入了 master 的一些改动,或者产生冲突。
b.stash pop 会应用改动到当前分支的代码
stash 只是保存了改动,并不关心改动是基于哪个分支的代码。它只是简单地将这些改动尝试应用到你当前所在的分支代码上。
-----------------------------------------------------------------------------------------------------
如果 dev 和 master 的基础代码差异较大,那么 stash pop 的结果可能会显得“混乱”。
如果代码上下文不一致,Git 会尝试通过三方合并的方式来解决差异,但这可能会引入额外的代码变更。
c.stash 不是跨分支的“精准快照”
stash 不是针对某个分支的快照,而是保存了改动的内容。因此,它不会自动考虑你切换到的分支是否适合直接应用这些改动。
-----------------------------------------------------------------------------------------------------
在从 dev 切到 master 后,stash 中的内容会尝试应用到 master 的代码基础上,而不是 dev 的代码基础。
如果你希望改动能完全基于 dev 分支的上下文,可以在 dev 分支完成后再提交,而不是直接跨分支应用。
d.解决方案
a.确保上下文一致性:
如果改动是基于 dev 分支的代码,尽量先在 dev 分支完成工作,提交后再切换到 master。
或者,在切换分支时,避免直接 stash pop,而是手动调整内容。
b.使用 git stash branch:
如果需要跨分支操作,考虑使用 git stash branch,它会基于 stash 的内容创建一个新的分支,避免直接应用到当前分支的代码。
git stash branch temp-branch
c.避免在不相关的分支上直接 stash pop:
在切换到 master 分支后,可以手动检查和合并 stash 中的改动,而不是直接应用。
git stash apply
# 手动解决冲突或调整代码
d.提前确认分支差异:
在切换分支前,使用 git diff 确认 dev 和 master 的差异,判断是否需要在 dev 完成工作再切换。