zoukankan      html  css  js  c++  java
  • 项目案例之Pipeline流水线及流水线发布PHP项目(二)

    项目案例之Pipeline流水线及流水线发布PHP项目(二)

    链接:https://pan.baidu.com/s/1NZZbocZuNwtQS0eGkkglXQ
    提取码:z7gj
    复制这段内容后打开百度网盘手机App,操作更方便哦

    4.Jenkins的Pipeline流水线

    主机名 IP地址 备注
    Git 192.168.200.61 Git服务器
    Jenkins 192.168.200.62 Jenkins服务器
    [root@Git ~]# cat /etc/redhat-release 
    CentOS Linux release 7.5.1804 (Core) 
    [root@Git ~]# uname -r
    3.10.0-862.3.3.el7.x86_64
    [root@Git ~]# systemctl stop firewalld
    [root@Git ~]# systemctl disable firewalld
    [root@Git ~]# systemctl stop NetworkManager
    [root@Git ~]# systemctl disable NetworkManager
    

    4.1 创建一个基于Pipeline流水线的项目

    image.png-87.9kB

    4.2 添加项目Git参数化构建

    image.png-166.1kB

    image.png-28.4kB

    4.3 Pipeline脚本语法架构介绍

    #Pipeline脚本语法架构
    node ('slave节点名') {          #被操控的节点服务器
        def 变量    #def可以进行变量声明
        stage('阶段名A'){     #流水线阶段一
            执行步骤A
            执行步骤B
            执行步骤C
        }
        stage('阶段名B'){     #流水线阶段二
            执行步骤A
            执行步骤B
            执行步骤C
        }
        stage('阶段名C'){     #流水线阶段三
            执行步骤A
            执行步骤B
            执行步骤C
        }
    }
    

    image.png-37.1kB

    #流水线模板脚本
    node {
       def mvnHome
       stage('Preparation') { // for display purposes
          // Get some code from a GitHub repository
          git 'https://github.com/jglick/simple-maven-project-with-tests.git'
          // Get the Maven tool.
          // ** NOTE: This 'M3' Maven tool must be configured
          // **       in the global configuration.           
          mvnHome = tool 'M3'
       }
       stage('Build') {
          // Run the maven build
          if (isUnix()) {
             sh "'${mvnHome}/bin/mvn' -Dmaven.test.failure.ignore clean package"
          } else {
             bat(/"${mvnHome}inmvn" -Dmaven.test.failure.ignore clean package/)
          }
       }
       stage('Results') {
          junit '**/target/surefire-reports/TEST-*.xml'
          archive 'target/*.jar'
       }
    }
    

    4.4利用Pipeline Syntax,编写Pipeline Script并构建

    (1)进入Pipeline Syntax

    image.png-41.2kB

    (2)通过脚本代码生成器,生成Pipeline脚本代码

    image.png-95.8kB

    image.png-66.3kB

    (3)将生成的代码复制到流水线脚本相应步骤的stage函数里

    image.png-254kB

    (4)开始构建Pipeline项目

    image.png-37.6kB

    image.png-37.3kB

    4.5 从远程仓库下载Pipeline Script,并构建

    (1)在Git服务器上创建一个存放Pipeline脚本的仓库

    [root@Git ~]# su - git
    上一次登录:二 10月 23 18:59:42 CST 2018pts/0 上
    [git@Git ~]$ cd /home/git/repos/
    [git@Git repos]$ ls
    app.git
    [git@Git repos]$ mkdir jenkinsfile        #创建存放Pipeline脚本的仓库
    [git@Git repos]$ cd jenkinsfile/
    [git@Git jenkinsfile]$ git --bare init    #初始化仓库
    初始化空的 Git 版本库于 /home/git/repos/jenkinsfile/
    

    (2)在jenkins服务器上,往远程仓库提交一个Pipeline脚本。

    [root@Jenkins ~]# mkdir /test
    [root@Jenkins ~]# cd /test/
    [root@Jenkins test]# git clone git@192.168.200.61:/home/git/repos/jenkinsfile
    正克隆到 'jenkinsfile'...
    warning: 您似乎克隆了一个空版本库。
    [root@Jenkins test]# ls
    jenkinsfile
    
    
    [root@Jenkins test]# cd jenkinsfile/
    [root@Jenkins jenkinsfile]# mkdir itemA
    [root@Jenkins jenkinsfile]# vim itemA/jenkinsfile
    [root@Jenkins jenkinsfile]# cat itemA/jenkinsfile
    node {
       def mvnHome
       stage('Preparation') {
       checkout([$class: 'GitSCM', branches: [[name: '${branch}']], 
       doGenerateSubmoduleConfigurations: false, extensions: [], 
       submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'f58165e3-e5a7-408a-a57d-a4b643b14308', 
       url: 'git@192.168.200.61:/home/git/repos/app.git']]])
       }
       stage('maven Build') {
        echo "maven build..."  
       }
       stage('deploy') {
        echo "deploy..."
       }
       stage('test') {
        echo "test..."
       }
    }
    
    #将脚本推送到远程仓库的master分支
    [root@Jenkins jenkinsfile]# git add *
    [root@Jenkins jenkinsfile]# git commit -m "第一次提交"
    [master(根提交) 10fb59e] 第一次提交
     1 file changed, 18 insertions(+)
     create mode 100644 itemA/jenkinsfile
    
    [root@Jenkins jenkinsfile]# git push -u origin master
    Counting objects: 4, done.
    Compressing objects: 100% (2/2), done.
    Writing objects: 100% (4/4), 563 bytes | 0 bytes/s, done.
    Total 4 (delta 0), reused 0 (delta 0)
    To git@192.168.200.61:/home/git/repos/jenkinsfile
     * [new branch]      master -> master
    分支 master 设置为跟踪来自 origin 的远程分支 master。
    

    (3)利用远程仓库里的Pipeline脚本,进行流水线的构建
    image.png-91.6kB

    image.png-68.4kB

    image.png-14.9kB

    image.png-59.8kB

    image.png-34.4kB

    image.png-22.9kB

    5. 项目案例一:Jenkins+Pipeline+Git+PHP博客项目流水线自动发布

    主机名 IP地址 备注
    Git 192.168.200.61 Git服务器
    Jenkins 192.168.200.62 Jenkins服务器
    Web01 192.168.200.64 Web服务器
    #所有服务器进行如下操作
    [root@Git ~]# cat /etc/redhat-release 
    CentOS Linux release 7.5.1804 (Core) 
    [root@Git ~]# uname -r
    3.10.0-862.3.3.el7.x86_64
    [root@Git ~]# systemctl stop firewalld
    [root@Git ~]# systemctl disable firewalld
    [root@Git ~]# systemctl stop NetworkManager
    [root@Git ~]# systemctl disable NetworkManager
    

    image.png-141.8kB

    5.1 创建一个Pipeline流水线项目并进行参数化构建

    image.png-89.9kB

    image.png-53.2kB

    由于我们仍旧打算将pipeline脚本放在远程Git仓库里,因此我们需要从远程Git仓库拉取Pipeline脚本,所以,参数化构建不支持Git的参数化。我们只能使用字符结构的参数化构建。

    image.png-60.3kB

    5.2 下载用于自动化发布的PHP源码wordpress源码包,并上传远程git仓库

    #在Git服务器上创建用于存放源码的Git仓库
    [root@Git ~]# hostname -I
    192.168.200.61 
    [root@Git ~]# cd /home/git/repos/
    [root@Git repos]# ls
    app.git  jenkinsfile
    [root@Git repos]# mkdir wordpress
    [root@Git repos]# cd wordpress/
    [root@Git wordpress]# git --bare init
    初始化空的 Git 版本库于 /home/git/repos/wordpress/
    
    [root@Git wordpress]# cd ..
    [root@Git repos]# ll -d wordpress
    drwxr-xr-x 7 root root 119 10月 23 20:12 wordpress
    [root@Git repos]# chown -R git.git wordpress
    [root@Git repos]# ll -d wordpress
    drwxr-xr-x 7 git git 119 10月 23 20:12 wordpress
    
    #在jenkins服务器上,克隆创建好的远程Git仓库
    [root@Jenkins ~]# mkdir /php-app
    [root@Jenkins ~]# cd /php-app
    [root@Jenkins php-app]# git clone git@192.168.200.61:/home/git/repos/wordpress
    正克隆到 'wordpress'...
    warning: 您似乎克隆了一个空版本库。
    [root@Jenkins php-app]# ls
    wordpress
    [root@Jenkins php-app]# cd wordpress/
    [root@Jenkins wordpress]# ls
    [root@Jenkins wordpress]#
    
    
    #下载wordpres源代码
    [root@Jenkins wordpress]# wget https://cn.wordpress.org/wordpress-4.9.4-zh_CN.tar.gz
    [root@Jenkins wordpress]# ls
    wordpress-4.9.4-zh_CN.tar.gz
    [root@Jenkins wordpress]# tar xf wordpress-4.9.4-zh_CN.tar.gz
    [root@Jenkins wordpress]# ls
    wordpress  wordpress-4.9.4-zh_CN.tar.gz
    [root@Jenkins wordpress]# mv wordpress-4.9.4-zh_CN.tar.gz /tmp/
    [root@Jenkins wordpress]# ls
    wordpress
    [root@Jenkins wordpress]# mv wordpress/* .
    [root@Jenkins wordpress]# ls
    index.php    wp-activate.php       wp-config-sample.php  wp-links-opml.php  wp-settings.php
    license.txt  wp-admin              wp-content            wp-load.php        wp-signup.php
    readme.html  wp-blog-header.php    wp-cron.php           wp-login.php       wp-trackback.php
    wordpress    wp-comments-post.php  wp-includes           wp-mail.php        xmlrpc.php
    [root@Jenkins wordpress]# rm -rf wordpress/
    
    #在jenkins上提交代码到远程Git仓库
    [root@Jenkins wordpress]# git add *
    [root@Jenkins wordpress]# git commit -m "第一次提交"
    [root@Jenkins wordpress]# git push -u origin master
    Counting objects: 1660, done.
    Compressing objects: 100% (1635/1635), done.
    Writing objects: 100% (1660/1660), 8.86 MiB | 4.73 MiB/s, done.
    Total 1660 (delta 173), reused 0 (delta 0)
    To git@192.168.200.61:/home/git/repos/wordpress
     * [new branch]      master -> master
    分支 master 设置为跟踪来自 origin 的远程分支 master。
    

    5.3 设置分布式构建的slave管理节点

    我们计划利用分布式构建的方式,启动pipeline的流水线项目发布
    slave管理节点就设置为需要用于发布项目的Web服务器

    5.3.1 添加用于连接slave代理节点的SSH证书

    image.png-29.7kB

    5.3.2 添加并设置slave管理从节点

    image.png-33kB

    image.png-59.6kB

    image.png-12.7kB

    5.3.3 slave从节点安装java环境,并启动jenkins的slave管理节点

    #解压安装jdk
    [root@Web01 ~]# ls
    anaconda-ks.cfg  jdk-8u171-linux-x64.tar.gz
    [root@Web01 ~]# tar xf jdk-8u171-linux-x64.tar.gz -C /usr/local
    [root@Web01 ~]# cd /usr/local/
    [root@Web01 local]# mv jdk1.8.0_171 jdk
    [root@Web01 local]# /usr/local/jdk/bin/java -version
    java version "1.8.0_171"
    Java(TM) SE Runtime Environment (build 1.8.0_171-b11)
    Java HotSpot(TM) 64-Bit Server VM (build 25.171-b11, mixed mode)
    
    #配置java环境
    [root@Web01 ~]# sed -i.org '$a export JAVA_HOME=/usr/local/jdk/' /etc/profile
    [root@Web01 ~]# sed -i.org '$a export PATH=$PATH:$JAVA_HOME/bin' /etc/profile
    [root@Web01 ~]# sed -i.org '$a export CLASSPATH=.$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar' /etc/profile
    [root@Web01 ~]# tail -3 /etc/profile
    export JAVA_HOME=/usr/local/jdk/
    export PATH=$PATH:$JAVA_HOME/bin
    export CLASSPATH=.$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar
    [root@Web01 ~]# source /etc/profile
    [root@Web01 ~]# java -version
    java version "1.8.0_171"
    Java(TM) SE Runtime Environment (build 1.8.0_171-b11)
    Java HotSpot(TM) 64-Bit Server VM (build 25.171-b11, mixed mode)
    

    image.png-13.7kB

    5.4 Web服务器安装LNMP环境,并手动拉取代码模拟访问

    [root@Web01 ~]# yum -y install epel-release nginx php-fpm php-mysql
    [root@Web01 ~]# rpm -qa epel-release nginx php-fpm php-mysql
    php-fpm-5.4.16-45.el7.x86_64
    nginx-1.12.2-2.el7.x86_64
    php-mysql-5.4.16-45.el7.x86_64
    epel-release-7-11.noarch
    
    [root@Web01 ~]# cd /etc/nginx/
    [root@Web01 nginx]# ls
    conf.d                fastcgi_params          mime.types          scgi_params           win-utf
    default.d             fastcgi_params.default  mime.types.default  scgi_params.default
    fastcgi.conf          koi-utf                 nginx.conf          uwsgi_params
    fastcgi.conf.default  koi-win                 nginx.conf.default  uwsgi_params.default
    [root@Web01 nginx]# cp nginx.conf{,.bak}
    [root@Web01 nginx]# egrep -v "#|^$" nginx.conf.bak > nginx.conf
    
    [root@Web01 nginx]# cat nginx.conf
    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;       #include了一个配置文件目录
        server {
            listen       80 default_server;        #默认的server配置(如果用IP访问就进入这个server)
            listen       [::]:80 default_server;
            server_name  _;
            root         /usr/share/nginx/html;    #默认的网页目录
            include /etc/nginx/default.d/*.conf;
            location / {
            }
            error_page 404 /404.html;
                location = /40x.html {
            }
            error_page 500 502 503 504 /50x.html;
                location = /50x.html {
            }
        }
    }
    
    #由于默认的配置文件include了/etc/nginx/conf.d/*.conf因此我们增加一个server配置文件即可
    [root@Web01 nginx]# cat /etc/nginx/conf.d/wp.conf
    server {
        listen 80;
        server_name www.yunjisuan.com;
        root    /usr/share/nginx/html/www.yunjisuan.com;
        location / {
            index index.php index.html;
        }
        location ~.php {
            fastcgi_index index.php;
            fastcgi_pass 127.0.0.1:9000;
            include fastcgi.conf;
        }
    }
    
    #创建网页目录
    [root@Web01 ~]# cd /usr/share/nginx/html/
    [root@Web01 html]# ls
    404.html  50x.html  index.html  nginx-logo.png  poweredby.png
    [root@Web01 html]# mkdir www.yunjisuan.com
    [root@Web01 html]# cd www.yunjisuan.com/
    
    #克隆Git仓库代码到本地网页目录
    [root@Web01 www.yunjisuan.com]# yum -y install git
    [root@Web01 www.yunjisuan.com]# rpm -qa git
    git-1.8.3.1-14.el7_5.x86_64
    
    [root@Web01 www.yunjisuan.com]# git clone git@192.168.200.61:/home/git/repos/wordpress
    正克隆到 'wordpress'...
    git@192.168.200.61's password: yangwenbo
    remote: Counting objects: 1660, done.
    remote: Compressing objects: 100% (1462/1462), done.
    remote: Total 1660 (delta 173), reused 1660 (delta 173)
    接收对象中: 100% (1660/1660), 8.86 MiB | 12.12 MiB/s, done.
    处理 delta 中: 100% (173/173), done.
    
    [root@Web01 www.yunjisuan.com]# ls
    wordpress
    [root@Web01 www.yunjisuan.com]# mv wordpress/* .
    [root@Web01 www.yunjisuan.com]# ls
    index.php    wp-activate.php       wp-config-sample.php  wp-links-opml.php  wp-settings.php
    license.txt  wp-admin              wp-content            wp-load.php        wp-signup.php
    readme.html  wp-blog-header.php    wp-cron.php           wp-login.php       wp-trackback.php
    wordpress    wp-comments-post.php  wp-includes           wp-mail.php        xmlrpc.php
    [root@Web01 www.yunjisuan.com]# rm -rf wordpress/
    
    将网页目录权限授权给apache程序用户
    [root@Web01 www.yunjisuan.com]# cd ..
    [root@Web01 html]# ll -d www.yunjisuan.com/
    drwxr-xr-x 5 root root 4096 10月 24 10:01 www.yunjisuan.com/
    [root@Web01 html]# id apache
    uid=48(apache) gid=48(apache) 组=48(apache)
    [root@Web01 html]# chown -R apache.apache /usr/share/nginx/html/www.yunjisuan.com
    [root@Web01 html]# ll -d www.yunjisuan.com/
    drwxr-xr-x 5 apache apache 4096 10月 24 10:01 www.yunjisuan.com/
    
    #启动nginx服务和php-fpm服务
    [root@Web01 ~]# systemctl start nginx
    [root@Web01 ~]# systemctl start php-fpm
    [root@Web01 ~]# ss -antup | egrep "80|9000"
    tcp    LISTEN     0      128    127.0.0.1:9000                  *:*                   users:(("php-fpm",pid=16195,fd=0),("php-fpm",pid=16194,fd=0),("php-fpm",pid=16193,fd=0),("php-fpm",pid=16192,fd=0),("php-fpm",pid=16191,fd=0),("php-fpm",pid=16189,fd=6))
    tcp    LISTEN     0      128       *:80                    *:*                   users:(("nginx",pid=16182,fd=6),("nginx",pid=16181,fd=6))
    tcp    LISTEN     0      128      :::80                   :::*                   users:(("nginx",pid=16182,fd=7),("nginx",pid=16181,fd=7))
    

    做好宿主机的域名映射后,浏览器访问测试http://www.yunjisuan.com

    image.png-65.1kB

    5.5 在远程Git仓库中创建一个用于构建的Pipeline脚本

    #在jenkins服务器上进行如下操作
    [root@Jenkins ~]# rm -rf /test
    [root@Jenkins ~]# mkdir /test
    [root@Jenkins ~]# cd /test/
    [root@Jenkins test]# git clone git@192.168.200.61:/home/git/repos/jenkinsfile
    正克隆到 'jenkinsfile'...
    remote: Counting objects: 8, done.
    remote: Compressing objects: 100% (5/5), done.
    remote: Total 8 (delta 1), reused 0 (delta 0)
    接收对象中: 100% (8/8), done.
    处理 delta 中: 100% (1/1), done.
    [root@Jenkins test]# ls
    jenkinsfile
    [root@Jenkins test]# cd jenkinsfile/
    [root@Jenkins jenkinsfile]# ls
    itemA  itemB
    [root@Jenkins jenkinsfile]# ls itemA/
    jenkinsfile
    

    通过流水线脚本生成器生成的阶段代码示例:

    image.png-55.3kB

    image.png-33.3kB

    image.png-15.3kB

    image.png-49.5kB

    #通过流水线脚本生成器生成如下脚本内容
    [root@Jenkins jenkinsfile]# vim itemA/jenkinsfile-php-wp
    [root@Jenkins jenkinsfile]# cat itemA/jenkinsfile-php-wp
    node ("PHP-slave-192.168.200.64") {
       stage('git checkout') {
           checkout([$class: 'GitSCM', branches: [[name: '${branch}']], 
           doGenerateSubmoduleConfigurations: false, extensions: [], 
           submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'f58165e3-e5a7-408a-a57d-a4b643b14308', 
           url: 'git@192.168.200.61:/home/git/repos/wordpress']]])
     }
       stage('code copy') {
           sh '''rm -rf ${WORKSPACE}/git
                 [ -d /data/backup ] || mkdir -p /data/backup
                 mv /usr/share/nginx/html/www.yunjisuan.com /data/backup/www.yunjisuan.com -$(data +%F_%T)
           cp -rf ${WORKSPACE} /usr/share/nginx/html/www.yunjisuan.com'''
     }
       stage('test') {
            sh 'curl http://www.yunjisuan.com/status.html'
     }
    }
    
    #推送到Git远程仓库
    [root@Jenkins jenkinsfile]# git add *
    [root@Jenkins jenkinsfile]# git commit -m "xxxx"
    [master 91d20a5] xxxx
     1 file changed, 17 insertions(+)
     create mode 100644 itemA/jenkinsfile-php-wp
    [root@Jenkins jenkinsfile]# git push -u origin master
    Counting objects: 6, done.
    Compressing objects: 100% (4/4), done.
    Writing objects: 100% (4/4), 736 bytes | 0 bytes/s, done.
    Total 4 (delta 0), reused 0 (delta 0)
    To git@192.168.200.61:/home/git/repos/jenkinsfile
       cd4f8f3..91d20a5  master -> master
    分支 master 设置为跟踪来自 origin 的远程分支 master。
    

    5.6 在PHP项目代码里增加Pipeline验证用的测试页面

    #在项目代码里加入一个健康检查测试页面,并推送到远程Git仓库
    #在Web服务器上进行如下操作
    [root@Web01 /]# mkdir /test
    [root@Web01 /]# cd /test/
    [root@Web01 test]# git clone git@192.168.200.61:/home/git/repos/wordpress
    正克隆到 'wordpress'...
    git@192.168.200.61's password: yangwenbo
    remote: Counting objects: 1660, done.
    remote: Compressing objects: 100% (1462/1462), done.
    remote: Total 1660 (delta 173), reused 1660 (delta 173)
    接收对象中: 100% (1660/1660), 8.86 MiB | 11.49 MiB/s, done.
    处理 delta 中: 100% (173/173), done.
    
    
    [root@Web01 test]# ls
    wordpress
    [root@Web01 test]# cd wordpress/
    [root@Web01 wordpress]# ls
    index.php        wp-admin              wp-content         wp-load.php      wp-signup.php
    license.txt      wp-blog-header.php    wp-cron.php        wp-login.php     wp-trackback.php
    readme.html      wp-comments-post.php  wp-includes        wp-mail.php      xmlrpc.php
    wp-activate.php  wp-config-sample.php  wp-links-opml.php  wp-settings.php
    [root@Web01 wordpress]# echo "OK-version V2.0" >> status.html
    
    #配置git全局配置
    [root@Web01 wordpress]# git config --global user.email "1773464408@qq.com"
    [root@Web01 wordpress]# git config --global user.name "Mr.yang"
    
    #将测试用页面提交到远程Git仓库
    [root@Web01 wordpress]# git add *
    [root@Web01 wordpress]# git commit -m "version V2.0"
    [master fc1c4fd] version V2.0
     1 file changed, 1 insertion(+)
     create mode 100644 status.html
    [root@Web01 wordpress]# git push -u origin master
    git@192.168.200.61's password: yangwenbo
    Counting objects: 4, done.
    Compressing objects: 100% (2/2), done.
    Writing objects: 100% (3/3), 284 bytes | 0 bytes/s, done.
    Total 3 (delta 1), reused 0 (delta 0)
    To git@192.168.200.61:/home/git/repos/wordpress
       b33992b..fc1c4fd  master -> master
    分支 master 设置为跟踪来自 origin 的远程分支 master。
    
    #在web服务器做域名映射(因为要进行curl验证)
    [root@Web01 wordpress]# echo `hostname -I` www.yunjisuan.com >> /etc/hosts
    [root@Web01 wordpress]# tail -1 /etc/hosts
    192.168.200.64 www.yunjisuan.com
    

    5.7 浏览器访问jenkins进行PHP项目流水线发布构建

    image.png-29.7kB

    image.png-97.1kB

  • 相关阅读:
    从句分析
    artDialog ( v 6.0.2 ) content 参数引入页面 html 内容
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 11 盛最多水的容器
    Java实现 LeetCode 11 盛最多水的容器
  • 原文地址:https://www.cnblogs.com/ywb123/p/11222980.html
Copyright © 2011-2022 走看看