GitOps实践 | 企业生产环境Jenkins流水线分享,从Gitlab到镜像构建到部署测试以及企业微信消息通知...

news2024/11/27 2:37:23

8dfe89dd223517f4a40bfec5f5cdac5c.jpeg

21f81614221efd8e1a06e986658356d0.gif

关注回复【学习交流群】加入【安全开发运维】答疑交流群


目录:

edfb7f5bf313708a79e4e303d61d2748.png

0x00 前言简述

描述: 当前在企业内部开发中最常用的CI/CD(持续集成和交付),总是可以看到Jenkins(大叔)的身影,其作为老牌开源的CI/CD工具,它可以完成自动化构建、测试和部署应用程序等阶段,并且Jenkins 拥有庞大的插件生态系统,提供了丰富的功能扩展和集成选项。无论是构建工具、测试框架、代码质量工具还是部署工具,都可以通过插件轻松集成到Jenkins中。此外Jenkins具有直观的用户界面和易于使用的操作,使得团队成员可以快速上手并参与到持续集成的过程中,Jenkins也提供了丰富的构建和测试报告功能,可以实时监控构建状态和测试结果,并生成易于理解的可视化报告,所以Jenkins在企业开发运维中具有重要的意义。

但是由于容器及云原生技术的发展,各 CI/CD 的工具雨后春笋般的出来,我们作为运维人员肯定选择最合适,最简单,最容易上手的,只是当下作者企业为了适应业务开发测试的需要,已经将CI/CD工具从Jenkins转为Tekton+ArgoCD,使之更加方便管理和运行,此处并不是说Jenkins不好,只是针对云原生环境可以使用其他CI/CD工具(有学习成本呀)来代替Jenkins。

为了总结经验及方便后续运维学习者,此处作者将自己企业CI/CD迁移前的GitOps安装环境Jenkins + Gitlab + Harbor + Kubernetes和部署流程做一个实践总结,还分享Jenkins生产线上的流水线Pipeline(带企业微信或者UME信息推送,Gitlab 流水线同步)、以及自行构建Jenkins-agent所需镜像在Jenkins配置Kubernetes支持使之实现动态工作节点的生成,最后为了各位运维同道中人在自己企业中在使用Jenkins工具搭建快速部署GitOps环境,减少工作量以及学习时间,遂有了此篇文章,希望大家多多支持。


温馨提示: 本文是作者原创文章,作者熬夜花费了许多精力进行实践和总结,为了防止恶意爬虫和伸手党直接转发,所以作者将此文设为付费文章(请作者喝一瓶可乐🍺 精神精神),希望大家理解并多多支持,作者后续将持续更新更多secdevops方面的文章,此外各位付费的朋友可以加入我们的【微信交流群】(关注后回复此关键即可)一起进行学习,相关问题讨论。

温馨提示: 此处,先来看看本文章,将实现的企业Jenkins持续集成与交付的Pipeline流水线,其构建部署结果如下所示:

1.Pipeline流水线构建参数

dd177453b6dab7d46fac39e6f016c024.png

2.Pipeline流水线CI/CD完整流程执行结果

8b7e3224e80f98ac56abd7216f2e532d.png

3.Pipeline流水线消息通知

a4879465a1f46c517fbd8fd5a3329bd2.png

温馨提示: 在文章末尾获取JenkinsPipeline流线脚本以及Jenkins-Agent镜像构建所需软件(镜像支持git openssh maven 3.9.4、jdk8/jdk11 gitlab-cli 0.15.0 nodejs等工具环境)。

1.GitOps 介绍

什么是GitOps?

答: GitOps是一种软件开发和运维的方法论,它将代码的版本控制和应用程序的部署、管理、监控等操作紧密结合在一起,通过使用Git作为唯一的源代码存储库,实现了基础设施即代码的理念。
通过GitOps,开发团队可以通过提交代码来触发应用程序的部署和更新,而不需要手动进行部署操作。这样可以减少人为因素带来的错误,并保证了环境的一致性和可重复性。同时,GitOps还提供了自动化的监控和报警机制,可以及时发现并解决问题。

GitOps的核心原则包括:

  • 基础设施即代码:将基础设施配置和操作以代码的形式存储和管理。

  • 自动化:通过自动化工具和流程实现将代码变更应用到基础设施的过程。

  • 可观察性:通过监控、日志和报警等手段来保证系统的可观察性,及时发现和解决问题。

  • 声明式配置:使用声明式配置来描述期望的系统状态,由系统自动将实际状态与期望状态保持一致。

2.Jenkins 介绍

描述: Jenkins是一个开源的持续集成(CI)工具,它允许开发人员自动化构建、测试和部署软件项目。Jenkins提供了一个易于使用的Web界面,可以通过配置任务来实现自动化流程。

Jenkins的主要功能包括:

  • 自动化构建:Jenkins可以从代码仓库(如Git、SVN等)中获取最新的代码,并自动进行构建、编译和打包。它支持各种编程语言和构建工具,如Java、Python、Maven、Gradle等。

  • 持续集成:Jenkins可以在代码提交后自动触发构建和测试过程,以快速发现和解决代码集成问题。它可以与版本控制系统集成,如监测代码库的提交并触发自动构建。

  • 测试和部署:Jenkins可以集成各种测试框架,并在构建过程中运行自动化测试。它还可以与云平台和容器技术集成,如Docker和Kubernetes,实现自动化部署和扩展。

  • 插件生态系统:Jenkins有一个丰富的插件生态系统,提供了各种功能和集成选项。通过安装插件,可以扩展Jenkins的能力,满足特定项目的需求。

  • 可扩展性:Jenkins是一个可扩展的平台,可以通过编写自定义插件和脚本来满足特定需求。它还支持分布式构建和部署,可以在多个节点上并行执行任务,提高效率。

总结: Jenkins的使用非常广泛,许多软件开发团队都使用它来实现持续集成和部署。它的灵活性和可扩展性使得开发人员可以根据自己的需求定制和扩展工作流程。

官方网站: https://www.jenkins.io

版本说明: https://www.jenkins.io/changelog-stable/

3.前置知识

描述: 前面作者提到本章是为实现在Jenkins中实现GitOps所示搭建部署的环境,所使用到的技术栈有 Jenkins + Gitlab + Harbor + Kubernetes (Docker) ,所以此基础上,你可能需要先安装配置 Kubernetes 、Gitlab 、Harbor、Docker(可选在构建镜像时以及使用其部署jenkins-agent时会用到) 等环境, 此处作者假设你们已经安装完毕,若不了解的或者没有安装部署的朋友,可以查看作者往期文章或者下面的链接。

  • Kubernetes 是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。它提供了一种可靠的方式来运行、管理和扩展容器化应用程序,使开发人员可以专注于应用程序的开发,而无需过多关注底层基础设施的管理。

    关注公众号回复【Kubernetes学习之路】进行Kubernetes的学习(作者的入门学习K8S路线以及经验笔迹)。
    云原生 | 企业DevOps实践之使用kubeadm方式安装高可用k8s集群v1.23.7(点击访问)

  • GitLab 是一个基于Git的版本控制和源代码管理平台。它提供了一个集成的Web界面,让团队能够协作开发、管理代码存储库、进行代码审查和问题跟踪等操作。

    GitOps实践 | 快速在银河麒麟KylinOS国产系统部署最新Gitlab-CE企业私有代码仓库(点击访问)

  • Harbor 是一个开源的企业级容器镜像注册表,它提供了一个安全可靠的方式来存储、分发和管理容器镜像。它是基于Docker Registry开发的,但在其基础上添加了一些额外的功能和特性。

    GitOps实践 | 快速在银河麒麟KylinOS国产系统部署最新Harbor企业私有镜像仓库(点击访问)

  • Docker 是一种开源的容器化平台,用于构建、发布和运行应用程序。它基于Linux容器技术,通过隔离应用程序的进程、文件系统和网络等资源,实现了应用程序的轻量级虚拟化。

    关注公众号回复【Docker学习之路】进行Docker的学习(作者的入门学习Docker路线以及经验笔迹)。
    Docker 的安装请参考此篇【0x01-Docker-安装实践】文章 [https://blog.weiyigeek.top/2019/5-3-455.html#0x01-Docker-安装实践]或者Docker官网。


0x01 在 Jenkins 部署 GitOps 环境实践

1.环境说明

实践环境说明:

# K8S 高可用集群主机 x 4 & Docker 版本 & Jenkins 版本
系统发行版: Ubuntu 20.04 
Kubernetes v1.23.17 
集群SVC: https://kubernetes.default.svc.cluster.prod
Docker 20.10.3 (已经在其中一台工作节点上安装)
Jenkins 2.387.3 (其agent需要运行在JDK11以上,作者当时升级后到CI/CD不能用,只能重新构建agent镜像,当前极度痛苦)


# Gitlab 代码仓库 & Harbor 镜像仓库主机 x 2 
系统发行版: Kylin Linux Advanced Server V10 
gitlab-server 10.20.176.250 | Gitlab v16.2.0
harbor-server 10.20.176.251 | Harbor v2.8.2
Docker v24.0.4 | containerd v1.6.21 | Docker-compose v2.20.2

温馨提示: 

Jenkins 2.387.3 为 2.3x 的最后一个版本,在2023年发布的我们实践的Jenkins版本还是比较新的,Jenkins 版本发布查看 [https://www.jenkins.io/changelog-stable]

温馨提示: 若你的基础环境使用的Ubuntu 22.04/20.04或者是CentOS8可以使用如下文章所示的脚本进行安全加固(线上环境必须,过保必须)

  • 网安等保 | 主机安全之Ubuntu 22.04/20.04服务器配置优化与安全加固基线文档脚本分享 [https://mp.weixin.qq.com/s/dO1bV0tfXKn4ZmqlMcUrrQ]

  • 网安等保 | 主机安全之CentOS8服务器配置优化与安全加固基线文档脚本分享 [https://mp.weixin.qq.com/s/WrwzkNaTGQ_xss727_ag9g]

2.在Kubernetes中快速安装配置Jenkins

描述: 此小节主要实践在K8S集群中安装部署我们的Jenkins工具。

操作部署

  • Step 1.使用 deployments 控制器安装 Jenkins 其部署配置清单yaml如下所示:

tee jenkins-deployments.yaml <<'EOF' 
# 创建devops名称空间
apiVersion: v1
kind: Namespace
metadata:
  name: devops
---
# 创建PV、PVC,为Jenkins提供数据持久化支持,storage-class 需要根据实际情况进行修改.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jenkins-pvc
  namespace: devops
  annotations:
    volume.beta.kubernetes.io/storage-class: "managed-nfs-storage"
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 5Gi
---
# 创建ServiceAccount以及在devops名称空间中资源角色访问授权绑定
apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins-sa
  namespace: devops
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: jenkins-cr
rules:
  - apiGroups: ["extensions", "apps"]
    resources: ["deployments"]
    verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
  - apiGroups: [""]
    resources: ["services"]
    verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["create","delete","get","list","patch","update","watch"]
  - apiGroups: [""]
    resources: ["pods/exec"]
    verbs: ["create","delete","get","list","patch","update","watch"]
  - apiGroups: [""]
    resources: ["pods/log"]
    verbs: ["get","list","watch"]
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: jenkins-crd
roleRef:
  kind: ClusterRole
  name: jenkins-cr
  apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
  name: jenkins-sa
  namespace: devops
---
# 使用Deployment控制器部署Jenkins以及Service的创建
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins
  namespace: devops 
spec:
  selector:
    matchLabels:
      app: jenkins
  template:
    metadata:
      labels:
        app: jenkins
    spec:
      terminationGracePeriodSeconds: 10
      serviceAccount: jenkins-sa
      containers:
      - name: jenkins
        image: docker.io/jenkins/jenkins:2.387.3-alpine  # 升级时其自行备份数据已经指定Jenkins版本的镜像即可
        imagePullPolicy: IfNotPresent
        env:
        - name: JAVA_OPTS
          value: -XshowSettings:vm -Dhudson.slaves.NodeProvisioner.initialDelay=0 -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85 -Duser.timezone=Asia/Shanghai
        ports:
        - containerPort: 8080
          name: web
          protocol: TCP
        - containerPort: 50000
          name: agent
          protocol: TCP
        resources:
          limits:
            cpu: 2
            memory: 4Gi
          requests:
            cpu: 500m
            memory: 512Mi
        livenessProbe:
          httpGet:
            path: /login
            port: 8080
          initialDelaySeconds: 60
          timeoutSeconds: 5
          failureThreshold: 12
        readinessProbe:
          httpGet:
            path: /login
            port: 8080
          initialDelaySeconds: 60
          timeoutSeconds: 5
          failureThreshold: 12
        volumeMounts:
        - name: jenkinshome
          mountPath: /var/jenkins_home
      securityContext:
        fsGroup: 1000
      volumes:
      - name: jenkinshome
        persistentVolumeClaim:
          claimName: jenkins-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: jenkins
  namespace: devops 
  labels:
    app: jenkins
spec:
  selector:
    app: jenkins
  type: NodePort
  ports:
  - name: web
    port: 8080
    targetPort: web
    nodePort: 30001
  - name: agent
    port: 50000
    targetPort: agent
EOF

Step 2.使用kubectl命令创建的 PVC 持久卷创建、集群中角色创建绑定以及 Jenkins deployment 和 Services服务,执行的命令: kubectl create -f jenkins-deployments.yaml

Step 3.查看创建的PVC、POD以及SVC

~$ kubectl get pvc,pod,svc -n devops
  # NAME                                STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
  # persistentvolumeclaim/jenkins-pvc   Bound    pvc-3cd916df-91cb-470d-b9ef-e9b4f115223d   5Gi        RWX            managed-nfs-storage   23m
  
  # NAME                          READY   STATUS    RESTARTS   AGE
  # pod/jenkins-689775956-nph9z   1/1     Running   0          15m
  
  # NAME              TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                          AGE
  # service/jenkins   NodePort   10.104.214.1   <none>        8080:30001/TCP,50000:30465/TCP   15m


# 使用 exec 命令进入到Shell终端中
~$ kubectl exec -n devops -it jenkins-689775956-nph9z bash
  $ ps aux   # 可看到有两个进程正在运行
  # PID   USER     TIME  COMMAND
  # 1 jenkins   0:39 /sbin/tini -- /usr/local/bin/jenkins.sh  # 主运行文件
  # 6 jenkins  57:00 java -Duser.home=/var/jenkins_home -XshowSettings:vm -Dhudson.slaves.NodeProvisioner.initialDelay=0 -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85 -Duser.timezone=Asia/Shanghai -Djenkins.model.Jenkins.slaveAgentPort=50000 -jar /usr/share/jenkins/jenkins.war   # 运行 jenkins.war 的命令

Step 4.在资源清单中配置的NodePort类型端口为30001,我们直接在浏览器用这个端口访问Jenkins UI,

# Jenkins 初始化密码获取的两种方式;
# 方式1.认证
$ kubectl logs -n devops pod/jenkins-689775956-nph9z | grep -A 2 "following password"
  # Please use the following password to proceed to installation:
  # c45f558fa237472f9f8f954ceb3a323e  获取到首次登录密码

65189931e4314c9391fa2be054a75701.png

Step 5.此处按照【Jenkins入门学习之持续化集成与部署】[https://blog.weiyigeek.top/2020/12-28-513.html] 文章的操作进行初始化, 当然您也可以选择自定义插件安装 -> Languages (两项插件) 先进行汉化。

  • 设置 Jenkins URL

    操作: Create First Admin User -> Instance Configuration (Jenkins URL) -> Save -> Restart 安装成功
    配置: Jenkins URL: http://jenkins.weiyigeek.top:30001/ # 注意需要添加解析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/867368.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Minecraft】Fabric Mod开发完整流程3 - 配方与挖掘等级

目录 新配方工作台配方无序合成配方有序合成配方 熔炉配方 挖掘等级与掉落物挖掘等级标准等级配置易错点分析 战利品与掉落物普通方块掉落物矿石方块掉落物 新配方 工作台配方 为便于你快速创建配方&#xff0c;可以直接去这个网站上通过拖拽的方式创建属于你的配方表&#xf…

9.3.1网络原理(应用层)

HTTP和HTTPS后面的博客会另外介绍. 一.设计应用层协议: 1.明确当前请求和响应中包含哪些内容. 2.明确具体请求和响应格式. 网络上传输的数据,本质上就是字符串(无法直接传对象). 序列号:发送数据的时候,把对象转化成二进制字符串.(注意,网络上传输的数据统一为大端字节序…

基于飞桨图学习框架实现的城市地点动态关系挖掘

李双利 飞桨开发者技术专家&#xff08;PPDE&#xff09;&#xff0c;百度研究院商业智能实验室研究实习生&#xff0c;中国科学技术大学在读博士生。 主要进行时空数据挖掘和图深度学习的相关研究工作。曾获2021年百度研究院年度优秀实习生&#xff0c;有多篇基于飞桨完成的论…

Linux常见面试题,应对面试分享

操作系统基础 1.cpu占⽤率太⾼了怎么办? 排查思路是什么&#xff0c;怎么定位这个问题&#xff0c;处理流程 其他程序: 1.通过top命令按照CPU使⽤率排序找出占⽤资源最⾼的进程 2.lsof查看这个进程在使⽤什么⽂件或者有哪些线程 3.询问开发或者⽼⼤,是什么业务在使⽤这个进程…

Linux学习之sed多行模式

N将下一行加入到模式空间 D删除模式空间中的第一个字符到第一个换行符 P打印模式空间中的第一个字符到第一个换行符 doubleSpace.txt里边的内容如下&#xff1a; goo d man使用下边的命令可以实现把上边对应的内容放到doubleSpace.txt。 echo goo >> doubleSpace.txt e…

无代码集成励销云CRM连接更多应用

场景描述&#xff1a; 基于励销云的开放API&#xff0c;实现无代码集成连接励销云与其它应用。通过Aboter可轻松搭建业务自动化流程&#xff0c;实现多个应用之间的数据连接。 接口能力&#xff1a; 用户模块业务模块拜访签到模块公海客户模块联系人模块合同模块客户模块任务…

EVE-NG 隐藏没有镜像的模板

eve-ng 默认情况下&#xff0c;在添加node时&#xff0c;会列出所有的模板&#xff0c;这样用着很不方便。 通过以下方式&#xff0c;可以使没有设备的模板不可见 cp /opt/unetlab/html/includes/config.php.distribution /opt/unetlab/html/includes/config.php 如下图&#…

大数据面试题:说下Spark中的Transform和Action,为什么Spark要把操作分为Transform和Action?

面试题来源&#xff1a; 《大数据面试题 V4.0》 大数据面试题V3.0&#xff0c;523道题&#xff0c;679页&#xff0c;46w字 可回答&#xff1a;Spark常见的算子介绍一下 参考答案&#xff1a; 我们先来看下Spark算子的作用&#xff1a; 下图描述了Spark在运行转换中通过算…

tomcat服务七层搭建动态页面查看

一个服务器多实例复制完成 配置tomcat多实例的环境变量 vim /etc/profile.d/tomcat.sh配置tomcat1和tomcat2的环境变量 进入tomcat1修改配置 测试通信端口是否正常 连接正常 toncat 2 配置修改 修改这三个 端口配置修改完成 修改tomcat1 shudown 分别把启动文件指向tomcat1…

【Linux】进程信号之信号的处理

进程信号 三 一、信号的处理时机二、内核态与用户态1、内核态与用户态的转化2、重谈进程地址空间 三、信号的处理1、一般信号的处理流程2、捕捉信号的处理流程3、信号捕捉函数sigaction 一、信号的处理时机 在前面我们讲过信号产生和保存以后&#xff0c;我们知道进程对于产生…

YOLOv5、YOLOv8改进: GSConv+Slim Neck

论文题目&#xff1a;Slim-neck by GSConv: A better design paradigm of detector architectures for autonomous vehicles 论文&#xff1a;https://arxiv.org/abs/2206.02424 代码&#xff1a;https://github.com/AlanLi1997/Slim-neck-by-GSConv 在计算机视觉领域&#x…

YOLOv8“炼丹“之扑克牌识别

最近沉迷炼丹, 效果图: 框架Ultralytics YOLOv8 来自GitHub的介绍: Ultralytics YOLOv8 is a cutting-edge, state-of-the-art (SOTA) model that builds upon the success of previous YOLO versions and introduces new features and improvements to further boost pe…

Centos7源码安装redis

1、下载redis Index of /releases/ 2、解压redis tar -xvf redis-6.2.9.tar.gz 3、进入解压后的目录 cd redis-6.2.9/4、指定内存分配器为 libc make MALLOClibc 5、进入src目录&#xff0c;安装 cd src && make install6、运行 ./redis-server 7、添加开机…

IIC延时函数

别人家的程序 void i2c_Start(void) {OLED_I2C_SDA_1(); //SDA 总线置1OLED_I2C_SCL_1(); //SCL 总线置1i2c_Delay(); //延时信号OLED_I2C_SDA_0(); //置 0 i2c_Delay();OLED_I2C_SCL_0(); //SCL 置0i2c_Delay(); }延时函数 static void i2c_Delay(void) {uint8_t…

企业时代下的汽车4S店形势分析

据网上数据显示&#xff0c;2022年约有2000家汽车4S店闭店退网&#xff0c;这一数据不由令人惊叹&#xff01; 疫情放开后&#xff0c;原以为汽车经销商的春天也即将来临&#xff0c;可它们有些已经死在了半路上。 2023年伊始&#xff0c;经销商大戏以一则破产消息开幕——浙…

NR700 —基础知识

01 中国5G频段分布及700M频谱 中国运营商频段分布&#xff1a; 不同频段的无线电波的特征&#xff1a; 700M网络因其低频特性&#xff0c;有着极佳的覆盖能力和穿透能力&#xff0c;但同时相对运营商已有的高频网络有着明显的性能差距。因此700M网络更适合用于底层网络深度覆盖…

mac harbor的安装

harbor的安装 为什么要整这个呢&#xff0c;因为我在学习k8s&#xff0c;但是需要一个自己的镜像仓库。于是&#xff0c;最开始想到的就是在本地直接部署一个&#xff0c;还比较安全、快速。 直接下载了官方的项目&#xff0c;运行脚本发现出了异常&#xff0c;这种异常我已经…

帮群里一位留学生订机票,省了2.2万元

注&#xff1a;此篇文章为峰哥环游世界番外篇&#xff0c;我会记录很多我认为值得分享的图文。在环游世界交流群里的同学记得扫描下方二维码直接观看&#xff0c;不要付费&#xff0c;具体事宜可以看贴&#xff1a;付费文章说明&#xff01; 想进一步了解我环游世界的故事&…

React 之 Suspense和lazy

一. Suspense 参考链接&#xff1a;https://react.docschina.org/reference/react/Suspense suspense&#xff1a;n. 焦虑、悬念 <Suspense> 允许你显示一个退路方案&#xff08;fallback&#xff09;直到它的所有子组件完成加载。 <Suspense fallback{<Loadin…

history记录日期时间和日志记录操作

history命令能查看到操作日期和时间的配置方法&#xff1a; 1&#xff09;在/etc/profile文件中添加一行&#xff1a; export HISTTIMEFORMAT"%F %T whoami " 2&#xff09;保存后&#xff0c;执行加载命令&#xff1a; source /etc/profile 3&#xff09;然后检…