GeekHour

embedded/2025/1/23 19:53:44/

Linux

Linux的是类Unix系统,作者是Linus,也是git的作者。符合GPL(General Public License)就可以Linux的使用、修改、再发布。

Linux四部分:

  1. 内核:驱动、内存管理、进程管理、文件系统、网络协议栈…。作用:管理硬件和提供最基本的系统服务
  2. 系统库:libc(C标准库)、libm(数学库)、libdl(动态链接库)、libpthread(线程库)、第三方库…。作用:提供常用函数和接口供开发使用。
  3. shell:用户使用Linux的接口
  4. 应用程序:Google、Vim、Git、MySQL、Nginx

Linux的发行版还包括包管理器(apt\yum)、GUI、系统工具等,比如Ubuntu(个人用户)、Debian、CentOS、Kali(网络安全和渗透测试)

安装Linux:

  • 虚拟机工具:VMware、VirtualBox、Hyper-V(window的WSL)、Multipass
  • Docker
  • 云服务器

Linux根目录:

  1. bin、sbin:可执行二进制文件
  2. home、root
  3. usr、opt、etc、
  4. lib\lib32\lib64、dev、mnt
  5. boot、sys、proc
  6. var、temp

Vim

一般服务器没有图形界面,只能使用Vim编辑器。vim是vi的提升版本(improved)。apt install vim -y

命令模式:

  1. a\A i\I o\O 表示进入插入模式,: 表示进入尾行模式。插入模式、尾行模式按ESC进入命令模式。
  2. 移动光标:h j k l 表示左下上右;ctrl + f/b/d/u 表示下页、上页、下半页、上半页;^ $表示行首、行末。gg G 3g 表示首行、尾行、第三行。:3 表示第三行。
  3. 3yy 表示复制三行;3dd 表示删除三行,D 表示清空本行;3p 表示复制三次粘贴板上的内容。
  4. ctrl + r 表示撤回,u 表示重做。

行末模式:

  1. 查找:/hello | ?hello 表示向下、向上查找。n | N 表示下一个、上一个。/hello\c 表示无视大小写
  2. 替换::2,5s/hello/world/g 表示2,5行,g表示此行全部。:s/hello/world 表示此行第一个替代。:%s/hello/world 表示每行第一个替代。

还有~\.vimrc 文件:可以设置一些常用的

set nu		# set nonu
syntax on
set ic		# 忽略大小写

tip:vimrc中rc表示run commands。

常用命令

ls -haltri		# i:inode节点、t:time、r:reverse
echo "hello world" > hello.txt		# 覆盖文件之前的内容
echo "second" >> hello.txt		# 追加文件内容
touch hello.txt		# 创建文件、更新文件时间
cat hello.txt		ln -s hello.txt hello_soft.txt	# 软连接
ln hello.txt hello_hard.txt		# 硬连接
# 硬连接:文件; 软连接:文件或目录# 权限
chmod u+x hello.txt		# ugoa +- rwx
chmod 777 hello.txt		# 等效
chmod root:root file	# 修改 所有者:所属组mkdir dir		# 删除空目录 rmdir dir
mkdir -p dir1/dir2	# rm -r dir1。linux删除不可逆
cp -r dir1 dir_copy
mv hello.txt dir/hello_move.txtdate whoami pwd	tree
du			# 目录
df -h		# 磁盘
which ls# 安装jdk1.8(java8)
apt list | grep jdk
sudo apt install openjdk-8-jdk
java -version# 解压
tar -xvzf file.tgz

inode:文件类型、权限、所有者、文件大小、时间戳、数据块指针。

命令

ps -ef # e表示所有 f表示信息
# 其中tty表示Teletypewriter, tty1,tty2表示物理终端界面; ?表示没有终端相连# 文件和进程的关系
lsof -u root -p 1234 	# 打开文件list,root中进程为1234所打开的文件
lsof file	# 哪些进程在使用file
lsof -i :80 # 查看80端口的进程
lsof -i tcp # 或者udp
# FD文件描述符: cwd/rtd/dir/txt/NOFD/mem/pipe/socket/chr/blk
# TYPE: REG(常规文件)DIR(目录)CHR(字符设备)

Shell

脚本的作用:定时处理(比如定时清理、定时备份)、批处理…

Shell种类:sh、bash(默认)、csh、ksh、zsh、powershell。可以cat /etc/shells 查看。

.profile.bashrc:用户打开bash前会使用这两个文件进行初始化环境。配置之后使用. bashrc 或 source .bashrc

/etc/bash 下的文件是对所有用户都有效。

环境变量

echo $SHELL		# 默认bash
echo $HOME	
echo $PATH
echo $0		# 表示当前的shell解释器。默认bash
export name=adair	# 在运行的shell中就可以获取

常用的$:

  1. $0、$1、 2 、 2、 2#:表示文件名、第一个参数、第二个参数、参数个数
  2. ∗ 、 *、 @:前者表示作为整体;后者表示按参数传递
  3. ? 、 ?、 ? 、 、 !:表示最后一个命令返回的结果;表示此进程PID;最后一个后台命令的PID

if中的数字比较:eq、ne、lt、le、gt、ge。

if中的字符串比较[[ "$str1" == "$str2" ]]:!=、>、== *、=~、-z、-n

举个例子

#!/bin/bash				# 默认解释器is_prime() {local num=$1		# 局部变量必须使用local,否则为全局变量if [ $num -lt 2 ]; thenreturn 1fifor ((i=2; i*i<=num; i++)); doif [ $((num % i)) -eq 0 ]; thenreturn 1fidonereturn 0
}read -p "输入数字:" numberif ! [[ "$number" =~ ^[0-9]+$ ]]; then	# 正则表达式符echo "no number"exit 1
fiif is_prime $number; then	# 函数返回0表示OKecho "$number 是素数"
elseecho "$number 不是素数"
fi

猜数字

#!/bin/bash# 等效 $(($RANDOM%10+1))
number=$(shuf -i 1-10 -n 1)	# 也可以使用反引号
echo "随机数为$number"while true; doecho "输入猜的值"read guessif [[ $guess -eq $number ]]; thenecho "对了, 请选择是否继续y/n"read choiceif [[ $choice = "y" ]] || [[ $choice = "Y" ]]; thennumber=$(($RANDOM % 10 + 1))echo "随机数为$number"continueelsebreakfielif [[ $guess -lt $number ]]; thenecho "小了"elseecho "大了"fi
done

管道:

如果输入bash confirm.sh,则会一直循环输入。可以直接yes | bash confirm.sh

#!/bin/bashfor ((i=0; i<3; i++)); do    read -p "输入y|n" flagecho "i=$i flag=$flag"if [ "$flag" == "y" ]; thencontinuefi
done

shell也可以结合:

  1. grep awk sed 等文本处理
  2. 函数和数组等高级特性。
  3. 系统管理和监控

RegEx

基本字符匹配:.、[ ]、[^ ]、|、
字符类:\d、\w、\s、\D、\W、\S。定位符:^、$、\b、\B、
量词:?、+、*、{n}、{n,m}、{n,}。贪婪匹配:ab{3,}、ab{3,}?
旗帜:i、m、s、g、
分组:(abc)、(?:abc)
前瞻:dog(?=cat)、dog(?!cat)。后顾:(?<=cat)dog、(?<!cat)dog

前面的字符都是有特定意义的,如果需要这个字符本身,需要进行转义。但是转义字符同样需要转义\\

基本类型:^$. [1-8B-Yc-x] [^] | \d \w \b \s \大写
量词:? + * {n} {n,m} {n,} {n,}?
前瞻:dog(?=cat) dog(?!cat) 	后顾:(?<=cat)dog (?<!cat)dog
分组:(abc) (?:abc)。\1
旗帜:i\g\s\m

部分解释:

  1. . 匹配除\n 的任意字符,s. 也可匹配\n
  2. ^$ 表示文本开始和结束。m^$ 表示每行开始和结束。
  3. \b :比如\b\d+\b 匹配 %300 而不是 s300

其他版本的RE:

  1. POSIX基本的BR、扩展的ERE。
  2. 其他版本的比如Python、Java、JS等。具体情况看文档。

拓展结合:

  • grep 和 sed 和 awk

Git

版本控制系统:集中式(比如:SVN)、分布式(比如Git)

Git的使用方式:命令行、GUI、IDE插件/扩展。

git配置:

# system 系统配置/etc/gitconfig:对所有用户生效。global 全局配置~/.gitconfig:所有仓库生效。 不带范围.git/config:默认此仓库
git config --global user.name "adair"
git config --global user.email "123@qq.com"
git config --global credential.helper store		# 存储密码,不用git push每次都要输入密码 
git config --global --list		# 查看属性

.gitignore的内容:

  1. 中间文件或者结果文件,class文件\o文件
  2. log\temp
  3. user\password、Token等
.a	# 忽略所有a类型文件
!lib.a	# 不包括lib.a
/TODO	# 忽略根目录下的TODO文件
build/	# 忽略任何目录的bulid文件夹
doc/*.o	# 忽略doc当前目录下o
doc/**/*.class	# 忽略doc所有下的class

不过项目都有相应的模板,不用自己写。https://github.com/github/gitignore

.git/ 文件夹

  1. config:配置的信息,core、user、branch( -a)
  2. refs/ (分支):heads/ (本地分支);remotes/(远程);tags/
  3. index:暂存区指针; HEAD: 版本库中。 指向object/:里面都是对象
  4. logs/ :HEAD(git log的内容);refs/:相应git branch -a其他所引用的内容

创建仓库:

# 本质都是有.git才是仓库。否则就是个普通文件夹
git init	# 把当前文件夹为git仓库
git init local-git  # 创建文件夹local-git为git仓库git clone url	# 克隆
git clone git@github.com:name/repo.git
git clone git@192.168.8.242:v40_7.1.git

添加和提交

# 工作区、暂存区、本地库。push 远程库ls		# 	工作区ls
git ls-files 	# 暂存区lsgit status		# 状态:??(Untracked)、M(modifid)、A(added)、D(deleted)、R(renamed)、U(updated)、修改file		# 返回  git restore file \ git checkout file 
git add file	# 返回 git restore --staged file  \ git reset HEAD(原理) \
git commit -m "message"	# -a -v	
git commit --amend	# 补充提交, 可以-m	git log		# --online --graph

版本回退

# 回退之前的版本
git reset --soft commmitID	# 指定commitID,且恢复工作区和暂存区
git reset --hard commmitID	# 指定commitID的,不恢复
git reset commmitID	# 指定commitID,且恢复工作区。默认--mixed# 从之前的版本到当前版本
git reflog		# 查看所有的提交的commitID# HEAD 当前版本
# HEAD^ HEAD~ 上一个版本
# HEAD~2 上两个版本

内容对比

git diff	# 工作区 vs 暂存区
git diff HEAD # 工作区 vs 本地库
git diff commitID1 commitID2	# 两个版本的比较,
git diff commitID1 commitID2 file.txt	# 只比较file.txt
# 也可以使用HEAD

git diff 分析

zql@adair-pc:~/git-learn/123$ git diff HEAD
diff --git a/m1 b/m1			# a/m1: 新版  b/m1: 旧版		
index 0e6c128..83e9726 100644	# 新版和旧版索引(hash) 100普通文件, 644权限
--- a/m1
+++ b/m1
@@ -1,3 +1,4 @@		# 旧版:1,3行。 新版:1,4行123456123q
+123			# +表示新增的

删除文件

git rm file.txt		# 综合 rm file.txt(工作区) 和 git rm --cached file.txt(暂存区) 
git mv m1.txt m2.txt	# 改名,git status . 出现renamed

分支

git branch	# 查看本地分支; -r:remote; -a:all;
git branch dev	# 创建分支。git branch -d dev	# 删除分支,没有合并则需要D
git checkout/switch dev	# 切换分支。checkout -b,创建并切换# main、dev合并分支,不冲突
git merge dev	# 当前在main,则合并dev分支。并且自动会让你输入message,表示一次提交commitID。# main、feat合并分支,冲突
git merge feat	# 此处会把冲突的文件内容合并,重新整理冲突文件。
git commit -am "zql:conflict merge" 	# 需要重新提交,产生commitID
git merge --abort	# 表示终止提交# rebase
git rebase dev	# 表示以dev为根,把main接到dev上。形成直线历史
git rebase main	# 同理

git merge dev冲突

# 提示冲突,
<<<<<<< HEAD
456
=======
123
>>>>>>> dev# 修改冲突之后在进行git commit

通过(github.com gitee.com)账户名和密码的方式克隆remote。

ssh配置,远程克隆到本地:

  1. 本地生成公钥密钥。
cd ~/.ssh		# 切换到~/.ssh下
ssh-keygen -t rsa -b 4096	# rsa类型,4096个bit位数
# 输入相应的名称比如demo,密码demo
# 生成demo.pub,密钥demovim config		# 增加以下内容
```
Host github.com
HostName github.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/demo
```
  1. 把公钥复制到GitHub中。ssh -T git@gitee.com 测试

  2. 本地创建一个空仓库,git remote add origin git@github.com:adair-zhang/learn-github.git 关联远程即可。

tip:这样创建空库再关联太慢了,不如clone。

本地推送到远程:

  1. GitHub中创建一个空仓库
  2. 在本地仓库中进行连接GitHub的空仓库
git remote add origin git@github.com:adair-zhang/learn-github.git
git branch -M main # 强制修改当前名(默认为master),修改为main
git push # git push -u origin main 第一次推送到远程。main其实是main(本地):main(远程)缩写git fetch 		# 默认git fetch origin main,此时并不在最新的commitID。然后合并git merge
git pull 		# 等效fetch + merge。默认是git pull origin main

代码托管平台:

  1. GitHub、gitee、gitlab
  2. 私有化部署:在自己服务器上部署一个gitlab代码托管平台。可以使用Docker进行部署。
# 比如my-repo是本地关联到github上。
git remote add gitlab git@gitlab.com:name/myrepo.git	# 本地再次关联到gitlab上
git remote -v	# 可以查看本地关联远程的情况
git push gitlab main	# 推送到gitlabgit remote add github2 git@github.com:adair-zhang/first-repo.git	# 关联其他仓库
git remote -v # 表示仓库关联的远程信息

git的GUI:GitHub Desktop、SourceTree、GitKraken等

也可以在VS code中进行操作:

  1. windows安装git
  2. 然后可以使用vs code中的git

git本质

image-20230916102952710

常用命令

image-20230916103020915


拓展配置:

  • post-git

git心得:

  • commit之前先review,查看代码是否错误,规范
  • 平时开发test分支,不要在master分支

C语言

丹尼斯创造为了Unix编写。

范围:Unix\Linux\Windows、git\vim、MySQL\Redis、Nginx

静态语言:编译时确定变量类型, C\C++\Java\Rust
动态语言:运行时确定变量类型,Python\JavaScript\Ruby\PHP

编译器:

  1. GCC:GNU Compiler Collection,包含了C、C++、Objective-C、Ada、Go等多种编译器
  2. Clang:编译C、C++、Objective-C、Objective-C++的编译器前端。采用LLVM为后端,在MacOS下使用

安装开发开发环境:MinGW,安装后 gcc -v 测试。

IDE:CLion、Code::Blocks

VS code

安装好MinGW中的gcc。vs code中不提供编译器。

vs code中然后再增加扩展中,Code Runner 就可以直接运行C的源码了

基本语法

数据类型:

  1. 基本数据类型:short、int、long、long long、char、float、double
  2. 派生数据类型:数组、指针、结构体、枚举、共用体、void
#define MAX 100	// 宏定义
int num; 	// 全局变量,静态变量int默认0
int main(){int age; 	// 不赋值,则默认内存的随机值const double PI = 3.14; // const表示常量
}

tip:sizeof(long)在win中始终是4,linux中sizeof(long)为4(32位系统),为8(64位系统)

goto:

int main() {for (size_t i = 0; i < 3; i++) {printf("%d\n", i);if(i == 1) goto out;}
out:printf("hello\n");  
}

指针

int main() {int a = 300;     int *p = &a;printf("a = %d\n", a);printf("p = %p\n", p);printf("*p = %d\n", *p);printf("p + 1 = %p\n", p+1);    // 地址+4字节int **p2 = &p;      // 指向指针的指针。printf("p2 = %p\n", p2);printf("*p2 = %p\n", *p2);  // 为p的地址printf("**p2 = %d\n", **p2); 
}

数组

int main() {int arr[5] = {1, 2, 3, 4}; // 默认初始值为0int *p = arr;*p = 10;    // 修改a[0] = 10printf("*p = %d\n", *p);       // a[0]值// +1表示指向下一个元素。sizeof(int)=4,所以加4。如果是double,加8p += 1;                 printf("*p = %d\n", *p);        // a[1]值// 二维数组int b[3][4] = {{1, 2, 3, 4},{1, 2, 3, 5},{1, 2, 3, 6}};
}

堆栈

int main() {// 栈内存:比较小,几M ~ 几十Mint a = 1;int b = 2;int c = func(a,b);// 堆内存:很大,可以申请使用int *p = (int *)malloc(sizeof(int));*p = 100;printf("*p = %d", *p);free(p);    // 释放p所指空间,防止内存溢出p = NULL;   // 防止野指针。
}

函数

// Demo1: 函数声明。项目开发中,则会声明函数在头文件,实现函数则文件\库中。
int add(int a, int b);	// 声明。也可以int add(int, int)
//或者,直接把实现体放到前面
int main() { }
int add(int a, int b){return a+b;
}// Demo2: 函数指针。项目开发中,实现一个回调函数,就把函数指针作为参数传递给另外一个函数,在此使用指针来执行此函数,比如事件处理或消息传递。
#include <stdio.h>int add(int a, int b){return a+b;
}
int substract(int a, int b){return a-b;
}
typedef int (*Operation)(int, int);
int main() {// 等效 int (*p)(int, int) = add;Operation p = substract;   printf("%d\n", p(3,4));
}

static

void test() {static int a = 0;a += 1;printf("a=%d\n", a);
}
int main() {test(); // print a=1test(); // print a=2
}// static修饰全局变量和函数时:表示只能在当前文件使用,用于模块封装,防止命名冲突

string

#include <string.h>	// 引入头文件
int main() {// 字符串本身就是字符数组,也可以使用指针表示。char a[20] = "hi"; // 等效{'h', 'i', '\0'};char *b = "hello"; printf("%s\n", a);printf("%s\n", b+1);    // 输出:ello// 字符串函数:strcpy\strcmp\.\strncat\strncpy\strncmpstrcat(a, b);   printf("%s\n", a);
}

结构体struct

typedef struct student {char name[20];int age;float score;
}Student;
int main() {struct student stu1 = {"Tom", 18, 60.1};    // Student stu1 =...strcpy(stu1.name, "Tommy");stu1.age = 19;printf("%s, %d, %f", stu1.name, stu1.age, stu1.score);    
}

共用体union

union student {// 两个变量共用一个地址。char name[10];int age;
};
int main() {union student stu1;    stu1.age = 97;printf("%s, %d", stu1.name, stu1.age);   // a, 97 
}

枚举enum

enum day {  // 下面的属性默认从0开始MON,    TUE,WED
};
int main() {enum day day1 = TUE;    printf("%d", day1);   // 1/*** 亦可* enum day {MON = 3,    TUE,WED};*/
}

库引用

// a.h
#ifndef A_H		// 解决库重复引用导致的重复定义问题。
#define A_H
int a = 1;
#endif// b.h
#include "a.h"// hello.c
#include <stdio.h>#include "a.h"
#include "b.h"
int main() {printf("hello %d\n", a);	// 如果没有上面的条件编译。报错:重复定义
}

编译链接过程:

  1. 预处理:
    1. 头文件和条件编译、宏定义
    2. 除掉注释
  2. 编译阶段:源文件转为汇编代码
    1. 语法检查、类型检查
    2. 代码优化:常量表达式直接计算出来、删掉无用代码
  3. 汇编阶段:汇编代码转为机器码(目标文件 .o
  4. 链接阶段:把所有目标文件使用的库文件链接起来,形成可执行文件。分为静态链接和动态链接。
    1. 静态链接:会将库默认直接嵌入到可执行文件中,运行时不再依赖外部库。
    2. 动态链接:程序运行时加载库。多个程序可以共享一个动态库,节省资源。

库:已经编译好的文件

  1. 静态库:.a (Linux中)、.lib (win中),并不是只用于静态链接。
  2. 动态库:.so (Linux中)、.dll (win中),并不是只用于动态链接。

有空再看:

特性CC++C#Objective-CObjective-C++
编程范式过程化编程面向对象、过程化面向对象面向对象面向对象 + 泛型编程
内存管理手动管理手动管理自动垃圾回收ARCARC + 手动管理
平台跨平台跨平台Windows、跨平台macOS、iOSmacOS、iOS + 跨平台
运行时静态编译静态编译静态编译动态运行时动态运行时
模板编程支持模板编程支持模板编程
使用场景操作系统、嵌入式应用程序开发、游戏企业应用、Web 开发macOS、iOS 开发混合 C++ 和 Objective-C
典型应用操作系统、硬件驱动高性能应用、游戏Web 应用、游戏开发iOS/macOS 应用开发iOS/macOS 应用开发

C:如果你需要控制硬件或开发底层系统,C 是最合适的选择。

C++:如果你需要高效且灵活的面向对象编程,并且涉及到复杂的数据结构或系统性能要求,C++ 更为合适。

C#:如果你开发 Windows 应用、Web 应用或跨平台应用,C# 是一个非常现代和高效的选择。

Objective-C:如果你在开发 iOS 或 macOS 应用,Objective-C 是一个必备语言,尤其是在 Swift 出现之前。

Objective-C++:如果你需要结合 C++ 的高效性和 Objective-C 的面向对象特性,尤其是在需要同时调用 C++ 库和 Objective-C 库时,可以使用 Objective-C++。


高级特性

  1. 如何编译makefile
  2. gdb调试器
  3. 栈溢出漏洞

编译运行机制

开发环境

常用工具

使用技巧

Makefile

构建工具make中的makfile相当于 maven中 pom.xml ,Node.js(npm) 中 package.json。

安装:

choco install make // win安装: 位置C:\ProgramData\chocolatey\bin\make.exe
sudo apt install make // linux

基本语法规则:

target: sourecesrules...

Demo:

目前有源文件

// message.h
void message();// message.c
#include <stdio.h>
void message() {printf("hello world\n");
}// hello.c
#include "message.h"
int main() {message();
}

makefile

.PHONY: clean all
CFLAGS = -Wall -g -O2
target = hello world
object = hello.o message.o
# source = hello.c message.call: hello world@echo "all done"$(target): $(object)gcc $(CFLAGS) $(object) -o $@%.o: %.cgcc $(CFLAGS) -c $< -o $@clean:rm -f *.o hello

解释:

.PHONY 表明 make clean/all 后面接的是命令,而不是文件(比如有个clean文件)
CFLAGS 设置编译选项,-Wall所有警告,-g调试,-O2中度优化$(target): $(object)gcc $(CFLAGS) $(object) -o $@
当所需$(object)没有时,向下查找生成目标。%.o: %.cgcc $(CFLAGS) -c $< -o $@
所有的c转为o: message.o 和 hello.o,
message.o: message.c	gcc $(CFLAGS) -c message.c -o message.omakefile中自动变量:$@ 表示target; $< 表示源文件第一个参数

CMake

makefile 无需手动编写,CMake自动生成,配置文件为 CMakeLists.txt 文件

sudo apt install cmake 	// linux安装cmake

vs code使用cmake

  1. 创建CMakeLists.txt
# 常用配置。手写
cmake_minimum_required(VERSION 3.10)project(HelloWorld)set(SOURCES hello.c message.c)add_executable(hello ${SOURCES})
  1. 执行 cmake 命令,自动识别CMakeLists.txt,并生成Makefile文件。
  2. 依旧执行命令:make 自动生成可执行文件hello,清理 make clean

Maven

Maven 在配置文件 pom.xml (Project Object Model)

  1. 管理依赖,将依赖jar和依赖的依赖jar的导入项目。手动导入依赖麻烦、可能冲突。
  2. 构建管理:java源文件 转为 class字节码,然后打包成可执行的jar或者war。执行 构建、打包、部署等工作。

Maven仓库:

  1. 本地仓库:~/.m2/repository/。本地没有则会去私服和中央仓库中查找并下载到本地,提高效率。
  2. 私服仓库:公司或组织的仓库,可以私用Nexus构建。非必须的
  3. 中央仓库:Maven官方仓库

安装:windows中,官网下载bin二进制压缩包,配置环境变量 MAVEN_HOME 和 path。mvn -v 查看版本。

# linux中安装
sudo apt install maven	# 自动配置环境变量。
# 如果使用解压包,则.bashrc下
export MAVEN_HOME=../..
export PATH=$MAVEN_HOME/bin:$PATH

配置.\config\settings.xml

<!--配置本地仓库地址-->
<localRepository>D:\environment\apache-maven-3.9.6\mvn_resp</localRepository><!--配置中央仓库镜像,由于Maven在国内访问慢-->
<mirror><id>alimaven</id><mirrorOf>central</mirrorOf><name>aliyun maven</name><url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror><!--配置对应jdk,可以不配-->
<profile><id>jdk-1.4</id><activation><jdk>1.4</jdk></activation><repositories><repository><id>jdk14</id><name>Repository for JDK 1.4 builds</name><url>http://www.myhost.com/maven/jdk14</url><layout>default</layout><snapshotPolicy>always</snapshotPolicy></repository></repositories>
</profile>

demo

Linux中创建demo:

# 创建mvn项目
mvn archetype:generate -DgroupId=net.geek -DartifactId=maven-sample -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.5 -DinteractiveMode=false# 编译,target下生成class字节码 
mvn compile# 打包:maven-sample-1.0-SNAPSHOT.jar
mvn package# 运行项目 cp:classpath。输入:Hello World!
java -cp target/maven-sample-1.0-SNAPSHOT.jar net.geek.App

IDEA中创建demo

  1. 依然选择maven-archetype-quickstart,然后选择GroupId,ArtifactId。即可创建成功
  2. 可以在IDEA的settings中修改Maven的home和配置

从IDEA中可以看到maven的各种生命周期,各种生命周期都是有对应的插件实现的,插件也就是java类,maven本质上就是通过接口调用这类来实现生命周期,而且default中生命周期有顺序的,直接执行后一个命令,会自动执行之前的命令:

  1. clean
  2. default:validate; compile; test; package; verify; install(将jar安装到本地仓库); deploy(将jar部署到公司的私服仓库);
  3. site:生成网站的信息和文档为静态网站。会生成index.html可以在浏览器中查看

tip:install的位置,比如D:\environment\apache-maven-3.9.6\mvn_resp\net\hour\mvn-exapmle\1.0-SNAPSHOT\mvn-exapmle-1.0-SNAPSHOT.jar。(net\hour包名、mvn-exapmle项目名、1.0-SNAPSHOT版本)

比较常用命令:

  1. mvn clean package
  2. mvn clean install

pom.xml中使用GAV(groupId artifactId version)标定一个jar包,version中snapshot (快照,开发中)和 release(开发完)

<!-- groupId不爆红说明有这个组,下面同理 -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>6.2.1</version>
</dependency><!--依赖传递: 直接依赖context,它会引用间接依赖core\aop\beans等-->
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.2.1</version>
</dependency>

依赖范围:

<dependencies><!--test: 只用于测试单元的源码,不会被正式源码引用,不会被打包--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency><!--compile默认:编译和运行都需要--><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>6.2.1</version><scope>compile</scope></dependency><!--provided:编译需要,运行不需。比如lombok简化Setter\Getter--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.34</version><scope>provided</scope></dependency><!--servlet运行时Tomcat或其他Web容器会提供,所以也是provided--><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></dependency><!--runtime: 运行时需要,编译无需,比如jdbc驱动--><dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId><version>42.7.4</version><scope>runtime</scope></dependency><!--system: 只能在本地电脑使用,因为源码放在git中,而git一般忽略jar,除非其他环境手动引入这些jar最好引入到私服仓库,其他成员只用pom即可--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>system</scope><systemPath>${basedir}/lib/junit-3.8.1.jar</systemPath></dependency>
</dependencies>

父子工程:多个模块的依赖管理

  1. 创建maven-parent项目,同上demo。把此项目src删除。
  2. 在父类项目中,创建多个module,并命名为child-a、child-c、child-d、
  3. 可以在IDEA右侧栏中看到相应模块。
<!--maven-parent 的 pom.xml-->
<groupId>net.geek</groupId>
<artifactId>maven-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<!--pom值: 表示父类-->
<packaging>pom</packaging>
<modules><module>child-a</module><module>child-b</module><module>child-c</module>
</modules><!--child-a 的 pom.xml-->
<parent><groupId>net.geek</groupId><artifactId>maven-parent</artifactId><version>1.0-SNAPSHOT</version>
</parent>
<artifactId>child-a</artifactId>
<!--表示jar,还可以war-->
<packaging>jar</packaging>

maven-parent 的 pom.xml:这样dependencies由于无条件继承,父子耦合高

<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring.version>6.2.1</spring.version>
</properties><!--child-* 无条件继承-->
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency>
</dependencies>

降低耦合度:

<!--maven-parent 的 pom.xml:子类不继承-->
<!--properties 可以定义通用的属性,以便后面引用-->
<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring.version>6.2.1</spring.version>
</properties>
<dependencyManagement><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency></dependencies>
</dependencyManagement><!--child-a 的 pom.xml:继承,默认version为父类的-->
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId></dependency>
</dependencies>

依赖冲突:比如A和B,A引入D,B通过引入C再引入D?或者A和B同时引入D?D是不同的版本,到底用那个版本。

  1. maven本身有第一的规则:最短路径优先,先声明优先。
  2. 开发者:通过exclusions标签排除依赖、optional标签标记可选依赖。

spring-jdbc版本此时就会冲突,此时child-a由于路径一样,则先声明优先,使用child-b中的spring-jdbc的版本。

<!--child-a 的 pom.xml,引入child-b和 child-c -->
<dependency><groupId>net.geek</groupId><artifactId>child-b</artifactId><version>1.0-SNAPSHOT</version>
</dependency>
<dependency><groupId>net.geek</groupId><artifactId>child-c</artifactId><version>1.0-SNAPSHOT</version>
</dependency>
</dependencies><!--child-b 的 pom.xml-->
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>6.2.1</version>
</dependency><!--child-c 的 pom.xml-->
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>6.2.1</version>
</dependency>

如果开发者想使用child-c中的spring-jdbc版本

// 方式一:修改child-a的pom.xml,exclusions排除
<dependency><groupId>net.geek</groupId><artifactId>child-b</artifactId><version>1.0-SNAPSHOT</version><exclusions><exclusion><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId></exclusion></exclusions>
</dependency>
<dependency><groupId>net.geek</groupId><artifactId>child-c</artifactId><version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>// 方式二:修改child-b的pom.xml, optional标签为ture表示可选(非必须的	)
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>6.2.1</version><optional>true</optional>
</dependency>

Nexus

Nexus用于私服仓库。

安装和使用:

  1. win中下载对应压缩包并解压,
  2. 通过./etc/nexus-default.properties知道端口为8081
  3. 开启服务nexus.exe/run ,通过浏览器 localhost:8081 访问。

Nexus网页介绍:

  1. 默认有maven-releases(本地hosts)、maven-snapshots(本地hosts)、maven-central(中央仓库)、maven-public(包含三者)、
  2. 开发者也可创建其他仓库,nexus不仅支持maven2;也支持docker,npm,yum之类的包文件

从Nexus下载:

<!-- ./conf/settings.xml 配置mirror和server -->
<mirror><id>maven-nexus</id><mirrorOf>*</mirrorOf><name>nexus私服</name><url>http://localhost:8081/repository/maven-public/</url>
</mirror><server><id>maven-nexus</id><username>admin</username><password>admin</password>
</server>

上传Nexus,即deploy:

<!-- pom.xml-->
<version>1.0.0</version><!-- 配置nexus的id和具体仓库的url -->
<distributionManagement><!-- 会根据version值是否有SNAPSHOTS,自动决定是releases还是snapshots仓库 --><repository><id>maven-nexus</id><url>http://localhost:8081/repository/maven-releases/</url></repository><snapshotRepository><id>maven-nexus</id><url>http://localhost:8081/repository/maven-snapshots/</url></snapshotRepository>
</distributionManagement>

tip:默认不许重复上传正式版本,比如1.0.0,第二次进行deploy就会报错。


import依赖范围

Nginx

最常用的Web服务器。一个Master进程管理多个Work进程。

安装方式:

  1. 包管理器:linux通过apt、win通过choco、mac通过brew
  2. 编译安装:下载对应C语言源码,预编译、编译、安装的方式
  3. 使用Docker:docker pull nginx

安装好之后,执行nginx.exe 即可启动服务,在浏览器中 localhost 即可访问,

nginx -s quit/stop 停止服务

nginx.conf为配置文件,规定了一些work数量,文件类型等。nginx -s reload 修改之后重新加载(signal)

hexo

需要装hexo,前提需安装 Node.js和 git

npm install -g hexo-cli;hexo init blog;
cd blog;
npm install;	# 安装hexo默认的依赖
hexo g;		# generate 生成静态文件
hexo s;		# server 本地开发服务器,通常在localhost:4000
# 此时只是hexo的服务# 把hexo生成的blog部署的nginx:把blog/public/* 复制到nginx的html下即可。

反向代理

先安装go:choco install go 默认C:\Program Files\Go\bin

main_8000.go;然后创建内容相同的main_8001.go; main_80001.go;

package mainimport ("fmt""net/http"
)func handler(w http.ResponseWriter, r *http.Request) {fmt.Fprintf(w, "Hello, World!8000")
}func main() {// 设置处理请求的路由http.HandleFunc("/", handler)// 启动服务器,监听8080端口fmt.Println("Server is running on http://localhost:8000")if err := http.ListenAndServe(":8000", nil); err != nil {fmt.Println("Error starting server:", err)}
}

启动服务

go run main_8000.go;	# 其他两个同理# 浏览器中可以localhost:8000 访问

配置反向代理nginx.conf:通过 localhost/app 即可轮训访问8000\8001\8002,

http{...upstream backend {ip_hash;server 127.0.0.1:8000 weight=3;server 127.0.0.1:8001;server 127.0.0.1:8002;}server {...;location /app {proxy_pass http://backend;}}...
}

负载均衡:weight=3表示大部分在此服务器;ip_hash表示在一台服务器比如只在8000,解决session互传

HTTPS配置

HTTP + SSL = HTTPS。默认http端口为80,https端口为443。一些主流的云平台可以申请到免费的ssl(Secure Sockets Layer)证书,也可以通过自签名生成证书和密钥,已经被TLS(Transport Layer Security)所取代。

安装openssl命令:choco 。默认C:\Program Files\SSL\bin

cd ssl	# 创建一个ssl文件夹
# 
openssl genpkey -algorithm RSA -out server.key
openssl req -new -key server.key -out server.csr	# 输入对应的信息,比如国家,公司,邮箱...
openssl x509 -req -in server.csr -signkey server.key -out server.crt

nginx.config

# 解决重定向问题	
server {listen      80;server_name localhost;# 重定向到 HTTPS 版本return 301 https://localhost$request_uri;
}server {listen 443 ssl;  # 监听 443 端口,并启用 SSLserver_name localhost;  # 你的域名ssl_certificate     D:/environment/nginx-1.27.3/ssl/server.crt;  # 证书文件ssl_certificate_key D:/environment/nginx-1.27.3/ssl/server.key;  # 私钥文件ssl_protocols TLSv1.2 TLSv1.3;  # 推荐的 SSL/TLS 协议版本# ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256';  # 强加密套件ssl_prefer_server_ciphers on;  # 强制使用服务器配置的加密算法# ssl_dhparam /path/to/dhparam.pem;  # Diffie-Hellman 参数,用于增加安全性,确保生成该文件(见后文)ssl_session_cache shared:SSL:10m;  # 缓存会话以提高性能ssl_session_timeout 1d;  # 设置 SSL 会话超时# listen       80;# server_name  localhost;#charset koi8-r;location /app {proxy_pass http://backend;}
}

然后 https://localhost

虚拟机

demo1:

可以在一台服务器部署多个站点,比如一个server 就相当于一个服务器

为了方便表示nginx.conf 的 server 配置在servers/local.conf 中

# nginx.conf 
http {...;include servers/*.conf;
}# 新建servers/local.conf,把nginx.conf 中的server拷过来
server{}

demo2:

npm create vite	# 选择Vue和TypeScript
npm install # 安装依赖node_modules/
npm run build	# 生成dist/ 下面有index.html

同样把这个网站部署到nginx上

server {listen 5173;server_name localhost; location / {root D:/environment/nginx-1.27.3/vuedemo/dist;index index.html index.htm;}
}

然后 https://localhost:5173

MySQL

数据库DB是按照数据结构进行组织、存储、管理数据的仓库,DBMS是数据库管理系统,常见RDBMS有MySQL

安装:

  1. 命令行,choco | apt
  2. win在官网下载安装包
  3. docker pull mysql

需要进行一些配置

# 创建文件在项目下 my.init
[mysqld]
basedir=D:\environment\mysql-8.0.33-winx64\
datadir=D:\environment\mysql-8.0.33-winx64\data\
port=3306# 输入命令
mysqld --initialize		# 初始化mysql,会生成data
mysqld --install		
net start mysql		# 启动mysql服务
mysql -u root -p	# 登陆,密码在data/*.err
alter user 'root'@'localhost' identified with mysql_native_password by 'newpassworld';

常用命令

show databases;
use mysql;
show tables;
select * from tables_priv; 

Redis

MongoDB

Docker

Kubernetes

堡垒机

Node.js

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境:

  1. 异步和事件驱动:非阻塞 I/O 模型,适用于大量并发
  2. 单线程
  3. 模块化,内置模块(fs、http、path)

安装:

  1. 下载Node.js安装包到environment\目录下。node -v | npm -v 测试
  2. 目录下创建文件夹node_cache,node_global。默认
npm config set prefix  "...\Nodejs\node_global"
npm config set cache "...\Nodejs\node_cache"
npm config get registry		# 配置国内镜像npm config get prefix
npm config list
  1. 系统变量,NODE_PATH为…\Nodejs\node_global\node_modules。并在PATH中添加%NODE_PATH%
  2. 用户变量,…\AppData\Roaming\npm修改为…\Nodejs\node_global
  3. 测试:npm install express -g 安装在\node_global\node_modules\express

Windows

命令

tasklist | findstr "nginx"	# 查找任务
taskkill /f /t /im nginx.exe	# 终止任务,f强制,t递归子进程,im映像名称# net命令:网络和系统管理
net stop nginx # 先停止系统的nginx服务,否则停止nginx,也会重新启动# netstat:查看端口
netstat -ano 	# a:all n:number o:pid

常见问题

端口占用

# 8080 端口被占用
netstat -ano | findstr "8080"	# 查找端口对应的pid(1234)
tasklist | findstr "1234" 	# 根据pid找到任务,
# 终止任务
tasklist /f /t /pid 1234	
tasklist /f /t /im demo.task	

tps://localhost:5173`

MySQL

数据库DB是按照数据结构进行组织、存储、管理数据的仓库,DBMS是数据库管理系统,常见RDBMS有MySQL

安装:

  1. 命令行,choco | apt
  2. win在官网下载安装包
  3. docker pull mysql

需要进行一些配置

# 创建文件在项目下 my.init
[mysqld]
basedir=D:\environment\mysql-8.0.33-winx64\
datadir=D:\environment\mysql-8.0.33-winx64\data\
port=3306# 输入命令
mysqld --initialize		# 初始化mysql,会生成data
mysqld --install		
net start mysql		# 启动mysql服务
mysql -u root -p	# 登陆,密码在data/*.err
alter user 'root'@'localhost' identified with mysql_native_password by 'newpassworld';

常用命令

show databases;
use mysql;
show tables;
select * from tables_priv; 

Redis

MongoDB

Docker

Kubernetes

堡垒机

Node.js

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境:

  1. 异步和事件驱动:非阻塞 I/O 模型,适用于大量并发
  2. 单线程
  3. 模块化,内置模块(fs、http、path)

安装:

  1. 下载Node.js安装包到environment\目录下。node -v | npm -v 测试
  2. 目录下创建文件夹node_cache,node_global。默认
npm config set prefix  "...\Nodejs\node_global"
npm config set cache "...\Nodejs\node_cache"
npm config get registry		# 配置国内镜像npm config get prefix
npm config list
  1. 系统变量,NODE_PATH为…\Nodejs\node_global\node_modules。并在PATH中添加%NODE_PATH%
  2. 用户变量,…\AppData\Roaming\npm修改为…\Nodejs\node_global
  3. 测试:npm install express -g 安装在\node_global\node_modules\express

Windows

命令

tasklist | findstr "nginx"	# 查找任务
taskkill /f /t /im nginx.exe	# 终止任务,f强制,t递归子进程,im映像名称# net命令:网络和系统管理
net stop nginx # 先停止系统的nginx服务,否则停止nginx,也会重新启动# netstat:查看端口
netstat -ano 	# a:all n:number o:pid

常见问题

端口占用

# 8080 端口被占用
netstat -ano | findstr "8080"	# 查找端口对应的pid(1234)
tasklist | findstr "1234" 	# 根据pid找到任务,
# 终止任务
tasklist /f /t /pid 1234	
tasklist /f /t /im demo.task	

http://www.ppmy.cn/embedded/156388.html

相关文章

【玩转全栈】----Django模板的继承

先赞后看&#xff0c;养成习惯&#xff01;&#xff01;&#xff01; 目录 模板继承的好处 模板继承的语法规则 更新代码 上文中的部门管理页面&#xff1a; 【玩转全栈】----Django制作部门管理页面-CSDN博客 大家会发现&#xff0c;由于定义了多个html文件&#xff0c;多个ht…

ElasticSearch是什么?基于Lucene的,那么为什么不是直接使用Lucene呢?

目录 ElasticSearch概述 Lucene与ElasticSearch的关系 为什么不直接使用Lucene 一个ES和数据库的对比 ElasticSearch是一个分布式的、开源的、实时的搜索和分析引擎,它是基于Apache Lucene构建的,旨在提供快速、可扩展、高性能的搜索解决方案。以下是对ElasticSearch及其…

graylog~认识一下-日志管理平台

1、介绍 Graylog 是一个开源的日志管理和分析平台&#xff0c;旨在帮助企业集中收集、存储、搜索和分析来自各种来源的日志数据。它提供了强大的实时日志处理能力&#xff0c;适用于大规模分布式系统和复杂的生产环境。 主要功能 集中化日志管理&#xff1a; 收集来自不同来源…

MongoDB的索引与聚合

一、实验目的 1. 理解索引的概念及其在MongoDB中的重要性和作用。 2. 学习如何选择适合建立索引的字段。 3. 掌握如何创建、删除索引以及如何强制使用索引。 4. 熟悉MongoDB的聚合框架和MapReduce工具&#xff0c;以及简单聚合命令的使用。 二、实验环境准备 1. JAV…

云原生前端开发:打造现代化高性能的用户体验

引言&#xff1a;前端开发的新风向 在过去的几年中&#xff0c;前端开发领域经历了快速的演变&#xff0c;从早期的静态网页到如今复杂的单页应用&#xff08;SPA&#xff09;&#xff0c;再到微前端架构和渐进式Web应用&#xff08;PWA&#xff09;&#xff0c;前端技术一直处…

Axios发起HTTP请求时的先后执行顺序

书写如下代码时&#xff0c;日志输出的顺序不可控&#xff0c;可能是"you How are"&#xff0c;也可能是"you are How" <script> import axios from axios export default {created() {this.fn1()this.fn2()console.log(you)},methods: {fn1() {axi…

C语言程序设计十大排序—插入排序

文章目录 1.概念✅2.插入排序&#x1f388;3.代码实现✅3.1 直接写✨3.2 函数✨ 4.总结✅5.十大排序 1.概念✅ 排序是数据处理的基本操作之一&#xff0c;每次算法竞赛都很多题目用到排序。排序算法是计算机科学中基础且常用的算法&#xff0c;排序后的数据更易于处理和查找。在…

通过以太网加载linux内核、设备树、根文件系统方法(以stm32MP135为例)

0 硬件平台 正点原子stm32MP135开发板 1 通过以太网加载linux内核、设备树、根文件系统方法&#xff08;以stm32MP135为例&#xff09; 在产品正式发布前&#xff0c;为了调试方便&#xff0c;我们可以使用以太网加载linux内核、设备树、根文件系统以加快调试速度。本文以stm3…