Jenkins 自动化部署上线

Jenkins 自动化部署上线

摘要php

jenkins自动化部署项目,经过jenkins 部署来节省运维时间,不须要手动cp上线及版本发布html

Jenkins 自动化部署上线

Jenkinsjava



1、Jenkins是什么

Jenkins是一款自包含的开源自动化服务,可用于自动执行与构建,测试和交付或部署软件有关的各类任务。
Jenkins目前能够经过本地系统软件包Docker进行安装,甚至能够经过任何安装了Java运行环境的计算机独立运行

2、上线流程图

既然咱们说到自动化上线,咱们就不得不说说一个项目上线的流程.只有规范起来才能够作到不出事故!

上线流程图以下图所示
image_1ch5i8umo201i1011vh11jaogd.png-168.4kB

3、Jenkins安装配置

Jenkins依赖Java环境,咱们须要安装Java环境以及相关的环境准备

  
  
  
  

###关闭防火墙$ iptables -F$ iptables -X$ systemctl stop firewalld$ systemctl disable firewalld###安装yum源$ wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo$ wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo$ yum clean all && yum makecache  

1.下载Jdk包
image_1ch2lpjhd1of5d9hvpj1rnqbjam.png-277.1kB
下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

上传jdk包到服务器

  
  
  
  


###解压拷贝jdk$ tar xf jdk-8u171-linux-x64.tar.gz -C /usr/local/$ ln -s /usr/local/jdk1.8.0_171/ /usr/local/jdk$ ln -s /usr/local/jdk/bin/java /usr/bin/java###设置环境变量$ vim /etc/profileexport JAVA_HOME=/usr/local/jdkexport CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jarexport PATH=$JAVA_HOME/bin:$PATH$ source  /etc/profile

2.安装Jenkins

  
  
  
  

$ wget  -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat/jenkins.repo$ rpm --import https://pkg.jenkins.io/redhat/jenkins.io.key$ yum install jenkins -y$ systemctl start jenkins##若是咱们启动Jenkins出现错误能够直接使用systemctl status jenkins查看错误

jenkins相关目录释义:

(1)/usr/lib/jenkins/:jenkins安装目录,war包会放在这里。
(2)/etc/sysconfig/jenkins:jenkins配置文件,“端口”,“JENKINS_HOME”等均可以在这里配置。
(3)/var/lib/jenkins/:默认的JENKINS_HOME。
(4)/var/log/jenkins/jenkins.log:jenkins日志文件。

检查端口是否存在
image_1ch2n40p91muo1t57j5b1tm85bl1j.png-230.9kB

3.配置Jenkins
image_1ch2q7pj31se6u37rpj8bok176b.png-106kB

Jenkins有安全策略,咱们按照提示拷贝验证码便可
image_1ch2ni2601kq018ge1tkfvjl160q20.png-113.7kB

将验证码复制到Web框里
image_1ch2nkdo0t0f17ekhi1vmmo7u2t.png-55.4kB

咱们这里使用推荐就能够了,由于后期咱们均可以在安装
image_1ch2nnk5no9f6ce1qe0ffl1nck3a.png-155.8kB

安装插件中,有的插件会由于网络问题没法安装成功

image_1ch2nudu5hbo53qes84409r147.png-164.5kB

咱们这里能够建立一个管理员,或者直接使用admin

咱们最好不要直接使用admin

image_1ch2o3sji13s01ahi1t7l1d45u7o4k.png-56.8kB

image_1ch2o5cqu2g3ds610ikjecmc351.png-63.3kB

安装完成访问地址:iP:8080
image_1ch2oae2qfi91ppegakidiq3k5u.png-112.6kB

到这里咱们Jenkins已经安装成功,剩下的就是配置插件和配置环境

image_1ch2qgfhj577pru1sf3p3f2lc78.png-183.2kB

由于咱们目前什么都没有须要安装插件,点击下步安装插件
image_1ch2qi0tfjfe1etl10d41g0rlth7l.png-188.4kB

为了模拟环境咱们须要安装Jenkins一些相关插件
 下面2个maven 插件都须要勾选  
 插件名称:maven lntergration

image_1ch2qscc99jb1uf31gk8kctd7r82.png-183.3kB

咱们勾选安装重启
image_1ch2r4r0vna81okq1mi2m9113hp8s.png-172.6kB
image_1ch2qu1a5im5dc1m001nln6q58f.png-127kB

安装完成后以下图所示
默认是没有下面的maven项目的
image_1ch2rbd4o130l8ir1it3ofa137v9p.png-356.4kB

4.Jenkins配置项目

配置SVN地址
由于我是新建的Jenkins目录,没有权限,因此须要建立一个用于认证.
image_1ch2rq133kcmcuc80q1tbb19sa6.png-104.6kB

填写SVN地址,由于我这里的svn已经连接到ldap,因此不须要输入svn的密码,默认这里是svn的用户和密码

具体文章能够参考 VisualSVN 迁移至Linux SVN+Apache+ssl集成LDAP

image_1ch2s4h57jh3jng184u1508fgeaj.png-395kB

认证成功以后
image_1ch2s9cqqg4v1g2r1oaf17ms1rnhb0.png-141.9kB

了解maven 配置
首先咱们的svn分支下面须要有pom.xml
image_1ch2t381b1cui2ovsmb1m2817id7.png-283.2kB

继续往下




由于咱们只安装maven的插件,并无安装maven服务,因此这里须要咱们配置
image_1ch2sdufi1n38104b1g6av4n1vcbd.png-131.4kB

咱们就在这里添加一个名字,maven就自动安装了
image_1ch2sis6h1ibrh4smjmdck15jqbq.png-179.3kB

Maven安装完成了,须要依赖吧都是从maven.apache.org下载会比较慢,因此咱们指定私服的地址,由于在实际生产中也都是使用私服的。

在maven的配置文件里面也须要配置  配置文件conf/settings.xml 由于咱们所使用的是Jenkins的自动安装,而不是指定路径因此咱们要查到这个配置文件

maven 自动安装的配置路径
image_1ch2u85t61gu61j65lnfcrlu4vhi.png-76.7kB

配置Maven仓库地址

这里配置的都是私服地址
相关文章  Jenkins+Maven+SVN+Nexus 搭建持续集成环境

image_1ch2triup1f4jim166els3sosfr.png-331.3kB
配置Maven 镜像地址
image_1ch2u3h8sphp1jc2f391ot71kmdgl.png-323.2kB

配置Maven 编译参数   [研发都会]

相关文章:maven 编译命令
image_1ch2ssmlfdha2eq1pkihuv6q1ca.png-74kB

这个pom.xml里面配置是私服的地址
由于代码里面有不少东西是须要拉去依赖包,这些依赖包就存放在本地的私有仓库里(Nexus)

代码中pom.xml配置以下
私有仓库的地址
image_1ch2t4und125pmdh5dbah71j5odk.png-400.7kB

5.构建测试
image_1ch2t9pqrus91mni1a35v0f1n9jee.png-96.6kB

控制台输出说明

image_1ch35he289os1698430sr21aobhv.png-385.2kB

image_1ch35l1sl4kg12l4rsjiad1shlic.png-681.9kB

image_1ch35pomf1p4pnduuk81s1qdl1ip.png-526.3kB

6.Jenkins 工程目录

image_1ch56eo7f1jdh61n1aho1g961lsl19.png-301.5kB

能够经过修改Jenkins主目录

image_1ch56lkd0g1q13ac142i1n49o4h33.png-132.1kB

Jenkins打包好后的目录,这个war包就是咱们须要拷贝的tomcat下面的
image_1ch56vm9tthi1ehs1l5ptp8ndl3g.png-382.6kB




4、Jenkins 自动化部署项目案例

由于目前环境缘由,我这里只是截图Jenkins发布的流程(本次演示只是针对测试环境平常发布版本)

(1) Java 环境演示 [Jenkins和Tomcat在一台服务器上]

1.Jenkins 配置
a.jpg-612.2kB

SVN部分配置
image_1ch5af0th1gfqljk28bte9mq5i.png-204.9kB

maven及脚本设置
image_1ch5ahb88fgspno7t66d81vn45v.png-142.8kB

2.不发脚本配置以下:
相关参考:Jenkins可用环境变量列表
脚本的存放路径能够在系统管理->全局配置->Jenkins路径

  
  
  
  


















Last login: Thu Jun 28 18:01:59 2018 from 172.16.29.39[root@tomcat ~]# cat /jenkins/deploy.sh#!/bin/bash## Jenkins工程构建通用TOMCAT部署脚本# @author abcdocker# @create_time 2017-08-19## 在Jenkins内配置部署单元参数#      参数格式:MAVEN_MODULE_NAME:TOMCAT_ABSOLUTE_PATH  MAVEN模块名称:须要部署的目标TOMCAT绝对路径#      只有单个部署单元且没有Maven子模块时,模块名称参数能够没有,参数格式为:TOMCAT_ABSOLUTE_PATH## 注意:#      在本部署脚本内会执行TOMCAT启动脚本,为避免Jenkins在构建成功之后杀掉全部衍生的后台进程,须要在Jenkins内配置全局环境变量 BUILD_ID 值为 allow_to_run_as_daemon##DEPLOY_TARGET_TOMCAT=$TOMCAT#校验部署参数,不能为空if [ -z "$DEPLOY_TARGET_TOMCAT" ]then    echo    echo 部署参数为空,部署失败!    echo "#####################################################################"    echo    echo 单个部署单元参数格式:    echo          MAVEN_MODULE_NAME:TOMCAT_ABSOLUTE_PATH MAVEN模块名称:须要部署的目标TOMCAT绝对路径    echo    echo 多个部署单元参数格式:(多个部署单元使用空格分割)    echo          MAVEN_MODULE_NAME:TOMCAT_ABSOLUTE_PATH MAVEN_MODULE_NAME:TOMCAT_ABSOLUTE_PATH    echo    echo "#####################################################################"    exit 1fiechoecho 部署参数:${DEPLOY_TARGET_TOMCAT}TOMCAT_ARR=${DEPLOY_TARGET_TOMCAT//;/ }ARR=($TOMCAT_ARR)ARR_LEN=${#ARR[*]}echo ${ARR_LEN} 个部署单元i=1#获取Jenkins传入的目标TOMCAT组for T in $TOMCAT_ARRdo    echo    echo 开始 处理第 ${i} 个部署单元    echo 第一个部署单元:$T    #获取目标TOMCAT的WAR路径和TOMCATA的绝对路径    TOMCAT_PARAM=(${T//:/ })    MODULE_NAME=${TOMCAT_PARAM[0]}    TARGET_TOMCAT_PATH=${TOMCAT_PARAM[1]}    WAR_PATH="$WORKSPACE/$MODULE_NAME/target/*.war"    echo 部署单元模块名称:"${MODULE_NAME}"    echo 部署WAR包路径:"${WAR_PATH}"    echo 部署TOMCAT路径:"${TARGET_TOMCAT_PATH}"    #须要考虑MAVEN单模块下的部署问题    #if [ "${#ARR[*]}" -eq 1 -a -z "$TARGET_TOMCAT_PATH" ]    if [ "$ARR_LEN" -eq 1 -a -z "$TARGET_TOMCAT_PATH" ]    then        #MAVEN过程没有子模块,单个部署单元        TARGET_TOMCAT_PATH=$MODULE_NAME    MODULE_NAME="NULL"    fi    #校验参数,WORKSPACE变量来自于Jenkins环境变量    if [ -z "$MODULE_NAME" -o ! -f $WAR_PATH ]    then        echo 错误:MAVEN部署模块名称 参数为空 找不到WAR包!        echo 部署失败!        exit 1    fi    if [ -z "$TARGET_TOMCAT_PATH" -o ! -d "$TARGET_TOMCAT_PATH" ]    then        echo 错误:目标TOMCAT绝对路径 参数为空 TOMCAT目录不存在!        echo 部署失败!        exit 1    fi    echo 开始清理目标TOMCAT启动进程...    TOMCAT_PID=`ps -ef |grep "$TARGET_TOMCAT_PATH" |grep  "start" |awk '{print $2}'`    if [ -n "$TOMCAT_PID" ]    then        echo TOMCAT_${i},PID${TOMCAT_PID},正在结束该进程...        kill -9 $TOMCAT_PID && echo PID${TOMCAT_PID} 已被干掉!    else        echo TOMCAT_${i} 进程未启动!    fi    echo 开始清理目标TOMCAT缓存...    rm -rf $TARGET_TOMCAT_PATH/webapps/*    rm -rf $TARGET_TOMCAT_PATH/logs/*    rm -rf $TARGET_TOMCAT_PATH/work/*    echo 开始部署WAR包...    cp -a $WAR_PATH $TARGET_TOMCAT_PATH/webapps/ROOT.war && echo WAR包部署完毕。    echo 开始启动目标TOMCAT服务...    sleep 10    /bin/bash $TARGET_TOMCAT_PATH/bin/startup.sh    echo 开始配置web目录的FTP权限...    #启动过程会自动解压WAR包,因此在这里须要等待WAR包解压完成再调整目录权限    sleep 30    chown -R vftpuser.vftpuser ${TARGET_TOMCAT_PATH}/webapps/ && echo 目录权限配置完毕。    echo 部署成功    echo 完成 第 ${i} 个部署单元处理。    echo    ((i++))done

3.构建效果以下图所示:
new_jenkins.gif-1968.9kB




(2) Java 环境演示 [Jenkins和Tomcat不在一台服务器上]

上面的脚本是针对Jenkins和Tomcat都在相同的目录,有的时候咱们测试环境会存在不在一台服务器的状况,脚本以下

  
  
  
  














只是脚本简单的修改[root@tomcat ~]# cat /jenkins/ysc.sh#!/bin/bash## Jenkins工程构建通用TOMCAT部署脚本# @author 刘曙# @create_time 2017-08-19## 在Jenkins内配置部署单元参数#      参数格式:MAVEN_MODULE_NAME:TOMCAT_ABSOLUTE_PATH  MAVEN模块名称:须要部署的目标TOMCAT绝对路径#      只有单个部署单元且没有Maven子模块时,模块名称参数能够没有,参数格式为:TOMCAT_ABSOLUTE_PATH## 注意:#      在本部署脚本内会执行TOMCAT启动脚本,为避免Jenkins在构建成功之后杀掉全部衍生的后台进程,须要在Jenkins内配置全局环境变量 BUILD_ID 值为 allow_to_run_as_daemon##DEPLOY_TARGET_TOMCAT=$YSCHOST=root@172.16.1.35#校验部署参数,不能为空if [ -z "$DEPLOY_TARGET_TOMCAT" ]then    echo    echo 部署参数为空,部署失败!    echo "#####################################################################"    exit 1fiechoecho 部署参数:${DEPLOY_TARGET_TOMCAT}TOMCAT_ARR=${DEPLOY_TARGET_TOMCAT//;/ }ARR=($TOMCAT_ARR)ARR_LEN=${#ARR[*]}echo ${ARR_LEN} 个部署单元i=1#获取Jenkins传入的目标TOMCAT组for T in $TOMCAT_ARRdo    echo    echo 开始 处理第 ${i} 个部署单元    echo 第一个部署单元:$T    #获取目标TOMCAT的WAR路径和TOMCATA的绝对路径    TOMCAT_PARAM=(${T//:/ })    MODULE_NAME=${TOMCAT_PARAM[0]}    TARGET_TOMCAT_PATH=${TOMCAT_PARAM[1]}    #WAR_PATH="/jenkins/workspace/ysc-all/${MODULE_NAME}/target/*.war"    WAR_PATH="${WORKSPACE}/${MODULE_NAME}/target/*.war"    echo 部署单元模块名称:"${MODULE_NAME}"    echo 部署WAR包路径:"${WAR_PATH}"    echo 部署TOMCAT路径:"${TARGET_TOMCAT_PATH}"    #判断IP是否有相关目录    ssh 172.16.1.35 "[ -d $TARGET_TOMCAT_PATH ]" >/dev/null 2>&1    if [ $? != 0 ];then       echo 错误    else       echo  正确    fi    #校验参数,WORKSPACE变量来自于Jenkins环境变量    if [ -z "$MODULE_NAME" -o ! -f $WAR_PATH ]    then        echo 错误:MAVEN部署模块名称 参数为空 找不到WAR包!        echo 部署失败!        exit 1    fi    #scp 软件包   ssh $HOST /etc/init.d/${MODULE_NAME} stop   ssh 172.16.1.35 "[ -d $TARGET_TOMCAT_PATH/webapps/ROOT/ ]" >/dev/null 2>&1   if [ $? = 0 ];then      ssh 172.16.1.35 rm -rf $TARGET_TOMCAT_PATH/webapps/ROOT        if [ $? = 0 ];then           scp  $WAR_PATH root@172.16.1.35:$TARGET_TOMCAT_PATH/webapps/ROOT.war && echo WAR包部署完毕。           echo $TARGET_TOMCAT_PATH is OK        else           echo 删除$TARGET_TOMCAT_PATH is error        fi   else           echo "not found $TARGET_TOMCAT_PATH/webapps/ROOT"           scp  $WAR_PATH root@172.16.1.35:$TARGET_TOMCAT_PATH/webapps/ROOT.war && echo WAR包部署完毕。           ssh $HOST /etc/init.d/${MODULE_NAME} restart   fi####################启动文件done  #scp /home/config.properties/ysc/${MODULE_NAME}.js root@172.16.1.35:$TARGET_TOMCAT_PATH/webapps/ROOT/web/js/basePath.js  ssh $HOST /etc/init.d/${MODULE_NAME} restart

Jenkins配置以下修改
b.jpg-221.2kB

image_1ch5dcoad126r201g961a6ised9q.png-148.7kB

修改完成后咱们构建演示
new_jenkins2.gif-879.3kB

提示:这种环境下配置文件都是经过maven build进行控制,也就是经过研发控制配置文件

+
+
+
+




(3) Java 环境演示 [上线脚本]

线上环境演示
咱们的上线流程以下:
image_1ch5foh2q1th6ulu1tar1dqb1jh7bt.png-45.1kB

Jenkins配置以下:
image_1ch5fsvoi1q5l1d9g108j1mg218mcca.png-123.7kB
image_1ch5fut497s13dofdr1b0v1hlqcn.png-168.4kB
image_1ch5g3h5ssmc15sr1r4s1gpa1nshd4.png-160kB

+
+
+
+
+
1.首先测试环境脚本:

  
  
  
  


[root@tomcat ~]# cat /server/scripts/.upgrade-smscenter.sh#!/bin/bashWAR="/jenkins/workspace/portal-smscenter/bxg-sms-center-web/target/*.war"Path="/data/hub/bxg-smscenter/`date +%Y%m%d`/"scp_war(){if [ ! -d $Path ];then ssh root@file-server mkdir -p $Path    scp $WAR root@file-server:$Pathelse    scp $WAR root@file-server:$Pathfi}ssh_file(){  ssh root@file-server "/bin/bash /server/script/bxg/bxg-smscenter.sh"}scp_warssh_file

2.跳板机脚本修改

[root@File-server1 ~]# cat /server/script/bxg/bxg-smscenter.sh#!/bin/bashHOST=online-server2WAR="/data/hub/bxg-smscenter/`date +%Y%m%d`"DIR="/application/smscenter/webapps/ROOT/"function scp_file {    if `ssh root@$HOST "[ ! -d $WAR ]"`;then            ssh root@$HOST "mkdir -p $WAR"    fi            scp $WAR/*.war root@$HOST:$WAR/            echo "scp $WAR/*.war root@$HOST:$WAR/"}ssh_deploy(){    ssh root@$HOST "/bin/bash /server/scripts/deploy_smscenter.sh"}scp_filessh_deploy

3.web 服务器脚本

  
  
  
  







[root@online-server2 ~]# cat /server/scripts/deploy_smscenter.sh#!/bin/bashWAR="/data/hub/bxg-smscenter/`date +%Y%m%d`"OBJECT="/application/smscenter/webapps/ROOT/"Backup="/data/tomcat/bxg-smscenter-`date +%Y%m%d`"SCR_D="/application/smscenter/webapps/ROOT"#config="/data/bak"backup_tar(){    tar zcvf $Backup.tar.gz $SCR_D/    echo "为了防止意外cp整个项目目录存放"    cp -a $SCR_D/ $Backup    rm -rf $OBJECT/*}cp_war(){    unzip $WAR/*.war -d $SCR_D/}cp_config(){    cat $Backup/WEB-INF/classes/application-prod.properties >$SCR_D/WEB-INF/classes/application-prod.properties    /etc/init.d/smscenter restart}backup_tarcp_warcp_config[root@online-server2 ~]#

相关文章  企业必会技能 tomcat

+
+
+
+




(4) NodeJs 环境演示 [上线脚本]

node 环境上线流程
Jenkins配置以下 [node项目不适用maven,因此能够不用建立maven项目,直接在Jenkins建立普通项目就能够]
image_1ch5h3tugmu110pr1p85c5e1fe5dh.png-122.6kB
image_1ch5hdkn1mlv17vj12ue1m7i1k6veu.png-261.6kB

1.测试环境脚本

  
  
  
  









[root@tomcat ~]# cat /server/scripts/mobile/mobile.sh#!/bin/bashsource /etc/profileHOST=file-serverBASE_DIR=/server/scripts/mobile/murl=$1server=$2DATE=`date +%Y%m%d`tar(){rm -rf $BASE_DIR    [ -d $BASE_DIR ] || mkdir $BASE_DIR    cd $BASE_DIR echo "##########################################################" echo "代码拉取中!!!" svn co -q $url/ .    echo "##########################################################"}cp(){    cd ${BASE_DIR} /bin/tar -zcvf m_${DATE}.tar.gz ./*    echo "##########################################################"    echo "文件已经打包完成! 正在拷贝中!!!"    echo "##########################################################"    sleep 5    scp  m_${DATE}.tar.gz root@$HOST:/data/hub/bxg-mobile/    echo "##########################################################"    echo "文件已经拷贝完成! 正在上传服务器中!!!"    echo "##########################################################"        ssh root@file-server "/bin/bash /server/script/bxg/bxg-mobile.sh $server"}tarcp[root@tomcat ~]#

2.跳板机脚本

  
  
  
  







[root@File-server1 ~]# cat /server/script/bxg/bxg-mobile.sh#!/bin/bashHOST=$1Mobile_tar="/data/hub/bxg-mobile"DIR="/application/node"DATE=`date +%Y%m%d`scp_file(){    if `ssh root@$HOST "[ ! -d $Mobile_tar ]"`;then            ssh root@$HOST "mkdir -p $Mobile_tar"    fi            scp $Mobile_tar/m_${DATE}.tar.gz root@$HOST:$DIR/        sleep 3        echo "   "        echo "##########################################################"        echo "File-server 正在拷贝 ${HOST}!!!"        sleep 3        echo "##########################################################"}ssh_deploy(){           echo "Hi"    ssh root@$HOST "/bin/bash /server/scripts/bxg/bxg-mobile.sh"}scp_filessh_deploy

3.web 发布脚本

  
  
  
  


















[root@iZbp11tefvghtcfn5mudgdZ ~]# cat /server/scripts/bxg/bxg-mobile.sh#!/bin/bashsource /etc/profileDIR="/application/node"DATE=`date +%Y%m%d`Backup="/application/node/m/"BAK="/data/hub/bxg-mobile"backup_tar(){    echo "为了防止意外cp整个项目目录存放"    cp -ar $Backup ${BAK}/mobile_$DATE    echo "online-server 原目录拷贝备份完成!"}cp_war(){    /etc/init.d/mobile stop    #mv $Backup /tmp/m_${DATE} && rm -rf /tmp/m_${DATE} rm -rf $Backup    mkdir $Backup && cd /application/node/ tar xf m_${DATE}.tar.gz -C $Backup}npm_config(){    cd $Backup cnpm install npm run build-prod npm run start-prod &>/var/log/mobile_${DATE}.log &}C(){    echo "++++++++++++++++++++++++++++++++++++++++++++++++++++"    curl  -I 127.0.0.1:3000    echo "###################################################"    echo "如果200 服务启动正常! 能够启动另外一台!"    echo "###################################################"}backup_tarcp_warnpm_configC

+
+
+
相关文章 Node.js 环境搭建

总结:Jenkins自动化不是运维一我的就能够完成的,须要研发的参与,本文只是给你们展现一下我公司的自动化,我眼里所谓的自动化. 但愿你们不喜勿喷,对文章有意见或建议请在评论留言哦~

相关文章
相关标签/搜索