linux集群架构--tomact集群2

linux集群架构--tomact集群2

接入nginx

bash 复制代码
[root@web03 /app/tools/tomact]#echo test >webapps/index.jsp
[root@web03 /app/tools/tomact]#curl 192.168.65.9:8080/index.jsp


  • 发现页面不对,访问的是test,返回的信息是

    在这里插入图片描述

  • 为什么会成这样?

bash 复制代码
tomcat访问的灵异事件

访问的时候  zrlog.wulinlinux.cn:8080/zrlog/

ROOT用户访问的时候不加上路径,直接访问文件,就会访问ROOT下面的内容.

zrlog.wulinlinux.cn:8080/wulin.jsp = webapps/ROOT/wulinssw.jsp

zrlog.wulinlinux.cn:8080/wulin/wulinssw.jsp


改名--因为与数据库db01是相连的

  • 访问浏览器,这个时候安装一下zrlog

    会发现现在不会在进行报错了,原因是因为没有zrlog目录
  • 数据库配置文件
bash 复制代码
[root@web03 /app/tools/tomcat/webapps/ROOT]#find -type f |xargs grep '172.16.1.51'

[root@web03 /app/tools/tomcat/webapps/ROOT]# cat
./WEB-INF/db.properties
#This is a database configuration file
#Wed jun 22 09:05:24 CST 2024

driverClass=com.mysql.cj.jdbc.Driver
user=zrlog
password=1
jdbcUrl=jdbc\:mysql\://172.16.1.51\:3306/zrlog?
characterEncoding\=UTF-8&allowPublicKeyRetrieval\=true&useSSL\=false&ser
verTimezone\=GMT
#jdbcUrl=jdbc\:mysql\://数据库地址\:3306/数据库名字?characterEncoding\UTF-8&allowPublicKEYRetrieval\=true&useSSL\=false&serverTimezone\GMT
[root@web03 /app/tools/tomcat/webapps/ROOT]#
  • zrlog.war改名为ROOT.war然后部署.
  • ngx配置文件web上的nginx,不是负载上的)
    [root@web03 ~]# find /var/cache/yum/ -type f -name "*.rpm"
    /var/cache/yum/x86_64/7/base/packages/price2-2--1.el7.ngx x86_64.rpm
    /var/cache/yum/x86_64/7/nginx-stable/packages/nginx-1.22.1.el7.ngx.x86_64.rpm

[root@web03 ~]#mkdir -p /app/rpms/

[root@web03 ~]# find /var/cache/yum/ -type f -name "*.rpm" |xargs cp -t /app/rpms/

#这里到时候安装一个内部的yum源,安装的就更快了

[root@web03 /etc/nginx/conf.d]# cat zrlog.wulinlinux.cn.conf

server {

listen 80;

server_name zrlog.wulinlinux.cn;

#思考,用户将请求发给nginx,nginx把进行发送给comact(有点类似于nginx代理

   error_log     /var/log/nginx/zrlog.wulinlinux.cn-error.log

notice;

access_log /var/log/nginx/zrlog.wulinlinux.cn-access.log main;

location / {

proxy_pass http://127.0.0.1:8080;

proxy_set_header Host $http_host;

proxy_set_header X-Forwarded-For

$proxy_add_x_forwarded_for;

}

}

[root@web03 /etc/nginx/conf.d]#nginx -t 检查语法

[root@web03 /etc/nginx/conf.d]#systemctl enable nginx #进行开机自启动

[root@web03 /etc/nginx/conf.d]#systemctl start nginx #开启nginx

#配置解析

#浏览器访问zrlog.wulinlinux.cn网站进行管理

tomact+nginx动静分离

bash 复制代码
需要开发拆开代码,把静态资源拆分出来单独进行存放


bash 复制代码
[root@web03 /etc/nginx/conf.d]# cat  zrlog.wulinlinux.cn.conf
server {
       listen 80;
       server_name zrlog.wulinlinux.cn;
#思考,用户将请求发给nginx,nginx把进行发送给comact(有点类似于nginx代理

       error_log     /var/log/nginx/zrlog.wulinlinux.cn-error.log
notice;
       access_log /var/log/nginx/zrlog.wulinlinux.cn-access.log main;
location / {
       proxy_pass http://127.0.0.1:8080;
       proxy_set_header Host $http_host;
       proxy_set_header X-Forwarded-For
$proxy_add_x_forwarded_for;
       }
       location ~* \.(js|html|css|png|jpg|jpeg)$ {
       expries 7d;
       #proxy_pass http://127.0.0.1:8080;
       #proxy_set_header Host $http_host;
       #proxy_set_header X-Forwarded-For$proxy_add_x_forwarded_for;
       }
}

[root@web03 /etc/nginx/conf.d]#nginx -t 检查语法
#访问网站,会发现一个问题
  • 浏览器解析,说明网站nginx出现问题
  • 重新启动nginx服务
  • 解决问题
  • 但是这种严格上来说这种拆开代码不算是真正的动静分类

#生产环境

user nginx; worker_processes 4; worker_cpu_affinity 0001 0010 0100

1000;

error_log /data/logs/nginx/error.log warn; pid /logs/nginx.pid;

worker_rlimit_nofile 65535; events {

use epoll;

workera_connections 10240; }

http {

include mime.types;

default_type application/octet-stream;

 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 /data/logs/nginx/access.log  main;
 
 charset utf-8;
 
 server_names_hash_bnucket_size 128;
 client_header_buffer_size   32k;
 large_client_header_buffers 4 32k;
 client_max_body_size  300m;
 sendfile  on;
 tcp_nopush     on;
 keepalive_timeout  60;
 tcp_nodelay  on;
 server_tokens off;
 client_body_buffer_size 512k;
 
 client_header_timeout   3m;
 client_body_timeout     3m;
 send_timeout            3m;
 
 ##cache##
 proxy_connect_timeout  5;
 proxy_read_timeout   5;
 proxy_send_timeout   60;
 proxy_buffer_size    64k;
 proxy_buffers 4 256k;
 proxy_temp_path /tmp/proxy_temp;
 proxy_cache_path /tmp/cache levels=1:2 keys_zone=cache_one:100m inactive=1d max_size=3000m;
 proxy_cache_key "$scheme$request_method$host$request_uri";
 
 ##end##
 
 gzip on;
 gzip_min_length  1100;
 gzip_comp_level 5;
 gzip_buffers   4   8k;
 gzip_types  text/xml text/plain text/css text/javascript  application/javascript application/json;
 
 #  output_buffers  1 32k;
 #  postpone_output 1460;
 
 #limit_buffers   1  32k;
 #postpone_output 1460;
 
 limit_rate_after  3m;
 limit_rate 512k;
 
 #自动补全"/"
 #if (-d $request_filename){
    #rewrite ^/([^/]$ http://$host/$1$2/ last;
    
 }
 #online server
 server {
      listen 80;
      server_name dbjyj.wulin.com www.wulin.com.cn vpn.wulin.com;
   index  index.jsp;
         proxy_set_header Host $host:$server_port;
         proxy_set_header REMOTE-HOST $remote_addr;
         proxy_set_header X-Real-IP $remote_addr;
         proxy_cache  cache one;
         
    location ~ / {
      rewrite ^/$ http://$host:8081/online last;
    }
    ###############动静分离配置###############
    
    ###############设定访问静态文件直接读取不经过tomact###########
    location ~ \.(html|html|gif|jpg|jpeg|png|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)(.*)$

{

expries max;

}

location ~ .(js|css|jsp|json)$ {

root /data/www;

expries 1d;

}

####################动静分离-配置完成############

    location ~ .*/api/mc/custormer/deliverAddress/list.json* {
          return 404;
    }
       location ^~ /online/ {
               proxy_pass        http://10.0.0.6:8081;
               proxy_cache cache_one;
               proxy_cache_valid 200 1h;
               proxy_cache_valid 302 10m;
               proxy_cache_valid any 1m;
       }
       location ^~ /onlinethread/ {
               proxy_pass        http://10.0.0.6:8081;
               proxy_cache cache_one;
               proxy_cache_valid 200 1h;
               proxy_cache_valid 302 10m;
               proxy_cache_valid any 1m;
       }
       location ^~ /mobile/ {
               proxy_pass        http://10.0.0.6:8081;
               proxy_cache cache_one;
               proxy_cache_valid 200 1h;
               proxy_cache_valid 302 10m;
               proxy_cache_valid any 1m;
       }
 }
 #12200 server
 server {
  listen 8080;
  server_name wulin.c0m www.b-long.com.cn brainlong.gcip.net;
  proxy_set_header Host:$server_port;
  proxy_set_header REMOTE-HOST $remote_addr;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_cache  cache_one;
  
  index index.jsp;
 }
 location ~ \.(html|html|gif|jpg|jpeg|png|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)(.*)$

{root /data/www;

expries max;

}

location ~ /data/www;

expries 1d;

}

8080 ##### location ^~ /ccbs/ {

 proxy_pass  http://10.0.0.6:8080;
 proxy_cache cache_one;
 proxy_cache_valid 200 1h;
 proxy_cache_valid 302 10m;
 proxy_cache_valid any 1m; } 

console server location ^~ /console/ {

proxy_pass   http://10.0.0.6:8080;
proxy_cache cache_one;
proxy_cache_valid 200 1h; }
  • 浏览器访问

zrlog.wulinlinux.cn:8081/test.jsp

  • 过滤

未来生产上,可以直接把tomcat+应用整体打包,使用的时候直接解压即可

Tomact监控功能

概述

  • 未来通过各种监控工具(Zabbix/Grafana/Prometheus/...),监控Tomcat/java.
  • 需要我们开启java远程监控功能(JMX remote)

步骤

  • tomcat配置中修改tomcat启动的选项.开启jmx远程监控功能.
  • 交给zbx就可以了(使用windows jdk连接tomcat).
bash 复制代码
catalina.sh文件中125后面
CATALINA_OPTSjava环境变量,指定java启动的时候的选项

[root@web03 /app/tools ~]#vim tomact/bin/catalina.sh

CATALINA_OPTS="$CATALINA_OPTS   \
-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=12345 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Djava.rmi.server.hostname=10.0.0.9"

[root@web03 /app/tools ~]#systemctl restart tomact
[root@web03 /app/tools ~]#ps -ef |grep java
/app/tools/jdk/bin/java -Djava.util.logging.config.file=/app/tools/tomcat/conf/logging.properties
-Diava.util.logging.manager=org.apache.juli.classLoaderLogManager 
-Djdk.tls.ephemeralDHkeysize-2048 
-Djdk.protocol .handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SeeurityListener.UMASK=8827-Dcom,sun.management.imxremote -Dcom,sun.management,imxremote,port=12345 -Dcom,sun.management.imxremote.authenticate=false-Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server,hostname=18.0.0.9 -Dignore.endorsed.dirs= -classpath /app/toolstomcat/bin/bootstrap.iar: /app/tools/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/app/tools/tomcat -Dcatalina.home=/app/toolstomcat -Djava.io.tmpdir=/app/tools/tomcat/temp org.apache.catalina.startup.Bootstrap start
[root@web03 /app/tools ~]#ss -lntup |grep java (有两个随机端口)
bash 复制代码
> ```bash
> > 温馨提示:
> > 1.从tomcat 8.5开始配置的每一行要通过\进行续行
> 
> > 修改后java进程中增加了上面添加的那些选项 ```/app/tools/jdk/bin/java
>  - Djava.util.logging.config.file=/app/tools/tomcat/con f/logging.properties
>  - Djava.util.logging.manager=org.apache.juli.ClassLoad erLogManager  -Djdk.tls.ephemeralDHKeySize=2048
>  - Djava.protocol.handler.pkgs=org.apache.catalina.webr esources  -Dorg.apache.catalina.security.SecurityListener.UMASK
> =0027  -Dcom.sun.management.jmxremote  -Dcom.sun.management.jmxremote.port=12345  -Dcom.sun.management.jmxremote.authenticate=false  -Dcom.sun.management.jmxremote.ssl=false  -Djava.rmi.server.hostname=10.0.0.9  -Dignore.endorsed.dirs= -classpath /app/tools/tomcat/bin/bootstrap.jar:/app/tools/tomca t/bin/tomcat-juli.jar - Dcatalina.base=/app/tools/tomcat -
> Dcatalina.home=/app/tools/tomcat -
> Djava.io.tmpdir=/app/tools/tomcat/temp
> org.apache.catalina.startup.Bootstrap start
  • 在windows下,通过jdk连接tomcat(模拟监控软件连接)

C:\Program Files\Java\jdk1.8.0_201\bin\jconsole.exe

  • 安装jdk_1.80_64bit.exe(一直选择进行下一步)








  • 选择不安全的连接


    当前jvm内存使用情况:

有一个执行GC(G)这个是垃圾回收站

以上这些页面,未来使用zabbix进行监控

掌握开启监控功能

Java故障案例

Java监控命令

bash 复制代码
```bash
命令(j打头)

​        jps(jdk提供的)

​        jstack

​        jmap

脚本,执行与查看结果即可

a.jps

bash 复制代码
[root@web03 /app/tools]#jps
78900 Bootstrap
68458 plugin-core.jar
7012  jps
[root@web03 /app/tools]#ps -ef |grep jagva

jps》》 java ps命令,只显示java进程.类似于ps -ef |grep java
[root@web03 /app/tools]#jps -lvm|grep tomcat-8081

b.jstack

jstack查看java进程内部信息,线程信息.

进程:占空间,占系统资源,厂房.

线程:厂房里面的工人,处理与用户的请求.

需要代码使用多线程技术.通过ps aux查看进程是否支持线程(是否使用多线程技术)

> 先过滤出java进程的pid

查看java进程的线程信息

jstack 1786

查看java线程状态

jstack 1786 |grep -i state

bash 复制代码
[root@web03 /app/tools]#jstack --help
Usage:
    jstack [-l] <pid>pid为进程
        (to connect to running process)
    jstack -F [-m] [-l] <pid>
        (to connect to a hung process)
    jstack [-m] [-l] <executable> <core>
        (to connect to a core file)
    jstack [-m] [-l] [server_id@]<remote server IP or hostname>
        (to connect to a remote debug server)

Options:
    -F  to force a thread dump. Use when jstack <pid> does not respond (process is hung)
    -m  to print both java and native frames (mixed mode)
    -l  long listing. Prints additional information about locks
    -h or -help to print this help message							

1、新建状态New;

2、就绪状态Runnable;

3、运行状态Running;

4、阻塞状态Blocked;

5、死亡状态Dead。

c.jsp

jmap查看或导出jvm信息

查看jvm使用情况

map -heap java-pid导出java进程的jvm 内存使用情况

导出jvm内存镜像

c 复制代码
```bash
未来生产环境该文件较大

```cjmap -dump:format=b,file=8081.hprof   1786
Dumping heap to /root/8081.hprof ...
Heap dump file created
[root@web03 ~]# ll -h 8081.hprof
-rw------- 1 root root 20M Sep 19 09:43 8081.hprof

d.mat分析工具

bash 复制代码
jvm内存映像文件,在windows/mac/ubuntu系统下通过MemoryAnalyzer Tool (MA/MAT)

1.需要jdk环境

2.软件包解压即可使用

3. MemoryAnalyzer.exe

 下载地址:https://www.eclipse.org/mat/downloads.php


jvm.dup/改名为jvm.hprof结尾,打开界面:

命令小结

​ jps-查看java进程信息(pid,进程名字),更加详细信息看ps

​ jstack-查看java线程信息,过滤线程状态

​ jmap-查看jvm内存信息(导出)

脚本

bash 复制代码
show-busy-java-thread.sh显示当前环境中,所有繁忙的java线程.以百分数显示使用率最高的前几个线程.

java应用负载高故障案例

排查流程小结:

  1. 通过监控服务发现系统负载高

涉及命令:zabbix,Prometheus,告警

  1. 登录到对应的节点,通过命令检查系统负载是否高

设计命令:w,uptime,top,lscpu;cpu核心总数与负载对比

  1. 真的高,定位什么导致的系统负载高

涉及命令top,ps,aux,iotop,vmstat;判断cpu,io导致的

  1. 找出原因并且找出对应的进程,需要根据进程找服务相关

根据找出的进程,查看日志信息

  1. java进程查看进程中的线程信息,

设计命令jps,jstack

  1. 导出jvm信息,通过mat工具进行分析

设计命令jmap,MA需要与开发进行一起看

java会话共享方案

Tomact配置https

  • 下载tomact使用证书(阿里云)
  • 修改配置文件(配置跳转)

应用建议

tomact可以支持https,可以在tomact中配置https证书。未来可以在nginx中配置证书加密,tomact未进行加密

  • tomact配置文件
bash 复制代码
 `[root@web03 /app/tools/tomcat]# mkdir cert
#部署代码包
[root@web03 /app/tools/tomcat/cert]#vim ../conf/server.xml`
bash 复制代码
[root@web03 /app/tools/tomcat/conf]# cat server.xml
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
    <Listener
        className="org.apache.catalina.startup.VersionLogger
    Listener" />
<Listener
    className="org.apache.catalina.core.AprLifecycleList
ener" SSLEngine="on" />
    <Listener
className="org.apache.catalina.core.JreMemoryLeakPre
ventionListener" />
    <Listener
className="org.apache.catalina.mbeans.GlobalResource
sLifecycleListener" />
    <Listener
className="org.apache.catalina.core.ThreadLocalLeakP
reventionListener" />
<GlobalNamingResources>
<Resource name="UserDatabase"
auth="Container"
type="org.apache.catalina.UserDatabase"
             description="User database that can be
updated and saved"
factory="org.apache.catalina.users.MemoryUserDataba
seFactory"
             pathname="conf/tomcat-users.xml" />
</lobalNamingResources>
<Service name="Catalina">
<Connector port="8080"
protocol="HTTP/1.1"
              connectionTimeout="20000"
              redirectPort="8443" />
<Connector port="8443"  
   protocol="HTTP/1.1"
   SSLEnabled="true"
   scheme="https"
   secure="true"
keystoreFile="/app/tools/tomcat/cert/ssl.wulinlinu
x.cn.pfx"
   keystoreType="PKCS12"
   ystorePass="AGrnHD9j"  
   clientAuth="false"
   SSLProtocol="TLSv1.1+TLSv1.2+TLSv1.3"
ciphers="TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_
AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,T
LS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AE
S_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA256"/>
<Engine name="Catalina"
defaultHost="localhost">
<Realm
className="org.apache.catalina.realm.LockOutRealm">
<Realm
className="org.apache.catalina.realm.UserDatabaseRea
lm"
              resourceName="UserDatabase"/>
</Realm>
<Host name="localhost"  appBase="webapps"
           unpackWARs="true"
autoDeploy="true">
     
<Valve
className="org.apache.catalina.valves.AccessLogValve
"
directory="logs"
              prefix="localhost_access"
suffix=".log"
              pattern="%h %l %u %t &quot;%r&quot;
%s %b &quot;%{Referer}i&quot; &quot;%{User
Agent}i&quot; &quot;%{X-Forwarded-For}i&quot;" />
</Host>
</Engine>
</Service>
</Server>

访问测试:https://ssl.wulinlinux.cn:8443
配置http-->https


说明:关于tomcat其他类型的证书格式配置  jks格式
keystoreFile="/app/tools/tomcat/cert/ssl.wulinlinux.cn.jks"
keystoreType="PKCS12" #删除这一行
keystorePass="AGrnHD9j"#密码
访问测试:https://ssl.wulinlinux.cn:8443
配置tomcat --->http8080--->ttps 8443

web.xml的在文件</welocme-file-list>后添加以下内容
<login-config>
    <!---AUTHorization setting for SSL  -->
    <auth-method<CLIENT-CERT</AUTH-method>
    <realm-name>Client Cert Users-only Area</real-name>
</login-config>
<security-constraint>
        <!--Authorization  setting for  SSL-->
        <web-resource-name>ssl</web-resource-name>
            <web-resource-name>ssl</web-resource-name>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <user-data-constraint>
              <transport-gurantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
</security-constraint>
        
bash 复制代码
[root@web03 /app/tools/tomcat/cert]#systemctl restart tomact
##做本地解析




tomcat-https小结

获取tomcat证书

​ tomcat server.xml文件8443

tomcat集群

​ nginx+tomcat

​ 与之前ngx+php https一致的

nginx中有两个结尾:

  • .pfx(公钥)
  • pfx-password.txt(私钥)

tomact:

  • .pfx(证书)
  • password(证书密码文件)

java前后端分离项目

Tomcat动静分离.提取出静态资源.

静态资源:前端(html,css,js).

后端:(Java,PHP,Python,Golang...)连接使用数据库.

前后端分离,拆分为前端部分和后端部分,一般前后端通过API接口的进行连接.

API应用程序接口:开发人员书写好的,可以直接调用的代码.使用的人员不需要关注功能如何实现的,只需要关注如何调用接口即可.

API接口在各种服务中广泛存在

前端分离

前端(静态资源)

API接口(Rest API)

后端(动态功能)

(2)数据库准备db02

bash 复制代码
#解压,环境准备
mkdir -p /app/tools/   /app/data/3306/
tax xf mysql-8.9.27-linux-glibc2.12-x86_64.tar.xz -C /app/tools/
ln -s /app/tools/mysql-8.0.27-linux-glibc2.12-x86_64/  /app/tools/mysql
yum install ncurses-devel libaio-devel openssl openssl-devel   -y

#配置文件,用户
useradd -s /sbin/nologin   -M  mysql

#设置配置文件
cat >/etc/my.cnf<<"EOF"

[mysqld]
#用户
user=mysql 
###安装目录
basedir=/app/tools/mysql/
###数据目录
datadir=/app/tools/3306/
port=3306
socket=/tmp/mysql.sock
[client]
socket=/tmp/mysql.sock
EOF

cat /etc/my.cnf
#修改配置和数据目录的所有者
chown mysql.mysql /etc/my.cnf
chown -R mysql.mysql /app/data/3306

#配置PATH环境变量
echo 'export PATH=/app/tools/mysql/bin:$PATH' >>/etc/profile
source /etc/profile
#检查
mysql -V

初始化数据库:

bash 复制代码
mysqld --initialize-insecure --user=mysql \
--basedir=/app/tools/mysql/ --datadir=/app/data/3306/
echo $?

启动:

bash 复制代码
#拷贝已经准备好的启动管理文件
cp /app/tools/mysql/sipport-files/mysql.server   /etc/onit.d/mysqld
#开机自启动服务,运行服务
systemctl enable mysqld
systemctl start  mysqld

今天这篇先更新到这里,整理好后续补充!!!

相关推荐
小陈phd17 分钟前
Vscode LinuxC++环境配置
linux·c++·vscode
运维&陈同学20 分钟前
【zookeeper01】消息队列与微服务之zookeeper工作原理
运维·分布式·微服务·zookeeper·云原生·架构·消息队列
是阿建吖!21 分钟前
【Linux】进程状态
linux·运维
明明跟你说过1 小时前
Linux中的【tcpdump】:深入介绍与实战使用
linux·运维·测试工具·tcpdump
Komorebi.py2 小时前
【Linux】-学习笔记05
linux·笔记·学习
Mr_Xuhhh2 小时前
重生之我在学环境变量
linux·运维·服务器·前端·chrome·算法
内核程序员kevin5 小时前
TCP Listen 队列详解与优化指南
linux·网络·tcp/ip
朝九晚五ฺ9 小时前
【Linux探索学习】第十四弹——进程优先级:深入理解操作系统中的进程优先级
linux·运维·学习
自由的dream9 小时前
Linux的桌面
linux
xiaozhiwise10 小时前
Makefile 之 自动化变量
linux