如何搭建android源代码repo仓库

.
版本: v0.3
作者:河东西望
日期:2022-7-5
.

如果你的开发是基于AOSP源码来建仓,那么搭建repo服务器和部署自己的repo仓库就是非常必要的工作了。

现实中很多公司都是直接把AOSP源代码放在一个git仓库中来管理,这样做没什么毛病。但是如果开发团队人数较多,会存在一些明显的弊端:

AOSP源代码结构复杂庞大,除了本身的代码模块之外,还集成了五六百个第三方仓库,这些仓库也会在不停的更新迭代。AOSP维护整个代码仓库框架就需要保持足够的灵活性,于是就引进了repo脚本来批量管理git仓库。AOSP的源代码切分的git仓库数量多达六七百多个。

如果我们想要跟上游平台仓库保持一致的仓库结构,很方便快捷的同步代码,而我们自己也能灵活的管理本地的扩展仓库,就需要搭建部署自己的repo仓库了。

在实际的团队开发实践中,代码管理框架一般是gerrit+repo的组合形式。gerrit的安装部署和权限管理等不是本文档的内容,请读者搜索网络材料来安装部署。本文档的主要内容包括:

本文档的服务器操作系统是ubuntu18.04。

1.1 repo如何工作的?

新的操作系统安装包中已经包含了repo命令程序,可以直接通过下面的命令安装:

sudo apt-get install repo

查看repo版本
repo --version

<repo not installed>
repo launcher version 2.17
       (from /usr/local/bin/repo)
git 2.34.1
Python 3.10.4 (main, Apr  2 2022, 09:04:19) [GCC 11.2.0]
OS Linux 5.15.0-39-generic (#42-Ubuntu SMP Thu Jun 9 23:42:32 UTC 2022)
CPU x86_64 (x86_64)
Bug reports: https://bugs.chromium.org/p/gerrit/issues/entry?template=Repo+tool+issue
</repo>

安装完毕,我们可以看到安装的实际上是一个repo的引导器。它还不是完整的管理工具。

通过cat命令查看一下repo文件,实际上是一个python3脚本.

which repo
/usr/local/bin/repo

cat /usr/local/bin/repo
........

客户端在同步仓库时一般用到的几个命令序列:

&#x521D;&#x59CB;&#x5316;&#x4ED3;&#x5E93;
repo init -u ....

&#x68C0;&#x51FA;&#x4EE3;&#x7801;
repo sync -j16
&#x5EFA;&#x7ACB;&#x672C;&#x5730;&#x5206;&#x652F;
repo start <branch> --all
&#x6279;&#x91CF;&#x6267;&#x884C;git&#x547D;&#x4EE4;
repo forall -c GIT COMMAND
</branch>

我们以清华大学官网的AOSP代码为例,操作一下repo的仓库同步。

&#x8BBE;&#x7F6E;&#x4E00;&#x4E0B;REPO_URL&#x3002;
export REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/'

mkdir -p ~/aosp
cd aosp

&#x521D;&#x59CB;&#x5316;&#x4ED3;&#x5E93;
repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest
Downloading Repo source from https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/
remote: Enumerating objects: 7372, done.

remote: Counting objects: 100% (7372/7372), done.

remote: Compressing objects: 100% (3935/3935), done.

remote: Total 7372 (delta 4765), reused 5577 (delta 3363)
&#x63A5;&#x6536;&#x5BF9;&#x8C61;&#x4E2D;: 100% (7372/7372), 3.27 MiB | 3.58 MiB/s, &#x5B8C;&#x6210;.

&#x5904;&#x7406; delta &#x4E2D;: 100% (4765/4765), &#x5B8C;&#x6210;.

... A new version of repo (2.21) is available.

... You should upgrade soon:
    cp /home/xxx/Documents/aosp/.repo/repo/repo /usr/local/bin/repo

Downloading manifest from https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest
remote: Enumerating objects: 98793, done.

remote: Counting objects: 100% (98793/98793), done.

remote: Compressing objects: 100% (39423/39423), done.

remote: Total 98793 (delta 38918), reused 98123 (delta 38532)
&#x63A5;&#x6536;&#x5BF9;&#x8C61;&#x4E2D;: 100% (98793/98793), 25.23 MiB | 2.40 MiB/s, &#x5B8C;&#x6210;.

&#x5904;&#x7406; delta &#x4E2D;: 100% (38918/38918), &#x5B8C;&#x6210;.

Your identity is: xxx <xxx@sina.com>
If you want to change this, please re-run 'repo init' with --config-name

Testing colorized output (for 'repo diff', 'repo status'):
  black    red      green    yellow   blue     magenta   cyan     white
  bold     dim      ul       reverse
Enable color display in this user account (y/N)? y

repo has been initialized in /home/xxx/Documents/aosp/
If this is not the directory in which you want to initialize repo, please run:
   rm -r /home/yl/Documents/aosp//.repo
and try again.

</xxx@sina.com>

repo init命令执行完毕,实际上就是下载了一个.repo目录下(repo命令版本过时,可以根据提示更新一下,也可以不用更新)。

我们看一下repo目录内容:

repo
&#x251C;&#x2500;&#x2500; manifests        // &#x6E05;&#x5355;&#x4ED3;&#x5E93;
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; .git -> ../manifests.git/
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; default.xml  // &#x771F;&#x6B63;&#x7684;&#x4ED3;&#x5E93;&#x6E05;&#x5355;&#x6587;&#x4EF6;
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; GLOBAL-PREUPLOAD.cfg
&#x2502;&#xA0;&#xA0; &#x2514;&#x2500;&#x2500; OWNERS
&#x251C;&#x2500;&#x2500; manifests.git    // &#x6E05;&#x5355;&#x4ED3;&#x5E93;git&#x914D;&#x7F6E;&#x4FE1;&#x606F;
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; branches
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; config
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; description
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; FETCH_HEAD
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; HEAD
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; hooks
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; index
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; info
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; logs
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; objects
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; packed-refs
&#x2502;&#xA0;&#xA0; &#x2514;&#x2500;&#x2500; refs
&#x251C;&#x2500;&#x2500; manifest.xml     // &#x6E05;&#x5355;&#x6587;&#x4EF6;&#xFF0C;&#x5185;&#x5BB9;&#x5305;&#x542B;default.xml&#x6587;&#x4EF6;
&#x2514;&#x2500;&#x2500; repo             // repo&#x5DE5;&#x5177;&#x811A;&#x672C;
    &#x251C;&#x2500;&#x2500; color.py
    &#x251C;&#x2500;&#x2500; command.py
    &#x251C;&#x2500;&#x2500; git_trace2_event_log.py
    &#x251C;&#x2500;&#x2500; hooks
    &#x251C;&#x2500;&#x2500; hooks.py
    &#x251C;&#x2500;&#x2500; repo
    &#x251C;&#x2500;&#x2500; .........

    &#x2514;&#x2500;&#x2500; wrapper.py

repo init干了这几件事情:

repo批量管理仓库的内容就在default.xml中。我们看一下文件内容:

<?xml version="1.0" encoding="UTF-8"?>
<manifest>

  <remote name="aosp" fetch=".." review="https://android-review.googlesource.com/">
  <default revision="master" remote="aosp" sync-j="4">

  <manifest-server url="http://android-smartsync.corp.google.com/android.googlesource.com/manifestserver">

  <superproject name="platform/superproject" remote="aosp">
  <contactinfo bugurl="go/repo-bug">

  <project path="build/make" name="platform/build" groups="pdk">
    <linkfile src="CleanSpec.mk" dest="build/CleanSpec.mk">
    <linkfile src="buildspec.mk.default" dest="build/buildspec.mk.default">
    <linkfile src="core" dest="build/core">
    <linkfile src="envsetup.sh" dest="build/envsetup.sh">
    <linkfile src="target" dest="build/target">
    <linkfile src="tools" dest="build/tools">
  </linkfile></linkfile></linkfile></linkfile></linkfile></linkfile></project>
  <project path="build/bazel" name="platform/build/bazel" groups="pdk">
    <linkfile src="bazel.WORKSPACE" dest="WORKSPACE">
    <linkfile src="bazel.sh" dest="tools/bazel">
    <linkfile src="bazel.BUILD" dest="BUILD">
  </linkfile></linkfile></linkfile></project>
  <project path="build/bazel_common_rules" name="platform/build/bazel_common_rules" groups="pdk">
  <project path="build/blueprint" name="platform/build/blueprint" groups="pdk,tradefed">
  <project path="build/pesto" name="platform/build/pesto" groups="pdk">
  <project path="build/soong" name="platform/build/soong" groups="pdk,tradefed">
    <linkfile src="root.bp" dest="Android.bp">
    <linkfile src="bootstrap.bash" dest="bootstrap.bash">
  </linkfile></linkfile></project>
  <project path="art" name="platform/art" groups="pdk">
  <project path="bionic" name="platform/bionic" groups="pdk">
  <project path="bootable/recovery" name="platform/bootable/recovery" groups="pdk">
  <project path="bootable/libbootloader" name="platform/bootable/libbootloader" groups="vts,pdk">
  <project path="device/common" name="device/common" groups="pdk-cw-fs,pdk">
  <project path="device/generic/arm64" name="device/generic/arm64" groups="pdk">
  <project path="device/generic/armv7-a-neon" name="device/generic/armv7-a-neon" groups="pdk">
  <project path="device/generic/art" name="device/generic/art" groups="pdk">
  ......

  <repo-hooks in-project="platform/tools/repohooks" enabled-list="pre-upload">

  <!--
    Merge marker to make it easier for git to merge AOSP-only manifest
    changes to a custom manifest.  Please keep this marker here and
    refrain from making changes on or below it.

  -->
</repo-hooks></project></project></project></project></project></project></project></project></project></project></project></contactinfo></superproject></manifest-server></default></remote></manifest>

这个XML文件的语法,不是本文档的内容。简单说明一下几个关键的:

remote: 远程服务端repo仓库名称
project: 每个项目的git仓库
path: 客户端git仓库路径
name: 服务端git仓库名称
revision: 分支名称或者commit id
linkfile: 软链接文件,src和dest表示源和目的。
copyfile: 文件拷贝,src和dest表示源和目的。
groups: 分组。

概括一下repo批量管理仓库的方式:

所以,repo仓库的管理核心就在manifest.git,而起关键作用的配置文件就是仓库清单文件xxx.xml,有多少个项目仓库,就有对应的xml清单文件。

1.2 搭建repo服务需要做哪些事情?

接着就是关键问题:搭建repo服务器我们要做哪些事情?

简而言之:

实际上,如果你的网络链接可以链接到外网的话,工具仓库git-repo.git是不需要搭建部署的。

只需要通过REPO_URL这个环境变量来指定URL就可以自动拉取git-repo.git仓库。

export REPO_URL=https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/

常用的URL有这些:

## google&#x5730;&#x5740;&#xFF0C;&#x9700;&#x8981;&#x68AF;&#x5B50;&#x3002;
https://gerrit.googlesource.com/git-repo

## &#x6E05;&#x534E;&#x5927;&#x5B66;&#x5F00;&#x6E90;&#x8F6F;&#x4EF6;&#x955C;&#x50CF;&#x7AD9;
https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/

## &#x5176;&#x4ED6;&#x53EF;&#x4EE5;&#x81EA;&#x5DF1;&#x7F51;&#x4E0A;&#x641C;&#x7D22;...

但是现实中,很多公司的外网是受限的,无法访问。这个时候就需要考虑搭建自己的工具仓库git-repo.git了。

这个仓库的搭建很简单,就是一个普通的git仓库,但是涉及到GPG签名的问题就比较复杂。这个过程不是本文档的内容,可以搜索互联网上的文档资料。

部署清单仓库的方式,跟普通的git仓库没有什么差别。关键问题在:

3.1 如何设计清单仓库及分支?

从服务器的角度来看,你的服务器上肯定会管理多个项目仓库(例如qcom8953,qcom8916,mtk6219,mtk2226,rk3399,rk3358等等),那我们管理这些仓库的方式可能有:

这两种方式都可以,取决于你的代码管理策略。我一般在整个服务器上使用一个manifests.git仓库,通过不同的xml文件来管理所有的项目仓库。服务器端项目仓库的目录结构设计如下:
aosp
├── manifests.git // 清单仓库
│ ├── qcom8953.xml
│ ├── rk3399.xml
│ ├── rk3358.xml
│ └── mtk6226.xml
├── qcom/qcom8953 // 项目仓库
├── rockchip/rk3399 // 项目仓库
├── rockchip/rk3358 // 项目仓库
└── mtk/mtk6226 // 项目仓库

清单仓库本身就是一个普通的git仓库,他也是有分支的。同一个配置文件,例如qcom8953.xml,他也可以切分出不同的分支,来管理不同的项目仓库版本。

清单仓库的分支,跟项目仓库的分支没有直接的关联关系。但是在实践操作中,我们一般会在清单仓库中建立项目仓库对应的分支,方便管理映射。例如qcom8953项目仓库,它有4个分支master、develop、test和release,那么我们的manifests.git也可以建立四个分支,跟项目仓库对应起来。

我这里建立两个分支:master和release。后面会按照这两个分支来操作。

我们先看一下repo init命令的常用参数:

repo init --help
Usage: repo init [options] [-u] url

Options:

  Manifest options:
    -u URL, --manifest-url=URL
                        manifest repository location
    -b REVISION, --manifest-branch=REVISION
                        manifest branch or revision (use HEAD for default)
    -m NAME.xml, --manifest-name=NAME.xml
                        initial manifest file

  repo Version options:
    --repo-url=URL      repo repository location ($REPO_URL)
    --repo-rev=REV      repo branch or revision ($REPO_REV)
    --no-repo-verify    do not verify repo source code

  Other options:
    --config-name       Always prompt for name/e-mail

一般来说,-b的默认值是master,-m的默认值是manifests.xml。如果我们想要使用不同的默认的清单文件,就需要在编写服务端清单文件和repo init参数时需要配合使用。

我这里全部使用默认值。在aosp源码的mannifests.xml中则体现在这几个项上:

  <remote name="aosp" fetch=".." review="https://android-review.googlesource.com/">
  <default revision="master" ## 远程默认分支 remote="aosp" 远程默认仓库,就是remote标签中的name="aosp" sync-j="4">
</default></remote>

3.2 如何编写清单文件?

编写清单文件,肯定不可能全部手写,需要拿到一份原始的manifests.xml文件。这份文件需要你从你的源头代码repo仓库中获取是最好的。

我这里就以qcom的AOSP源码为例,修改出我自己的仓库qcom8953.xml。

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
    <!-- remote: 服务器远程仓库的信息。 name: 远程manifest仓库名称,一般默认为origin fetch: 仓库url。如果设置为"."(注意是一个点), 就表示在repo init -u url中配置。 review: 评审系统网址。如果提交代码,就会进入这个评审系统。 -->
    <remote name="origin" fetch="." review="gerrit.your_domain.com">
        <!--
          default: 这个repo仓库的默认属性。
          revision: 默认的工程代码仓库分支,可以修改这里来指向不同的分支。
          remote:   远程仓库的名称。这里跟<remote>标签是对应的,当然还可以指向其他仓库的remote。
        -->
        <default revision="master" remote="origin">

        <!--
            project: 每个仓库就是一个project
            path: 客户端同步到本地后的路径名称。
            name: 服务器端git仓库名称,注意带了路径。
        -->
        <project path="build" name="build">
        <project path="device" name="device">
        <project path="frameworks/base" name="frameworks/base">
        <!--
            重要说明:
            这里的build目录和其下的三个子目录:blueprint, kati, soong是嵌套的git仓库结构!
            这种嵌套的git仓库。有一个非常重要的控制文件:.gitignore.

            父级目录那种一定存在一个.gitignore文件,其中包含了嵌套的子级仓库路径。
        -->
        <project path="build" name="build">
            <!-- copyfile: 将build/core/root.mk拷贝为Makefile。其中带有相对路径 -->
            <copyfile src="core/root.mk" dst="Makefile">
        </copyfile></project>
        <project path="build/blueprint" name="build/blueprint">
        <project path="build/kati" name="build/kati">
        <project path="build/soong" name="build/soong">
            <!-- linkfile: 建立一个软链接Android.bp指向build/soong/root.bp -->
            <linkfile src="root.bp" dest="Android.bp">
            <linkfile src="bootstrap.bash" dest="bootstrap.bash">
         </linkfile></linkfile></project>
         <!-- 更多仓库信息 ...... -->
</project></project></project></project></project></default></remote></!--></manifest>

3.3 创建清单仓库manifests.git

创建清单仓库可以有两种方式:

第一种方式比较简单,在WEB页面上操作就可以,没有什么特别的。

重点介绍第二种命令行方式。

ssh -p 29418 <username>@<gerrit_ip_address> gerrit create-project aosp/manifests.git
</gerrit_ip_address></username>

创建完毕,在gerrit页面上也可以看到这个manifests.git仓库。管理员可以在页面上创建两个分支:master,release。

客户端按照正常的git操作操作:

## &#x514B;&#x9686;&#x4EE3;&#x7801;
git clone .../manifests.git
## &#x63D0;&#x4EA4;&#x6E05;&#x5355;&#x6587;&#x4EF6;qcom8953.xml
git add qcom8953.xml
git commit -m "add qcom8953.xml"
git push

这样我们就建立了一个manifests.git仓库,并上传了一个清单文件qcom8953.xml。

下一步就是如何创建项目仓库了。

初始工程仓库的源代码,最好来自平台厂商提供的带了.repo和.git的完整repo仓库,然后我们看看如何将这个仓库移植到我们自己的内部仓库。

一般的操作步骤:

4.1 批量创建服务端空仓库

批量创建子仓库只能通过gerrit命令行来进行。

ssh -p 29418 <username>@<gerrit_ip_address> gerrit create-project aosp/qcom8953/xxx.git
</gerrit_ip_address></username>

这里我们需要知道的qcom8953仓库的所有仓库名字,然后通过脚本来批量创建,有两种方式:

我们最终需要一个仓库列表文件:project.list。文件内容如下:

qcom/qcom8953/art
qcom/qcom8953/bionic
qcom/qcom8953/bootable/bootloader/edk2
qcom/qcom8953/bootable/recovery
qcom/qcom8953/build/blueprint
qcom/qcom8953/build/kati
qcom/qcom8953/build
qcom/qcom8953/build/soong
qcom/qcom8953/cts
qcom/qcom8953/dalvik
qcom/qcom8953/developers/build
qcom/qcom8953/developers/demos/JustForUs
qcom/qcom8953/developers/samples/android
qcom/qcom8953/development
qcom/qcom8953/device/common
qcom/qcom8953/device/generic/arm64
qcom/qcom8953/device/generic/armv7-a-neon
......

接下来我们可以使用下列命令来批量创建服务端空仓库:

&#x53C2;&#x6570;&#x8BF4;&#x660E;
--empty-commit: &#x5F3A;&#x5236;&#x53C2;&#x6570;, &#x5FC5;&#x987B;&#x6DFB;&#x52A0;;
-p YOUR-projects&#xFF1A; &#x4F60;&#x7684;gerrit&#x6743;&#x9650;&#x4ED3;&#x5E93;&#x3002;&#x6839;&#x636E;&#x4F60;&#x7684;gerrit&#x6743;&#x9650;&#x540D;&#x79F0;&#x6765;&#x786E;&#x5B9A;&#x3002;
&#x5176;&#x4ED6;&#x53C2;&#x6570;&#x5C31;&#x4E0D;&#x8981;&#x518D;&#x6DFB;&#x52A0;&#x4E86;&#xFF0C;&#x753B;&#x86C7;&#x6DFB;&#x8DB3;&#x4EE5;&#x540E;&#xFF0C;&#x591A;&#x51FA;&#x5F88;&#x591A;&#x95EE;&#x9898;&#x3002;
&#x6CE8;&#x610F;&#x8FDC;&#x7A0B;&#x4ED3;&#x5E93;&#x540D;&#x79F0;&#x524D;&#x9700;&#x8981;&#x5E26;path&#x524D;&#x7F00;(qcom/qcom8953)&#xFF0C;&#x9632;&#x6B62;&#x670D;&#x52A1;&#x5668;&#x7AEF;&#x4ED3;&#x5E93;&#x8DEF;&#x5F84;&#x6DF7;&#x4E71;&#x3002;

cat project.list | xargs -I {}  ssh -p 29418 root@192.168.1.1 gerrit create-project "{}" --empty-commit -p YOUR-projects

创建完毕,在gerrit页面上就看到了几百个git仓库。

4.2 预处理本地repo代码

在上传本地repo仓库之前,需要做几个预处理动作:

git remote set-url origin ssh://root@192.168.1.1:29418/xxx

4.3 上传分支和代码

仓库预处理完毕,你需要一一上传各仓库的指定的分支和代码到服务器仓库。
这里是通用的操作, 你也需要自己编写脚本进行上传同步:

git checkout master
git push origin master:master
git push -- tags

当然,上传之后,你最好在第三方测试验证一下,是不是有些.gitignore或者某些嵌套仓库存在问题,需要手工进行修复。

repo仓库搭建完毕,对客户端来说,使用操作并不麻烦,使用常用的repo命令和git命令即可完成代码提交。

&#x521D;&#x59CB;&#x5316;&#x4ED3;&#x5E93;
repo init -u <remote manifests url> -n <manifests branch> -m <manifest name.xml>
&#x68C0;&#x51FA;&#x4EE3;&#x7801;
repo sync -j16
&#x5EFA;&#x7ACB;&#x672C;&#x5730;&#x5206;&#x652F;
repo start <branch> --all
&#x6279;&#x91CF;&#x6267;&#x884C;git&#x547D;&#x4EE4;
repo forall -c GIT COMMAND
</branch></manifest></manifests></remote>

单个仓库的代码提交合并:

git add xxx
git commit -m "xxxx"
git push HEAD:refs/for/BRANCH

初次提交时可能会报告no change id的小错误,百度搜索一下,很容易修复的。

Original: https://www.cnblogs.com/aosp/p/16445394.html
Author: 河东西望
Title: 如何搭建android源代码repo仓库

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/644309/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 1956和1985高程转换

    Original: https://www.cnblogs.com/gisoracle/p/16394986.htmlAuthor: gisoracleTitle: 1956和19…

    技术杂谈 2023年5月30日
    091
  • Linux下安装MySQL问题及报错解决

    前言: 在Linux环境下,安装MySQL服务 环境: 虚拟机CentOS7———————&#8…

    技术杂谈 2023年6月21日
    0131
  • .net自动分类算法【原创】

    目前自动分类算法是参考网上的思路和想法个人自主研发的。 当然互联网上有很多人采用不同的方式去解决自动分类问题,也有不同的算法和论文支持去做,但纵观自动分类这块工作是属于机器学习这块…

    技术杂谈 2023年7月24日
    063
  • Lambda表达式

    1.常见单方法接口 Comparator Runnable Callable @FunctionalInterface 只定义了单方法的接口称之为 FunctionalInterf…

    技术杂谈 2023年7月24日
    080
  • MySQL — 数据操作语言

    DML 全称 Data Manipulation Language。数据操作语言,用来对数据库表中的数据进行增删改。 插入一条数据 插入多条数据 update &#x886…

    技术杂谈 2023年7月11日
    078
  • Windows权限维持

    Windows权限维持 来源 https://cloud.tencent.com/developer/article/1850726 0x01 前言 红队人员拿到一台主机权限后首先…

    技术杂谈 2023年5月31日
    0148
  • PyTorch 介绍 | LEARN THE BASICS

    大多数机器学习流程都包括数据、创建模型、优化模型参数,以及保存训练模型工作。该教程向你介绍一个在PyTorch上实现的完整的机器学习工作流,并提供了了解这些概念详细信息的链接。 我…

    技术杂谈 2023年7月25日
    077
  • 关于 Delphi 中流的使用(1) 用 TMemoryStream(内存流) 入门

    所谓”流”, 就是一段数据或是一块内存; 在进行流操作时, 我们不必关心流中的数据到底是什么; 只需要知道流的大小和当前的指针位置. 所以流只有两个属性: …

    技术杂谈 2023年5月31日
    092
  • k8s整合Traefik2入门(一)

    k8s整合Traefik入门(一) 安装 首先下载helm,根据自己的k8s版本来选择相应的版本 [root@k8s-master1 ~]# tar -zvxf helm-v3.6…

    技术杂谈 2023年5月31日
    0125
  • Wireshark抓包工具使用教程以及常用抓包规则

    Wireshark是一个非常好用的抓包工具,当我们遇到一些和网络相关的问题时,可以通过这个工具进行分析,不过要说明的是,这只是一个工具,用法是非常灵活的,所以今天讲述的内容可能无法…

    技术杂谈 2023年6月1日
    0111
  • Linux特殊权限之suid、sgid、sbit权限

    文件权限管理之特殊命令 一:特殊权限 昨天所学的Linux基本权限为为9个;分别是rwx rwx rwx。但有时会发现系统中会有一些特殊的权限位符号; 例如: Linux系统一共有…

    技术杂谈 2023年7月11日
    0124
  • JVM中的进程和线程

    阻塞状态(Blocked): 线程暂时停止运行,重新进入就绪状态后,再次获得CPU资源才会进入运行状态。 阻塞状态分为三种:同步阻塞、等待(wait)阻塞、其他阻塞同步阻塞: 多个…

    技术杂谈 2023年6月21日
    088
  • 今天把HP6520S笔记本给拆解了

    今天把HP6520S笔记本给拆解了 两年前买的爱机 HP 6520s,实在欢喜的不得了,但随着每天15小时左右的高负荷工作,爱机 最近的风扇声音也开始烦躁起来了,且一天叫个不停,难…

    技术杂谈 2023年7月11日
    092
  • 「实用」打造自我感觉非常漂亮的Mac终端

    背景 (今天我是一个美妆博主😊)突然发现自己使用的iterm2终端样式有些朴素,为了让她看起来花枝招展的,我决定给她打扮打扮。毕竟每天面对她的时间比对象还多…&#823…

    技术杂谈 2023年7月24日
    0113
  • Elasticsearch Analyzer 内置分词器

    Elasticsearch Analyzer 内置分词器 篇主要介绍一下 Elasticsearch中 Analyzer 分词器的构成 和一些Es中内置的分词器 以及如何使用它们 …

    技术杂谈 2023年7月10日
    095
  • Java异步执行器CompletableFuture源码解析

    CompletableFuture是对 Future的一种强有力的扩展, Future只能通过轮询 isDone()方法或者调用 get()阻塞等待获取一个异步任务的结果,才能继续…

    技术杂谈 2023年7月24日
    092
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球