从零出发

中义传家美,永保万年春

0%

如何让Typora上传图片到指定图床

一、先看效果

Typora自动上传图片

我们发现复制Typora的图片先由本地地址经过Uploading自动变成网络图片地址,这个网络地址根目录就叫做图床

二、为什么要使用图床

在我们使用Typora编写Markdown文档时,可以设置本地相对路径自动上传到本地,就像这样:

image-20211221134122019

看起来也很方便,不过在有些方面是无法和图床相比的,比如:

  • 文档编写要关注文档本身,使用网络图片可以减少文档整体大小,而且不会因为忘记拷贝图片文件夹导致图片无法加载。
  • 如果文档作为项目的一部分,整个项目结构怎么管理都不好,一段url就能搞定多好啊。
  • 可重复利用。

三、Typora如何实现自动上传图片

3.1 准备工作

点击Typora工具栏,格式=》图像=》全局图像设置,我们发现如下图:

image-20211221221747157

插入图片时栏目有上传图片选项,上传服务设定栏目有三种方式可供选择,凭直觉我选**PicGO-Core(command line)**,因为它肯定比APP更好用,因为轻量且干净。

点击下载或更新按钮,会发现正在安装PicGO-Core。

下载安装过程中可能会卡住,关掉Typora再试一次就会好。

安装好后,Windows系统会出现这个C:\Users\{username}\AppData\Roaming\Typora\picgo\win64\picgo.exe可执行程序。同时点一下打开配置文件,我们可以定位到C:\Users\{username}\.picgo这个隐藏目录,里面的config.json就是上传服务设定的配置文件。

它应该是这样的:

1
2
3
4
5
6
7
{
"picBed": {
"current": ""
},
"picgoPlugins": {
}
}

显然这个就是让我们配置图床信息和picgo插件的地方,还提供了验证图片上传选项功能让我们进行配置验证。

得出以下几步:

  1. 配置自己需要的图床信息。

  2. 可能需要安装picgo插件。

  3. 配置好之后进行验证图片上传选项按钮验证。

  4. 实际操作一番,就像我的动图一样。

3.2 理解PicGo

我们很轻易就能找到PicGo官方文档。从文档中我们发现配置文件picBed支持很多图床,默认是smms,只需要登录smms获取token,设置一个属性就可以了。

1
2
3
{
"token": "" // 注册后获取的 api token
}

还支持七牛、又拍云、腾讯云、GitHub、阿里云、自定义代理很多种图床,但是没有我想要的,我想用minio

在网站picgoPlugins和picgo-plugin-*条目上告诉我们PicGo是支持第三方插件的,那么我们需要找到picgo-plugin-minio

3.3 安装picgo-plugin-minio

1
C:\Users\{username}\AppData\Roaming\Typora\picgo\win64\picgo.exe install picgo-plugin-minio 

注意:需要在上面提到的config.json目录C:\Users\{username}\.picgo中执行,不然后面.\picgo.exe set uploader无法选择minio。

2023年3月1日笔者再次使用时发现,以上命令报错会报错:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
C:\Users\fusionshen\.picgo>C:\Users\fusionshen\AppData\Roaming\Typora\picgo\win64\picgo.exe install picgo-plugin-minio
npm ERR! code E404
npm ERR! 404 Not Found - GET https://registry.npmjs.org/picgo-plugin-picgo-plugin-minio - Not found
npm ERR! 404
npm ERR! 404 'picgo-plugin-picgo-plugin-minio@*' is not in this registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.

npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\fusionshen\AppData\Local\npm-cache\_logs\2023-03-01T02_39_55_325Z-debug-0.log
(node:9132) UnhandledPromiseRejectionWarning: #<Object>
(node:9132) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:9132) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

可以换一种思路:在C:\Users\{username}\.picgo中执行npm install picgo-plugin-minio,然后依次执行下面配置,即可正常。

这种方式需要本机安装过NodeJS,如果没有,推荐使用nvm安装NodeJS。Windows安装nvm执行文件时两个目录都不要带空格。

3.4 配置minio

1
2
3
4
5
6
7
8
9
10
11
PS C:\WINDOWS\system32> cd C:\Users\{username}\AppData\Roaming\Typora\picgo\win64\
PS C:\Users\{username}\AppData\Roaming\Typora\picgo\win64> .\picgo.exe set uploader
? Choose a(n) uploader
imgur
aliyun
upyun
> minio
smms
tcyun
github
(Move up and down to reveal more choices)

选择minio依次填入相关选项,当然你也可以手动维护C:\Users\{username}\.picgo\config.json,这个命令可以给我们提供配置文件模板,最后你的config.json应该是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"picBed": {
"current": "minio",
"minio": {
"endPoint": "oss.website.com",
"port": "",
"useSSL": true,
"accessKey": "username",
"secretKey": "password",
"bucket": "yourbucket",
"sameNameFileProcessingMode": "跳过",
"baseDir": "",
"customDomain": "",
"isAutoArchive": true
}
},
"picgoPlugins": {
"picgo-plugin-minio": true
}
}

注意endPoint不带http[s]://

3.5 上传验证

我们可以借助验证图片上传选项验证配置是否正确,当然也能验证minio是否配置正确,最后定能看到如下所示:

image-20211221232740613

四、体会效率吧

image-20211221131110127

Tips:原先使用本地图片的Markdown文档,也可以选择图片右键自动上传哦。

使用CompletbaleFuture搞定循环取值

一、先看代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* 使用CompletableFuture完成
* @author fusionshen
* @date 2021年12月25日
* @param lineCode
* @param date
* @return
*/
@Override
public List<InspectItem> getInspectRecordsInSomeday(String lineCode, String date) {
Supplier<List<InspectItem>> getOuterItemInfoTask = () -> hbl4Service.selectInspectItemListByLineCode(lineCode);
List<InspectItem> join = CompletableFuture.supplyAsync(getOuterItemInfoTask).join();
List<CompletableFuture<InspectItem>> collect = join.stream().map(t ->
CompletableFuture.supplyAsync(() -> {
try {
return getRecentDataTask(t, LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd")));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return t;
})).collect(Collectors.toList());
// 调用allOf, 需要构造数组结构
CompletableFuture<Void> allFutures = CompletableFuture.allOf(collect.toArray(new CompletableFuture[collect.size()]));
CompletableFuture<List<InspectItem>> listCompletableFuture =
allFutures.thenApply(t -> collect.stream().map(v -> v.join()).collect(Collectors.toList()));
return listCompletableFuture.join();
}

二、无返回值的情况

1
2
3
4
5
6
7
8
9
10
11
List<CompletableFuture<Void>> collect = docUrlList.stream().map(t ->
CompletableFuture.runAsync(() -> {
try {
doInsertDocumentDetail(t, contractId);
} catch (Exception e) {
e.printStackTrace();
}
})).collect(Collectors.toList());
// 调用allOf, 需要构造数组结构
CompletableFuture<Void> allFutures = CompletableFuture.allOf(collect.toArray(new CompletableFuture[collect.size()]));
allFutures.join();

三、退化版FutureTask

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
* 使用FutureTask计算,可考虑替换成CompletableFuture
*
* @param lineId 管控线Id
* @param procedureCode 工序编码
* @param date 日期,格式"yyyy-MM-hh"
* @return
*/
@Override
public List<InspectItem> getHourlyInspectRecords(String lineId, String procedureCode, String date) {
// 获取管控项信息列表
List<InspectItem> inspectItems = hbl4Service.selectInspectItemList(lineId, procedureCode);
if (inspectItems.isEmpty()) {
throw new IllegalArgumentException("管控线Id和工序编码传入有误");
}
// 并发管控项取监测数据,将数据作为data字段存入
List<InspectItem> resultList = new ArrayList<>();
List<Future<InspectItem>> futures = new ArrayList<>();
ExecutorService executorService = Executors.newCachedThreadPool();
System.out.println("已经提交资源申请");
for (InspectItem inspectItem : inspectItems) {
futures.add(executorService.submit(() -> getHourlyDataTask(inspectItem, LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd")))));
}
futures.stream().forEach(f -> {
if (!f.isDone()) {
System.out.printf("资源还没有准备好");
}
try {
resultList.add(f.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
});
executorService.shutdown();
return resultList;
}

四、总结

  • CompletableFuture是FutureTask的增强版,优先考虑使用前者。
  • 一和二是范式,可直接套用,try-catch中放入需要实现的耗时业务。
  • 面试再被问平常工作中是否用过多线程,YES!!!

Git使用分享

一、Git概述

1.1 Git历史

Git 诞生于一个极富纷争大举创新的年代。Linux 内核开源项目有着为数众多的参与者。 绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。 到 2002 年,整个项目组开始启用一个专有的分布式版本控制系统 BitKeeper 来管理和维护代码。
到了 2005 年,开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了 Linux 内核社区免费使用 BitKeeper 的权力。 这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linus Torvalds)基于使用 BitKeeper 时的经验教训,开发出自己的版本控制系统。
他们对新的系统制订了若干目标:

  • 速度
  • 简单的设计
  • 对非线性开发模式的强力支持(允许成千上万个并行开发的分支)
  • 完全分布式
  • 有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量)

    1.2 Git与SVN对比

    SVN是集中式版本控制系统,版本库是集中放在中央服务器的,而开发人员工作的时候,用的都是自己的电脑,所以首先要从中央服务器下载最新的版本,然后开发,开发完后,需要把自己开发的代码提交到中央服务器。
    Git 与 SVN 区别点:
  • 1、Git 是分布式的,SVN 不是:这是 Git 和其它非分布式的版本控制系统,例如 SVN,CVS 等,最核心的区别。
  • 2、Git 把内容按元数据方式存储,而 SVN 是按文件:所有的资源控制系统都是把文件的元信息隐藏在一个类似 .svn、.cvs 等的文件夹里。
  • 3、Git 分支和 SVN 的分支不同:分支在 SVN 中一点都不特别,其实它就是版本库中的另外一个目录。
  • 4、Git 没有一个全局的版本号,而 SVN 有:目前为止这是跟 SVN 相比 Git 缺少的最大的一个特征。
  • 5、Git 的内容完整性要优于 SVN:Git 的内容存储使用的是 SHA-1 哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。

集中式版本控制工具缺点:

  • 服务器单点故障
  • 容错性差
    Git是分布式版本控制系统(Distributed Version Control System,简称 DVCS) ,分为两种类型的仓库:
  • 本地仓库:是在开发人员自己电脑上的Git仓库
  • 远程仓库:是在远程服务器上的Git仓库
    svn.vs.git

    1.3 Git工作流程

    工作流程如下:
    1.从远程仓库中克隆代码到本地仓库
    2.从本地仓库中checkout代码然后进行代码修改
    3.在提交前先将代码提交到暂存区
    4.提交到本地仓库。本地仓库中保存修改的各个历史版本
    5.修改完成后,需要和团队成员共享代码时,将代码push到远程仓库
    git-workflow

    1.4 Git下载与安装

    下载地址: https://git-scm.com/download
    git-dowmload
    下载完成后可以得到如下安装文件:
    git.exe
    这里默认下载的是64位的软件
    双击下载的安装文件来安装Git。
    一直下一步直到安装完成即可
    安装完成后在电脑桌面(也可以是其他目录)点击右键,如果能够看到如下两个菜单则说明Git安装成功。
    git-bash
    Git GUI:Git提供的图形界面工具
    Git Bash:Git提供的命令行工具

    二、Git代码托管服务

    2.1 常用的Git代码托管服务

    前面我们已经知道了Git中存在两种类型的仓库,即本地仓库和远程仓库。那么我们如何搭建Git远程仓库呢?我们可以借助互联网上提供的一些代码托管服务来实现,其中比较常用的有GitHub、码云、GitLab等。
  • gitHub( 地址:https://github.com/ )是一个面向开源及私有软件项目的托管平台,因为只支持Git 作为唯一的版本库格式进行托管,故名gitHub
  • 码云(地址: https://gitee.com/ )是国内的一个代码托管平台,由于服务器在国内,所以相比于GitHub,码云速度会更快
  • GitLab (地址: https://about.gitlab.com/ )是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的web服务

本次使用码云作为演示,码云在国内用起来网速比GitHub快

2.2 在码云注册账号

要想使用码云的相关服务,需要注册账号(地址: https://gitee.com/signup
gitee-register

2.3 登录码云并创建Git远程仓库

注册完成后就可以使用刚刚注册的邮箱进行登录(地址: https://gitee.com/login
gitee-login
登录成功后就可以创建Git远程仓库
git-init
创建完成后可以查看仓库信息
git-init
每个Git远程仓库都会对应一个网络地址,可以点击克隆/下载按钮弹出窗口并点击复制按钮获得这个网络地址
git-test

2.4 邀请其他用户成为仓库成员

前面已经在码云上创建了自己的远程仓库,目前仓库成员只有自己一个人(身份为管理员)。在企业实际开发中,一个项目往往是由多个人共同开发完成的,为了使多个参与者都有权限操作远程仓库,就需要邀请其他项目参与者成为当前仓库的成员。
gitee-members

三、Git常用命令

先学习如下一些命令和概念:

  • 环境配置
  • 获取Git仓库
  • 工作目录、暂存区以及版本库概念
  • Git工作目录下文件的两种状态
  • 本地仓库操作
  • 远程仓库的使用
  • 分支
  • 标签

    3.1 环境配置

    当安装Git后首先要做的事情是设置用户名称和email地址。这是非常重要的,因为每次Git提交都会使用该用户信息
    设置用户信息
    git config --global user.name “your name”
    git config --global user.email “your name@gmail.com”
    查看配置信息
    git config --list
    git config user.name
    通过上面的命令设置的信息会保存在~/.gitconfig文件中

3.2 获取Git仓库

要使用Git对我们的代码进行版本控制,首先需要获得Git仓库
获取Git仓库通常有两种方式:

  • 在本地初始化一个Git仓库
  • 从远程仓库克隆

    3.2.1 在本地初始化一个Git仓库

    执行步骤如下:
  1. 在电脑的任意位置创建一个空目录(例如testGit)作为我们的本地Git仓库
  2. 进入这个目录中,点击右键打开Git bash窗口
  3. 执行命令git init
  4. 如果在当前目录中看到.git文件夹(此文件夹为隐藏文件夹)则说明Git仓库创建成功
    git-folder

    3.2.2 从远程仓库克隆

    可以通过Git提供的命令从远程仓库进行克隆,将远程仓库克隆到本地
    命令形式为:git clone 远程Git仓库地址
    git-clone

执行如下命令以创建一个本地仓库的克隆版本:
git clone /path/to/repository
如果是远端服务器上的仓库,你的命令会是这个样子:
git clone username@host:/path/to/repository

3.3 工作目录、暂存区以及版本库概念

为了更好的学习Git,我们需要了解Git相关的一些概念,这些概念在后面的学习中会经常提到

  • 版本库:前面看到的.git隐藏文件夹就是版本库,版本库中存储了很多配置信息、日志信息和文件版本信息等

  • 工作目录(工作区):包含.git文件夹的目录就是工作目录,主要用于存放开发的代码

  • 暂存区:.git文件夹中有很多文件,其中有一个index文件就是暂存区,也可以叫做stage。暂存区是一个临时保存修改文件的地方

  • HEAD:指向你最近一次提交后的结果
    参考外图
    下面这个图展示了工作区、版本库中的暂存区和版本库之间的关系
    参考外图

  • 图中左侧为工作区,右侧为版本库。在版本库中标记为 “index” 的区域是暂存区(stage/index),标记为 “master” 的是 master 分支所代表的目录树。

  • 图中我们可以看出此时 “HEAD” 实际是指向 master 分支的一个”游标”。所以图示的命令中出现 HEAD 的地方可以用 master 来替换。

  • 图中的 objects 标识的区域为 Git 的对象库,实际位于 “.git/objects” 目录下,里面包含了创建的各种对象及内容。

  • 当对工作区修改(或新增)的文件执行 git add 命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中。

  • 当执行提交操作(git commit)时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树。

  • 当执行 git reset HEAD 命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。

  • 当执行 git rm --cached <file> 命令时,会直接从暂存区删除文件,工作区则不做出改变。

  • 当执行 git checkout . 或者 git checkout-- <file>命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区的改动。

  • 当执行 git checkout HEAD . 或者 git checkout HEAD <file> 命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。

    3.4 Git工作目录下文件的五种状态

    Git工作目录下的文件存在五种状态:

  • untracked 未跟踪(未被纳入版本控制)

  • tracked 已跟踪(被纳入版本控制)

  • unmodified 未修改状态

  • modified 已修改状态

  • staged 已暂存状态
    这些文件的状态会随着我们执行Git的命令发生变化

    3.5 本地仓库操作

  • git status 查看文件状态,也可以使用git status –s 使输出信息更加简洁

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    PS D:\test> git status
    On branch master
    Your branch is up to date with 'origin/master'.

    Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git checkout -- <file>..." to discard changes in working directory)

    modified: README.md

    no changes added to commit (use "git add" and/or "git commit -a")
    PS D:\test> git status -s
    M README.md
    PS D:\test>
  • git add 将未跟踪的文件加入暂存区
    将新创建的文件加入暂存区后查看文件状态

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    PS D:\test> git add .\README.md
    PS D:\test> git status
    On branch master
    Your branch is up to date with 'origin/master'.

    Changes to be committed:
    (use "git reset HEAD <file>..." to unstage)

    modified: README.md

    PS D:\test>
  • git reset 将暂存区的文件取消暂存
    将文件取消暂存后查看文件状态

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    PS D:\test> git reset .\README.md   
    Unstaged changes after reset:
    M README.md
    PS D:\test> git status
    On branch master
    Your branch is up to date with 'origin/master'.

    Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git checkout -- <file>..." to discard changes in working directory)

    modified: README.md

    no changes added to commit (use "git add" and/or "git commit -a")
    PS D:\test>
  • git commit 将暂存区的文件修改提交到本地仓库

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    PS D:\test> git add .\README.md
    PS D:\test> git commit -m "update Readme" .\README.md
    [master 7ac056e] update Readme
    1 file changed, 4 insertions(+)
    PS D:\test> git status
    On branch master
    Your branch is ahead of 'origin/master' by 1 commit.
    (use "git push" to publish your local commits)

    nothing to commit, working tree clean
    PS D:\test>
  • git rm 删除文件
    删除文件后查看文件状态

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    PS D:\test> git rm .\README.md   
    rm 'README.md'
    PS D:\test> git status
    On branch master
    Your branch is ahead of 'origin/master' by 1 commit.
    (use "git push" to publish your local commits)

    Changes to be committed:
    (use "git reset HEAD <file>..." to unstage)

    deleted: README.md

    PS D:\test>

    上面删除的只是工作区的文件,需要提交到本地仓库

  • 将文件添加至忽略列表
    一般我们总会有些文件无需纳入Git 的管理,也不希望它们总出现在未跟踪文件列表。 通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。 在这种情况下,我们可以在工作目录中创建一个名为 .gitignore 的文件(文件名称固定),列出要忽略的文件模式。下面是一个示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # no .a files
    *.a
    # but do track lib.a, even though you're ignoring .a files above
    !lib.a
    # only ignore the TODO file in the current directory, not subdir/TODO
    /TODO
    # ignore all files in the build/ directory
    build/
    # ignore doc/notes.txt, but not doc/server/arch.txt
    doc/*.txt
    # ignore all .pdf files in the doc/ directory
    doc/**/*.pdf

    3.6 远程仓库操作

    前面执行的命令操作都是针对的本地仓库,本章节我们会学习关于远程仓库的一些操作,具体包括:

  • 查看远程仓库
    如果想查看已经配置的远程仓库服务器,可以运行 git remote 命令。 它会列出指定的每一个远程服务器的简写。 如果已经克隆了远程仓库,那么至少应该能看到 origin ,这是 Git 克隆的仓库服务器的默认名字

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    PS D:\test> git remote
    origin
    PS D:\test> git remote -v
    origin https://gitee.com/fusionshen/test.git (fetch)
    origin https://gitee.com/fusionshen/test.git (push)
    PS D:\test> git remote show origin
    * remote origin
    Fetch URL: https://gitee.com/fusionshen/test.git
    Push URL: https://gitee.com/fusionshen/test.git
    HEAD branch: master
    Remote branch:
    master tracked
    Local branch configured for 'git pull':
    master merges with remote master
    Local ref configured for 'git push':
    master pushes to master (up to date)
    PS D:\test>
  • 添加远程仓库
    运行 git remote add < shortname> < url> 添加一个新的远程 Git 仓库,同时指定一个可以引用的简写

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    PS D:\minhang\testGit> git status
    On branch master

    No commits yet

    nothing to commit (create/copy files and use "git add" to track)
    PS D:\minhang\testGit> git remote add origin https://gitee.com/fusionshen/test.git
    PS D:\minhang\testGit> git remote -v
    origin https://gitee.com/fusionshen/test.git (fetch)
    origin https://gitee.com/fusionshen/test.git (push)
    PS D:\minhang\testGit>
  • 从远程仓库克隆
    如果你想获得一份已经存在了的 Git 仓库的拷贝,这时就要用到 git clone 命令。 Git 克隆的是该 Git 仓库服务器上的几乎所有数据(包括日志信息、历史记录等),而不仅仅是复制工作所需要的文件。 当你执行 git clone 命令的时候,默认配置下远程 Git 仓库中的每一个文件的每一个版本都将被拉取下来。
    克隆仓库的命令格式是 git clone [url]

  • 移除无效的远程仓库
    如果因为一些原因想要移除一个远程仓库 ,可以使用 git remote rm

    1
    2
    3
    4
    5
    PS D:\minhang\testGit> git remote 
    origin
    PS D:\minhang\testGit> git remote rm origin
    PS D:\minhang\testGit> git remote
    PS D:\minhang\testGit>

    注意:此命令只是从本地移除远程仓库的记录,并不会真正影响到远程仓库

  • 从远程仓库中抓取与拉取
    git fetch 是从远程仓库获取最新版本到本地仓库,不会自动merge
    git pull 是从远程仓库获取最新版本并merge到本地仓库,即git fetch + git merge
    fetch&merge

    注意:如果当前本地仓库不是从远程仓库克隆,而是本地创建的仓库,并且仓库中存在文件,此时再从远程仓库拉取文件的时候会报错(fatal: refusing to merge unrelated histories ),解决此问题可以在git pull命令后加入参数–allow-unrelated-histories
    当执行git中的“git pull origin master –allow-unrelated-histories”命令时,会出现“ couldn’t find remote ref –allow-unrelated-histories”的错误,
    输入如下命令即可解决:
    git pull –rebase origin master

  • 将本地分支与远程分支关联:
    git branch --set-upstream-to origin/master master

  • 推送到远程仓库
    当你想分享你的代码时,可以将其推送到远程仓库。 命令形式:git push [remote-name] [branch-name]
    git-push

    3.7 Git分支

    几乎所有的版本控制系统都以某种形式支持分支。 使用分支意味着你可以把你的工作从开发主线上分离开来,以免影响开发主线。Git 的master分支并不是一个特殊分支。 它跟其它分支没有区别。 有人把 Git 的分支模型称为必杀技特性,而正是因为它,将 Git 从版本控制系统家族里区分出来,也就是所谓“杀手”级应用。之所以几乎每一个仓库都有 master 分支,是因为git init 命令默认创建它,并且大多数人都懒得去改动它。
    在本章节我们会学习到关于分支的相关命令,具体如下:

  • 查看分支

    • 列出所有本地分支
      git branch
    • 列出所有远程分支
      git branch -r
    • 列出所有本地分支和远程分支
      git branch -a
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      PS D:\minhang\testGit> git banch -r
      git: 'banch' is not a git command. See 'git --help'.

      The most similar command is
      branch
      PS D:\minhang\testGit> git branch -r
      origin/master
      PS D:\minhang\testGit> git branch -a
      dev
      master
      * stage
      remotes/origin/master
      PS D:\minhang\testGit>
  • 创建分支

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    PS D:\minhang\testGit> git branch
    * master
    PS D:\minhang\testGit> git branch dev
    PS D:\minhang\testGit> git branch
    dev
    * master
    PS D:\minhang\testGit> git checkout -b stage
    Switched to a new branch 'stage'
    PS D:\minhang\testGit> git branch
    dev
    master
    * stage
  • 切换分支

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    PS D:\minhang\testGit> git branch -a
    dev
    master
    * stage
    remotes/origin/master
    PS D:\minhang\testGit> git checkout master
    Switched to branch 'master'
    Your branch is up to date with 'origin/master'.
    PS D:\minhang\testGit> git branch
    dev
    * master
    stage
    PS D:\minhang\testGit>
  • 推送至远程仓库分支

    1
    2
    3
    4
    5
    6
    7
    8
    PS D:\minhang\testGit> git push origin dev
    Total 0 (delta 0), reused 0 (delta 0)
    remote: Powered by GITEE.COM [GNK-5.0]
    remote: Create a pull request for 'dev' on Gitee by visiting:
    remote: https://gitee.com/fusionshen/test/pull/new/fusionshen:dev...fusionshen:master
    To https://gitee.com/fusionshen/test.git
    * [new branch] dev -> dev
    PS D:\minhang\testGit>
  • 合并分支

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    PS D:\minhang\testGit> git status
    On branch dev
    (use "git add <file>..." to update what will be committed)
    (use "git checkout -- <file>..." to discard changes in working directory)

    modified: README.md
    no changes added to commit (use "git add" and/or "git commit -a")
    PS D:\minhang\testGit> git add .
    PS D:\minhang\testGit> git commit -m "测试分支合并"
    [dev acff4ab] 测试分支合并
    1 file changed, 2 insertions(+), 1 deletion(-)
    PS D:\minhang\testGit> git push origin dev
    Counting objects: 3, done.
    Delta compression using up to 4 threads.
    Compressing objects: 100% (3/3), done.
    Writing objects: 100% (3/3), 320 bytes | 320.00 KiB/s, done.
    Total 3 (delta 2), reused 0 (delta 0)
    remote: Powered by GITEE.COM [GNK-5.0]
    To https://gitee.com/fusionshen/test.git
    f5d3192..acff4ab dev -> dev
    PS D:\minhang\testGit> git checkout master
    Switched to branch 'master'
    Your branch is up to date with 'origin/master'.
    PS D:\minhang\testGit> git merge dev
    Updating f5d3192..acff4ab
    Fast-forward
    README.md | 3 ++-
    1 file changed, 2 insertions(+), 1 deletion(-)
    PS D:\minhang\testGit> git status
    On branch master
    Your branch is ahead of 'origin/master' by 1 commit.
    (use "git push" to publish your local commits)

    nothing to commit, working tree clean
    PS D:\minhang\testGit>

    有时候合并操作不会如此顺利。 如果你在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git 就没办法合并它们,同时会提示文件冲突。此时需要我们打开冲突的文件并修复冲突内容,最后执行git add命令来标识冲突已解决

  • 删除分支

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    PS D:\minhang\testGit> git branch
    * dev
    master
    stage
    PS D:\minhang\testGit> git checkout stage
    Switched to branch 'stage'
    PS D:\minhang\testGit> git branch -d stage
    error: Cannot delete branch 'stage' checked out at 'D:/minhang/testGit'
    PS D:\minhang\testGit> git checkout master
    Switched to branch 'master'
    Your branch is ahead of 'origin/master' by 1 commit.
    (use "git push" to publish your local commits)
    PS D:\minhang\testGit> git branch -d stage
    Deleted branch stage (was f5d3192).
    PS D:\minhang\testGit>

    如果要删除的分支中进行了一些开发动作,此时执行上面的删除命令并不会删除分支,如果坚持要删除此分支,可以将命令中的-d参数改为-D

    3.8 Git标签

    像其他版本控制系统(VCS)一样,Git 可以给历史中的某一个提交打上标签,以示重要。 比较有代表性的是人们会使用这个功能来标记发布结点(v1.0 、v1.2等)。标签指的是某个分支某个特定时间点的状态。通过标签,可以很方便的切换到标记时的状态。
    下面将学习:

  • 列出已有的标签

    1
    2
    3
    4
    # 列出所有tag
    $ git tag
    # 查看tag信息
    $ git show [tag]
  • 创建新标签

    1
    2
    # 新建一个tag
    $ git tag [tagName]
  • 将标签推送至远程仓库

    1
    2
    # 提交指定tag
    $ git push [remote] [tag]
  • 检出标签

    1
    2
    # 新建一个分支,指向某个tag
    $ git checkout -b [branch] [tag]
  • 删除标签

    1
    2
    3
    4
    # 删除本地tag
    $ git tag -d [tag]
    # 删除远程tag
    $ git push origin :refs/tags/[tag]

    四、在IDEA中使用Git

    4.1 在IDEA中配置Git

    安装好IntelliJ IDEA后,如果Git安装在默认路径下,那么idea会自动找到git的位置,如果更改了Git的安装位置则需要手动配置下Git的路径。
    选择File→Settings打开设置窗口,找到Version Control下的git选项:
    idea-config-git
    选择git的安装目录后可以点击“Test”按钮测试是否正确配置

    4.2 在IDEA中使用Git

    本章节我们会学习在IDEA中使用Git进行版本管理,具体包括:

  • 在IDEA中创建工程并将工程添加至Git
    idea-clone
    将项目添加至Git管理后,可以从IDEA的工具栏上看到Git操作的按钮
    当然更多的情况是用IDEA打开远程仓库
    idea-cloneimage-20210315211623301

  • 将文件添加到暂存区
    git-add-dot

  • 提交文件
    git-commit

  • 将代码推送到远程仓库
    git-pushimage-20210315213016819git-push-3

  • 从远程仓库克隆工程到本地

  • 从远程拉取代码
    git-pull-1git-pull-2

  • 版本对比
    git-diffgit-diff-2git-diff-3

  • 创建分支
    git-b-branch

  • 切换分支
    git-checkout

  • 分支合并
    git-merge
    git-merge-2

    五、命令行更好用

    5.1 查看提交历史

  • git log -查看历史提交记录
    在使用 Git 提交了若干更新之后,又或者克隆了某个项目,想回顾下提交历史,我们可以使用 git log 命令查看。

    • 我们可以用 –oneline 选项来查看历史记录的简洁的版本。git log --oneline
      1
      2
      3
      4
      5
      6
      7
      8
      9
      PS D:\minhang\testGit> git log --oneline
      1f98086 (HEAD -> master, origin/master) fix conflicts
      69302e7 idea
      2d5d070 (origin/dev, dev) 测试idea合并分支
      b394ef7 测试IDEA提交服务器
      acff4ab 测试分支合并
      f5d3192 提交
      7399e20 Initial commit
      PS D:\minhang\testGit>
    • 我们还可以用 –graph 选项,查看历史中什么时候出现了分支、合并,开启了拓扑图选项。git log --graph
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      PS D:\minhang\testGit> git log --graph --oneline
      * 1f98086 (HEAD -> master, origin/master) fix conflicts
      |\
      | * 2d5d070 (origin/dev, dev) 测试idea合并分支
      * | 69302e7 idea
      * | b394ef7 测试IDEA提交服务器
      |/
      * acff4ab 测试分支合并
      * f5d3192 提交
      * 7399e20 Initial commit
      PS D:\minhang\testGit>
    • 我们也可以用 –reverse 参数来逆向显示所有日志。git log --reverse --online
    • 如果只想查找指定用户的提交日志可以使用命令:git log –author , 例如,比方说我们要找 Git 源码中 Linus 提交的部分。
      git log --author=Linus --oneline -5
  • 如果你要指定日期,可以执行几个选项:–since 和 –before,但是你也可以用 –until 和 –after。例如,如果我要看 Git 项目中三周前且在四月十八日之后的所有提交,我可以执行这个(我还用了 –no-merges 选项以隐藏合并提交) 。
    git log --oneline --before={3.weeks.ago} --after={2010-04-18} --no-merges

  • git blame -如果要查看指定文件的修改记录

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    PS D:\minhang\testGit> git blame .\README.md   
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 1) # test
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 2)
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 3) #### 介绍
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 4) 测试
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 5)
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 6) #### 软件架构
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 7) 软件架构说明
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 8)
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 9)
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 10) #### 安装教程
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 11)
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 12) 1. xxxx
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 13) 2. xxxx
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 14) 3. xxxx
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 15)
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 16) #### 使用说明
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 17)
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 18) 1. xxxx
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 19) 2. xxxx
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 20) 3. xxxx
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 21)
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 22) #### 参与贡献
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 23)
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 24) 1. Fork 本仓库
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 25) 2. 新建 Feat_xxx 分支
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 26) 3. 提交代码
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 27) 4. 新建 Pull Request
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 28)
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 29)
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 30) #### 特技
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 31)
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 32) 1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 33) 2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 34) 3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 35) 4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 36) 5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
    ^7399e20 (fusionshen 2021-03-15 16:55:24 +0800 37) 6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
    f5d3192c (fusionshen 2021-03-15 17:56:33 +0800 38)
    f5d3192c (fusionshen 2021-03-15 17:56:33 +0800 39) #### 测试2
    acff4ab3 (fusionshen 2021-03-15 20:49:17 +0800 40) 就是个测试
    b394ef7c (fusionshen 2021-03-15 21:29:36 +0800 41) 测试分支合并
    b394ef7c (fusionshen 2021-03-15 21:29:36 +0800 42) 测试idea将文件添加至暂存区
    PS D:\minhang\testGit>

    5.2 版本回退

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    PS D:\minhang\testGit> git log --graph --oneline
    * 1f98086 (HEAD -> master, origin/master) fix conflicts
    |\
    | * 2d5d070 (origin/dev, dev) 测试idea合并分支
    * | 69302e7 idea
    * | b394ef7 测试IDEA提交服务器
    |/
    * acff4ab 测试分支合并
    * f5d3192 提交
    * 7399e20 Initial commit
    PS D:\minhang\testGit>

    首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交1f98086...,上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100

  • HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id
  • 穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。
  • 要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。

    5.3 惯用分支,大胆commit,谨慎push(引用廖雪峰git教程)

    软件开发中,经常要开发耗时很长的模块或者功能,通常有两种做法:
  • 功能分解成小任务小模块,本地开发完成并验证通过后依次push到远程分支。以便于发现bug后本地回滚

  • 本地开发完全并全部验证通过后统一push到远程分支。
    有同时满足以上要求的吗?有!

  • 本地新增一个分支,依次开发,小任务小模块commit。

  • 全部开发完成并本地验证通过后merge到自己主分支,优先pull。

  • git reset –soft

  • git add . & git commit -m “xxxxx” & git push origin master。

  • 远程分支验证通过后,删除本地新增分支或者不删除,留作纪念。
    还有没有更简单的方法?有!

    1
    2
    $ git checkout master
    $ git merge --no-ff feature

    ​ A—B—C feature(master)

    ​ / \

    D—E—F———–G master (–no-ff)
    --no-ff 会让 Git 生成一个新的提交对象。为什么要这样?通常我们把 master 作为主分支,上面存放的都是比较稳定的代码,提交频率也很低,而 feature 是用来开发特性的,上面会存在许多零碎的提交,快进式合并会把 feature 的提交历史混入到 master 中,搅乱 master 的提交历史。所以如果你根本不在意提交历史,也不爱管 master 干不干净,那么 --no-ff 其实没什么用。不过,如果某一次 master 出现了问题,你需要回退到上个版本的时候,比如上例,你就会发现退一个版本到了 B,而不是想要的 F,因为 feature 的历史合并进了 master 里。
    软件开发中,bug就像家常便饭一样。有了bug就需要修复,在Git中,由于分支是如此的强大,所以,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。
    当你接到一个修复一个代号101的bug的任务时,很自然地,你想创建一个分支issue-101来修复它,但是,等等,当前正在dev上进行的工作还没有提交。
    并不是你不想提交,而是工作只进行到一半,还没法提交,预计完成还需1天时间。但是,必须在两个小时内修复该bug,怎么办?
    幸好,Git还提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:

    1
    2
    $ git stash
    Saved working directory and index state WIP on dev: f52c633 add merge

    现在,用git status查看工作区,就是干净的(除非有没有被Git管理的文件),因此可以放心地创建分支来修复bug。
    首先确定要在哪个分支上修复bug,假定需要在master分支上修复,就从master创建临时分支:

    1
    2
    3
    4
    5
    6
    7
    $ git checkout master
    Switched to branch 'master'
    Your branch is ahead of 'origin/master' by 6 commits.
    (use "git push" to publish your local commits)

    $ git checkout -b issue-101
    Switched to a new branch 'issue-101'

    现在修复bug,需要把“Git is free software …”改为“Git is a free software …”,然后提交:

    1
    2
    3
    4
    $ git add readme.txt 
    $ git commit -m "fix bug 101"
    [issue-101 4c805e2] fix bug 101
    1 file changed, 1 insertion(+), 1 deletion(-)

    修复完成后,切换到master分支,并完成合并,最后删除issue-101分支:

    1
    2
    3
    4
    5
    6
    7
    8
    $ git switch master
    Switched to branch 'master'
    Your branch is ahead of 'origin/master' by 6 commits.
    (use "git push" to publish your local commits)
    $ git merge --no-ff -m "merged bug fix 101" issue-101
    Merge made by the 'recursive' strategy.
    readme.txt | 2 +-
    1 file changed, 1 insertion(+), 1 deletion(-)

    现在,是时候接着回到dev分支干活了!

    1
    2
    3
    4
    5
    6
    $ git switch dev
    Switched to branch 'dev'

    $ git status
    On branch dev
    nothing to commit, working tree clean

    工作区是干净的,刚才的工作现场存到哪去了?用git stash list命令看看:

    1
    2
    $ git stash list
    stash@{0}: WIP on dev: f52c633 add merge

    工作现场还在,Git把stash内容存在某个地方了,但是需要恢复一下,有两个办法:
    一是用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;
    另一种方式是用git stash pop,恢复的同时把stash内容也删了:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    $ git stash pop
    On branch dev
    Changes to be committed:
    (use "git reset HEAD <file>..." to unstage)

    new file: hello.py

    Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git checkout -- <file>..." to discard changes in working directory)

    modified: readme.txt

    Dropped refs/stash@{0} (5d677e2ee266f39ea296182fb2354265b91b3b2a)

    再用git stash list查看,就看不到任何stash内容了:

    1
    $ git stash list

    你可以多次stash,恢复的时候,先用git stash list查看,然后恢复指定的stash,用命令:

    1
    $ git stash apply stash@{0}

    在master分支上修复了bug后,我们要想一想,dev分支是早期从master分支分出来的,所以,这个bug其实在当前dev分支上也存在。
    那怎么在dev分支上修复同样的bug?重复操作一次,提交不就行了?
    有没有更简单的方法?
    有!
    同样的bug,要在dev上修复,我们只需要把4c805e2 fix bug 101这个提交所做的修改“复制”到dev分支。

    注意:我们只想复制4c805e2 fix bug 101这个提交所做的修改,并不是把整个master分支merge过来。
    为了方便操作,Git专门提供了一个cherry-pick命令,让我们能复制一个特定的提交到当前分支:

    1
    2
    3
    4
    5
    6
    $ git branch
    * dev
    master
    $ git cherry-pick 4c805e2
    [master 1d4b803] fix bug 101
    1 file changed, 1 insertion(+), 1 deletion(-)

    Git自动给dev分支做了一次提交,注意这次提交的commit是1d4b803,它并不同于master的4c805e2,因为这两个commit只是改动相同,但确实是两个不同的commit。用git cherry-pick,我们就不需要在dev分支上手动再把修bug的过程重复一遍。
    既然可以在master分支上修复bug后,在dev分支上可以“重放”这个修复过程,那么直接在dev分支上修复bug,然后在master分支上“重放”行不行?当然可以,不过你仍然需要git stash命令保存现场,才能从dev分支切换到master分支。

    六、贴士

  • 全命令https://git-scm.com/docs

  • Google现场教学视频https://v.qq.com/x/page/o0772kqh5iv.html?n_version=2021

  • Git 不仅仅是个版本控制系统,它也是个内容管理系统(CMS),工作管理系统等,但是不适合管理二进制文件。

  • Git push -f 慎用
    git-push-f

  • 优先pull,冲突只能在本地分支解决。

  • git rebase或者git pull –rebase可以让提交时间线整齐划一

  • git flow
    A successful Git branching model » nvie.com

  • RP和代码审查

  • git服务器搭建

  • 《ProGit》进阶

WSL 2下docker安装

一、安装过程

WSL 2环境配置请参考
因为wsl2已经完整使用了linux内核了,此种方式和先前在linux虚拟机安装docker类似,步骤如下:

1
2
3
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh
$ sudo service docker start

执行脚本安装过程中,脚本提示“建议使用Docker Desktop for windows”,20s内按Ctrl+C会退出安装,所以需要等待20s,另外此种方式需要访问外网。

检查docker安装正常

1
2
3
4
5
6
# 检查dockerd进程启动
service docker status
ps aux|grep docker
# 检查拉取镜像等正常
docker pull busybox
docker images

不同于完全linux虚拟机方式,WLS2下通过apt install docker-ce命令安装的docker无法启动,因为WSL2方式的ubuntu里面没有systemd。上述官方get-docker.sh安装的docker,dockerd进程是用ubuntu传统的init方式而非systemd启动的。

二、镜像加速

之前还有 Docker 官方加速器 https://registry.docker-cn.com ,现在好像已经不能使用了,我们可以多添加几个国内的镜像,如果有不能使用的,会切换到可以使用个的镜像来拉取。

Ubuntu14.04、Debian7Wheezy

对于使用 upstart 的系统而言,编辑 /etc/default/docker 文件,在其中的 DOCKER_OPTS 中配置加速器地址:

1
DOCKER_OPTS="--registry-mirror=https://registry.docker-cn.com"

重新启动服务:

1
$ sudo service docker restart

Ubuntu16.04+、Debian8+、CentOS7

对于使用 systemd 的系统,请在 /etc/docker/daemon.json 中写入如下内容(如果文件不存在请新建该文件):

1
{"registry-mirrors":["https://reg-mirror.qiniu.com/"]}

之后重新启动服务:

1
$ sudo systemctl restart docker

Windows10专业版WSL环境搭建

一、官网解读

二、概述

2.1 什么是WSL

适用于 Linux 的 Windows 子系统可让开发人员直接在 Windows 上按原样运行 GNU/Linux 环境(包括大多数命令行工具、实用工具和应用程序),且不会产生传统虚拟机或双启动设置开销。

  • 在 Microsoft Store 中选择你偏好的 GNU/Linux 分发版。
  • 运行常用的命令行软件工具(例如 grepsedawk)或其他 ELF-64 二进制文件。
  • 运行 Bash shell 脚本和 GNU/Linux 命令行应用程序,包括:
    • 工具:vim、emacs、tmux
    • 语言:NodeJS、Javascript、Python、Ruby、C/ C++、C# 与 F#、Rust、Go 等。
    • 服务:SSHD、MySQL、Apache、lighttpd、MongoDBPostgreSQL
  • 使用自己的 GNU/Linux 分发包管理器安装其他软件。
  • 使用类似于 Unix 的命令行 shell 调用 Windows 应用程序。
  • 在 Windows 上调用 GNU/Linux 应用程序。

2.2 WSL 1和WSL 2

WSL 2 使用最新、最强大的虚拟化技术在轻量级实用工具虚拟机 (VM) 中运行 Linux 内核。 但是,WSL 2 不是传统的 VM 体验。

逃离Hyper-V

2.2.1 比较功能

功能 WSL 1 WSL 2
Windows 和 Linux 之间的集成
启动时间短
与传统虚拟机相比,占用的资源量少
可以与当前版本的 VMware 和 VirtualBox 一起运行
托管 VM
完整的 Linux 内核
完全的系统调用兼容性
跨 OS 文件系统的性能

从上述比较表中可以看出,除了跨操作系统文件系统的性能外,WSL 2 体系结构在多个方面都比 WSL 1 更具优势。

2.2.2 跨 OS 文件系统的性能

建议不要跨操作系统使用文件,除非有这么做的特定原因。 若想获得最快的性能速度,请将文件存储在 WSL 文件系统中,前提是在 Linux 命令行(Ubuntu、OpenSUSE 等)中工作。 如果使用 Windows 命令行(PowerShell、命令提示符)工作,请将文件存储在 Windows 文件系统中。

例如,在存储 WSL 项目文件时:

  • 使用 Linux 文件系统根目录:\\wsl$\Ubuntu-18.04\home\<user name>\Project
  • 而不使用 Windows 文件系统根目录:C:\Users\<user name>\Project

所有当前正在运行的分发 (wsl -l) 均可通过网络连接进行访问。 为此,请运行命令 [WIN+R](键盘快捷方式)或在文件资源管理器地址栏中键入 \\wsl$,以查找相应的分发名称并访问其根文件系统。

还可以在 WSL 的 Linux 终端中使用 Windows 命令。 尝试打开 Linux 分发版(即 Ubuntu),通过输入以下命令确保你位于 Linux 主目录中:cd ~。 然后通过输入 powershell.exe /c start .(不要忘记尾部的句点),在文件资源管理器中打开 Linux 文件系统。

如果遇到错误“-bash: powershell.exe: 找不到命令”,请参阅 WSL 故障排除页面予以解决。

WSL 2 仅适用于 Windows 10 版本 1903、内部版本 18362 或更高版本。 通过按 Windows 徽标键 + R,检查你的 Windows 版本,然后键入 winver,选择“确定”。 (或者在 Windows 命令提示符下输入 ver 命令)。 你可能需要更新到最新的 Windows 版本。 低于 18362 的版本根本不支持 WSL。

WSL 2 适用于 VMware 15.5.5+VirtualBox 6+。 通过我们的 WSL 2 常见问题解答了解详细信息。

2.2.3 WSL 2 中的新增功能

WSL 2 是对基础体系结构的一次重大改造,它使用虚拟化技术和 Linux 内核来实现其新功能。 此更新的主要目标是提高文件系统性能和添加完全的系统调用兼容性。

2.2.3.1 WSL 2 体系结构

传统的 VM 体验可能启动速度慢,是独立的,消耗大量资源,需要你花费时间进行管理。 WSL 2 没有这些属性。

WSL 2 有 WSL 1 的优点,包括 Windows 和 Linux 之间的无缝集成,启动时间短,资源占用量少,并且无需 VM 配置或管理。 虽然 WSL 2 确实使用 VM,但 VM 是在幕后管理和运行的,因此你将具有与 WSL 1 相同的用户体验。

2.2.3.2 完整的 Linux 内核

WSL 2 中的 Linux 内核是 Microsoft 根据最新的稳定版分支(基于 kernel.org 上提供的源代码)构建的。此内核已专门针对 WSL 2 进行了调整,针对大小和性能进行了优化,以便在 Windows 上提供良好的 Linux 体验。 内核将由 Windows 更新提供服务,这意味着你将获得最新的安全修补程序和内核改进功能,而无需自行管理它。

WSL 2 Linux 内核是开源的。 如果你想要了解详细信息,请查看由构建该内核的团队撰写的博客文章随 Windows 一起提供 Linux 内核

2.2.3.3 提升了文件 IO 性能

如果使用 WSL 2,文件密集型操作(如 git 克隆、npm 安装、apt 更新、apt 升级等)的速度都明显更快。

实际的速度提升将取决于你运行的应用以及它与文件系统的交互方式。 在对压缩的 tarball 进行解包时,WSL 2 的初始版本的运行速度比 WSL 1 快达 20 倍,在各种项目上使用 git 克隆、npm 安装和 cmake 时,大约快 2-5 倍。

2.2.3.4 完全的系统调用兼容性

Linux 二进制文件使用系统调用来执行访问文件、请求内存、创建进程等功能。 虽然 WSL 1 使用的是由 WSL 团队构建的转换层,但 WSL 2 包括了自己的 Linux 内核,具有完全的系统调用兼容性。 优点包括:

  • 可以在 WSL 内部运行的一组全新应用,例如 Docker 等。
  • 对 Linux 内核的任何更新都立即可供使用。 (无需等待 WSL 团队实现更新并添加更改)。

2.2.4 例外情况(使用 WSL 1 而不是 WSL 2)

我们建议使用 WSL 2,因为它提供更快的性能和100% 的系统调用兼容性。 但是,在某些特定情况下,你可能会更倾向于使用 WSL 1。 在以下情况下,请考虑使用 WSL 1:

  • 你的项目文件必须存储在 Windows 文件系统中。 WSL 1 可以更快地访问从 Windows 装载的文件。
    • 如果你将使用 WSL Linux 分发版来访问 Windows 文件系统上的项目文件,并且这些文件无法存储在 Linux 文件系统上,那么,通过使用 WSL 1,你将跨 OS 文件系统实现更快的性能。
  • 一个项目要求对相同的文件使用 Windows 和 Linux 工具进行交叉编译。
    • 在 WSL 1 中,跨 Windows 和 Linux 操作系统的文件性能比 WSL 2 中更快,因此如果要使用 Windows 应用程序来访问 Linux 文件,则目前通过 WSL 1 可实现更快的性能。
  • 你的项目需要访问串行端口或 USB 设备。
  • 有严格的内存要求
    • WSL 2 的内存使用量会随使用而缩放。 当进程释放内存时,这会自动返回到 Windows。 但从现在开始,在关闭 WSL 实例前,WSL 2 还不会将内存中缓存的页面释放回 Windows。 如果你有长时间运行的 WSL 会话或访问非常大量的文件,此缓存可能会耗尽 Windows 内存。 我们通过 WSL Github 存储库问题 4166 跟踪工作以改善此体验

请考虑尝试 VS Code 远程 WSL 扩展,以便使你不仅能够使用 Linux 命令行工具将项目文件存储在 Linux 文件系统上,而且还可以使用 Windows 上的 VS Code 在 Internet 浏览器中创作、编辑、调试或运行项目,而不会造成任何与跨 Linux 和 Windows 文件系统工作相关联的性能下降。 了解详细信息

2.2.5 访问网络应用程序

2.2.5.1 从 Windows (localhost) 访问 Linux 网络应用

如果要在 Linux 分发版中构建网络应用(例如,在 NodeJS 或 SQL server 上运行的应用),可以使用 localhost 从 Windows 应用(如 Microsoft Edge 或 Chrome Internet 浏览器)访问它(就像往常一样)。

但是,如果运行的是较旧版本的 Windows(版本 18945 或更低版本),则需要获取 Linux 主机 VM 的 IP 地址(或更新到最新的 Windows 版本)。

若要查找为 Linux 分发版提供支持的虚拟机的 IP 地址,请执行以下操作:

  • 在 WSL 分发版(即 Ubuntu)中运行以下命令:ip addr
  • 查找并复制 eth0 接口的 inet 值下的地址。
  • 如果已安装 grep 工具,请通过使用以下命令筛选输出来更轻松地查找此地址:ip addr | grep eth0
  • 使用此 IP 地址连接到 Linux 服务器。

下图显示了一个示例,该示例使用 Microsoft Edge 浏览器连接到 Node.js 服务器。

通过 Edge 连接到 NodeJS 服务器

2.2.5.2 从 Linux(主机 IP)访问 Windows 网络应用

如果要从 Linux 分发版(即 Ubuntu)访问 Windows 上运行的网络应用(例如,在 NodeJS 或 SQL 服务器上运行的应用),则需要使用主机的 IP 地址。 虽然这不是一种常见方案,但你可以执行以下步骤来使其可行。

  1. 通过在 Linux 分发版中运行以下命令来获取主机的 IP 地址:cat /etc/resolv.conf
  2. 复制以下词语后面的 IP 地址:nameserver
  3. 使用复制的 IP 地址连接到任何 Windows 服务器。

下图显示了一个示例,该示例说明如何通过 curl 连接到在 Windows 中运行的 Node.js 服务器。

在 Windows 中通过 Curl 连接到 NodeJS 服务器

2.2.6 其他网络注意事项

2.2.6.1 通过远程 IP 地址进行连接

当使用远程 IP 地址连接到应用程序时,它们将被视为来自局域网 (LAN) 的连接。 这意味着你需要确保你的应用程序可以接受 LAN 连接。

例如,你可能需要将应用程序绑定到 0.0.0.0 而非 127.0.0.1。 以使用 Flask 的 Python 应用为例,可以通过以下命令执行此操作:app.run(host='0.0.0.0')。 进行这些更改时请注意安全性,因为这将允许来自你的 LAN 的连接。

2.2.6.2 从局域网 (LAN) 访问 WSL 2 分发版

当使用 WSL 1 分发版时,如果计算机设置为可供 LAN 访问,那么在 WSL 中运行的应用程序也可供在 LAN 中访问。

这不是 WSL 2 中的默认情况。 WSL 2 有一个带有其自己独一无二的 IP 地址的虚拟化以太网适配器。 目前,若要启用此工作流,你需要执行与常规虚拟机相同的步骤。 (我们正在寻找改善此体验的方法。)

下面是一个示例 PowerShell 命令,用于添加侦听主机上的端口 4000 的端口代理并将其连接到端口 4000,并使用 IP 地址 192.168.101.100 连接到 WSL 2 VM。

PowerShell复制

1
netsh interface portproxy add v4tov4 listenport=4000 listenaddress=0.0.0.0 connectport=4000 connectaddress=192.168.101.100

2.2.6.3 IPv6 访问

WSL2 分发版目前无法访问纯 IPv6 地址。 我们正在致力于添加此功能。

2.2.6.4 扩展 WSL 2 虚拟硬盘的大小

WSL 2 使用虚拟硬盘 (VHD) 来存储 Linux 文件。 在 WSL 2 中,VHD 在 Windows 硬盘驱动器上表示为 .vhdx 文件。

WSL 2 VHD 使用 ext4 文件系统。 此 VHD 会自动调整大小以满足你的存储需求,并且其最大大小为 256GB。 如果 Linux 文件所需的存储空间超过此大小,则可能需要将其展开。 如果你的分发版大小增长到大于 256GB,则会显示错误,指出磁盘空间不足。 可以通过扩展 VHD 大小来纠正此错误。

若要将最大 VHD 大小扩展到超过 256GB,请执行以下操作:

  1. 使用 wsl --shutdown 命令终止所有 WSL 实例

  2. 若要查找你的分发版安装包名称(“PackageFamilyName”):

    • 使用 PowerShell(其中,“distro”是分发版名称)输入以下命令:
    • Get-AppxPackage -Name "*<distro>*" | Select PackageFamilyName
    • 例如: Get-AppxPackage -Name "*Ubuntu*" | Select PackageFamilyName

    Get-AppxPackage 命令行屏幕快照

  3. 使用生成的 PackageFamilyName 查找 WSL 2 安装使用的 VHD 文件 fullpath,这将是你的 pathToVHD。 若要查找完整路径:

    • 在“开始”菜单中,输入“%LOCALAPPDATA%”并选择打开 %LOCALAPPDATA% 文件文件夹。
    • 接下来,打开“Packages”文件夹并搜索分发版的 PackageFamilyName。 打开该文件夹(即 CanonicalGroupLimited.Ubuntu20.04onWindows_79xxxxx)。
    • PackageFamilyName 文件夹中,打开“LocalState”文件夹并找到 <disk>.vhdx 文件。
    • 复制该文件的路径,它应如下所示:%LOCALAPPDATA%\Packages\<PackageFamilyName>\LocalState\<disk>.vhdx
    • 例如,Ubuntu 20.04 的 <pathToVHD> 应如下所示:%LOCALAPPDATA%\Packages\CanonicalGroupLimited.Ubuntu20.04onWindows_79xxxx\LocalState\ext4.vhdx
  4. 通过完成以下命令调整 WSL 2 VHD 的大小:

    • 以管理员权限打开 Windows 命令提示,然后输入:

      cmd复制

      1
      diskpart

      cmd复制

      1
      DISKPART> Select vdisk file="<pathToVHD>"

      cmd复制

      1
      DISKPART> detail vdisk
    • 检查 detail 命令的输出。 输出将包含虚拟大小的值。 这是当前的最大值。 将此值转换为兆字节。 如果如果“详细信息”输出显示“虚拟大小: 256 GB”,请将此转换为 256000 。

    • 你输入的新值必须大于此原始值。 例如,若要将上述虚拟大小翻倍,可输入值 512000。 确定要为新大小(以 MB 为单位)设置的数字后,在 Windows 命令提示符 diskpart 提示中输入以下命令:

      cmd复制

      1
      DISKPART> expand vdisk maximum=<sizeInMegaBytes>
    • Exit diskpart

      cmd复制

      1
      DISKPART> exit
  5. 启动 WSL 分发版(例如 Ubuntu)。

  6. 通过从 WSL 分发版命令行运行以下命令,让 WSL 知道它可扩展其文件系统的大小。

    Bash复制

    1
    2
    sudo mount -t devtmpfs none /dev
    mount | grep ext4
    • 可能会看到以下消息,它响应第一个 mount 命令:“/dev: /dev 上未装载任何内容。” 可以放心地忽略此消息。
    • 复制此项的名称,该名称类似于:/dev/sdX(X 表示任何其他字符)。 在下面的示例中,X 的值是 b:

    Bash复制

    1
    sudo resize2fs /dev/sdb <sizeInMegabytes>M
    • 在上述示例中,我们将 vhd 大小更改为了 512000,因此命令将为 sudo resize2fs /dev/sbd 512000M

三、快速入门

3.1 手动安装

3.1.1 步骤1-启用适用于Linux的Windows子系统

以管理员身份打开PowerShell并运行

1
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

3.1.2 步骤2-检查运行WSL 2的要求

若要更新到 WSL 2,需要运行 Windows 10。

  • 对于 x64 系统:版本 1903 或更高版本,采用 内部版本 18362 或更高版本。
  • 对于 ARM64 系统:版本 2004 或更高版本,采用 内部版本 19041 或更高版本。
  • 低于 18362 的版本不支持 WSL 2。 使用 Windows Update 助手更新 Windows 版本。

若要检查 Windows 版本及内部版本号,选择 Windows 徽标键 + R,然后键入“winver”,选择“确定”。 更新到“设置”菜单中的最新 Windows 版本

3.1.3 步骤3-启用虚拟机功能

安装 WSL 2 之前,必须启用“虚拟机平台”可选功能。 计算机需要虚拟化功能才能使用此功能。

以管理员身份打开 PowerShell 并运行:

PowerShell复制

1
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

重新启动 计算机,以完成 WSL 安装并更新到 WSL 2。

3.1.4 步骤4-下载Linux内核更新包

  1. 下载最新包:

    如果使用的是 ARM64 计算机,请下载 ARM64 包。 如果不确定自己计算机的类型,请打开命令提示符或 PowerShell,并输入:systeminfo | find "System Type"警告: 在非英语 Windows 版本中,你可能需要修改搜索文本,例如在德语中为 systeminfo | find "Systemtyp"

  2. 运行上一步中下载的更新包。 (双击以运行 - 系统将提示你提供提升的权限,选择“是”以批准此安装。)

安装完成后,请继续执行下一步 - 在安装新的 Linux 分发时,将 WSL 2 设置为默认版本。 (如果希望将新的 Linux 安装设置为 WSL 1,请跳过此步骤。)

3.1.5 步骤5-将WSL 2设置为默认版本

打开 PowerShell,然后在安装新的 Linux 发行版时运行以下命令,将 WSL 2 设置为默认版本:

PowerShell复制

1
wsl --set-default-version 2

查看

1
wsl -l -v

3.1.6 步骤6-安装所选的Linux分发

  1. 打开 Microsoft Store,并选择你偏好的 Linux 分发版。

    Microsoft Store 中的 Linux 分发版的视图

    单击以下链接会打开每个分发版的 Microsoft Store 页面:

  2. 在分发版的页面中,选择“获取”。

    Microsoft Store 中的 Linux 分发版

首次启动新安装的 Linux 分发版时,将打开一个控制台窗口,系统会要求你等待一分钟或两分钟,以便文件解压缩并存储到电脑上。 未来的所有启动时间应不到一秒。

然后,需要为新的 Linux 分发版创建用户帐户和密码

Windows 控制台中的 Ubuntu 解包

祝贺你!现已成功安装并设置了与 Windows 操作系统完全集成的 Linux 分发!

3.2 安装 Windows 终端(可选)

Windows 终端可启用多个选项卡(在多个 Linux 命令行、Windows 命令提示符、PowerShell 和 Azure CLI 等之间快速切换)、创建键绑定(用于打开或关闭选项卡、复制粘贴等的快捷方式键)、使用搜索功能,以及使用自定义主题(配色方案、字体样式和大小、背景图像/模糊/透明度)。 了解详细信息。

安装 Windows 终端

Windows 终端

3.3 将分发版版本设置为 WSL 1 或 WSL 2

可打开 PowerShell 命令行并输入以下命令(仅在 Windows 内部版本 18362 或更高版本中可用),检查分配给每个已安装的 Linux 分发版的 WSL 版本:wsl -l -v

PowerShell复制

1
wsl --list --verbose

若要将分发版设置为受某一 WSL 版本支持,请运行:

PowerShell复制

1
wsl --set-version <distribution name> <versionNumber>

请确保将 <distribution name> 替换为你的分发版的实际名称,并将 <versionNumber> 替换为数字“1”或“2”。 可以随时更改回 WSL 1,方法是运行与上面相同的命令,但将“2”替换为“1”。

备注

从 WSL 1 更新到 WSL 2 可能需要几分钟才能完成,具体取决于目标分发版的大小。 如果从 Windows 10 周年更新或创意者更新运行 WSL 1 的旧(历史)安装,可能会遇到更新错误。 按照这些说明卸载并删除任何旧分发

如果 wsl --set-default-version 结果为无效命令,请输入 wsl --help。 如果 --set-default-version 未列出,则表示你的 OS 不支持它,你需要更新到版本 1903(内部版本 18362)或更高版本。 如果你在使用 ARM64 版本 19041,那么当使用 PowerShell 时,此命令可能会失败;在这种情况下,你可使用命令提示符,而不是发出 wsl.exe 命令。

运行命令后如果看到此消息:WSL 2 requires an update to its kernel component. For information please visit https://aka.ms/wsl2kernel。 仍需要安装 MSI Linux 内核更新包。

此外,如果要使 WSL 2 成为你的默认体系结构,可以通过此命令执行该操作:

PowerShell复制

1
wsl --set-default-version 2

这会将安装的任何新分发版的版本设置为 WSL 2。

四、为Linux分发版创建用户账户和密码

启用 WSL 并从 Microsoft Store 中安装 Linux 分发版后,在打开新安装的 Linux 分发版时将会要求你完成的第一步是创建帐户,包括用户名密码

  • 用户名密码特定于安装的每个单独的 Linux 分发版,与 Windows 用户名无关。

  • 创建用户名密码后,该帐户将是分发版的默认用户,并将在启动时自动登录。

  • 此帐户将被视为 Linux 管理员,能够运行 sudo (Super User Do) 管理命令。

  • 在适用于 Linux 的 Windows 子系统上运行的每个 Linux 分发版都有其自身的 Linux 用户帐户和密码。 每当添加分发版、重新安装或重置时,都必须配置一个 Linux 用户帐户。

Windows 控制台中的 Ubuntu 解包

4.1 更新和升级包

大多数分发版随附了一个空的的包目录或最简单的包目录。 我们强烈建议定期更新包目录并使用分发版的首选包管理器升级已安装的包。 对于 Debian/Ubuntu,请使用 apt:
sudo apt update && sudo apt upgrade

Windows 不会自动更新或升级 Linux 分发版。 大多数 Linux 用户往往倾向于自行控制此任务。

4.2 重置 Linux 密码

若要更改密码,请打开 Linux 分发版(例如 Ubuntu)并输入以下命令:passwd

系统会要求你输入当前密码,然后要求输入新密码,之后再确认新密码。

4.3 忘记密码

如果忘记了 Linux 分发版的密码:

  1. 请打开 PowerShell,并使用以下命令进入默认 WSL 分发版的根目录:wsl -u root

如果需要在非默认分发版中更新忘记的密码,请使用命令:wsl -d Debian -u root,并将 Debian 替换为目标分发版的名称。

  1. 在 PowerShell 内的根级别打开 WSL 发行版后,可使用此命令更新密码:passwd ,其中 是 DISTRO 中帐户的用户名,而你忘记了它的密码。

  2. 系统将提示你输入新的 UNIX 密码,然后确认该密码。 在被告知密码已成功更新后,请使用以下命令在 PowerShell 内关闭 WSL:exit

五、Tips

5.1 重启

wsl环境下reboot和shutdown都是没有作用的,wsl可以通过windows命令行进行重启,使用管理员权限运行下面脚本实现重启:

  • cmd
1
2
net stop LxssManager
net start LxssManager
  • PowerShell
1
Get-Service LxssManager | Restart-Service

5.2 sudo su不输入密码

由于默认情况下我们不知道 root 用户的密码,所以如果我们想要使用 root 用户的话可以使用 passwd 命令为 root 用户设置一个新的密码,同时为了避免sudo切换root是需要输入密码,把自己配置的用户名加到sudo免密中,命令如下:

1
2
# 替换leap为自己单独配置的用户名
sudo echo "leap ALL=(ALL:ALL) NOPASSWD: ALL" >> /etc/sudoers

或者使用

1
visudo

进行编辑

5.2 更换ubuntu的apt更新源

默认的安装源相对国内很慢,我们更换源到阿里云,登录到ubuntu到操作如下:

1
2
3
4
5
6
7
8
9
10
11
12
cp /etc/apt/sources.list /etc/apt/sources.list.bak

echo "deb http://mirrors.aliyun.com/ubuntu/ focal main restricted
deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted
deb http://mirrors.aliyun.com/ubuntu/ focal universe
deb http://mirrors.aliyun.com/ubuntu/ focal-updates universe
deb http://mirrors.aliyun.com/ubuntu/ focal multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-updates multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted
deb http://mirrors.aliyun.com/ubuntu/ focal-security universe
deb http://mirrors.aliyun.com/ubuntu/ focal-security multiverse" > /etc/apt/sources.list

执行更新:

1
apt update && apt upgrade -y

可以会使用到

1
apt-get update && apt-get upgrade -y