010-update-alternatives安装gcc多版本

update-alternatives安装gcc多版本

1: 安装update-alternatives

  • 该工具属于dpkg软件包管理系统的核心组件,一般系统已预装。若提示命令不存在,可通过以下命令安装
  • 安装: sudo apt install dpkg
  • 验证: update-alternatives --help

2: ​添加旧版本软件源(针对gcc-4.8.5)

  • 由于Ubuntu 2024.04的默认源可能不包含gcc-4.8.5,需要手动添加旧版仓库:
1
2
sudo sed -i '$a deb http://archive.ubuntu.com/ubuntu/ xenial main universe' /etc/apt/sources.list
sudo apt update

3: 安装各版本GCC/G++

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 安装gcc/g++ 4.8.5(需依赖旧版源)
sudo apt install gcc-4.8 g++-4.8

# 安装gcc/g++ 7和9
sudo apt install gcc-7 g++-7 

#(默认源支持)
sudo apt install gcc-9 g++-9


# 如果apt 安装不了,手动下载安装
https://ftp.gnu.org/gnu/gcc/

4: 配置update-alternatives

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 添加gcc版本(优先级数值越大优先级越高)
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 40 \ 
--slave /usr/bin/g++ g++ /usr/bin/g++-4.8 \
--slave /usr/bin/gcov gcov /usr/bin/gcov-4.8

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 70 \ 
--slave /usr/bin/g++ g++ /usr/bin/g++-7 \
--slave /usr/bin/gcov gcov /usr/bin/gcov-7

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 90 \ 
--slave /usr/bin/g++ g++ /usr/bin/g++-9 \
--slave /usr/bin/gcov gcov /usr/bin/gcov-9

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 130 \ 
--slave /usr/bin/g++ g++ /usr/bin/g++-13 \
--slave /usr/bin/gcov gcov /usr/bin/gcov-13

5: 切换默认版本

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 交互式选择版本
sudo update-alternatives --config gcc

# 输出示例:
There are 3 choices for the alternative gcc (providing /usr/bin/gcc).

  Selection    Path              Priority   Status
------------------------------------------------------------
* 0            /usr/bin/gcc-9     90        auto mode
  1            /usr/bin/gcc-4.8   40        manual mode
  2            /usr/bin/gcc-7     70        manual mode
  3            /usr/bin/gcc-9     90        manual mode

Press <Enter> to keep the current choice[*], or type selection number: 

6: 版本验证

1
2
gcc --version  # 应显示当前选择的版本
g++ --version  # 应与gcc版本一致

020-pyenv管理python多版本

pyenv 管理 python 多版本

1:virtualenv

  • virtualenv 所要解决的是同一个库不同版本共存的兼容问题。例如项目 A 需要用到 requests 的 1.0 版本,项目 B 需要用到 requests 的 2.0 版本。如果不使用工具的话,一台机器只能安装其中一个版本,无法满足两个项目的需求。

019-文档转为markdown

将非 Markdown 格式的文档转换为 Markdown

1:介绍

  • 这是一个由微软开源的 Python 工具,可以将非 Markdown 格式的文档转换为 Markdown 格式,支持 PDF、PPT、Word 和 Excel 等多种文件类型,为文档的索引和文本分析提供了极大的便利。

017-pysftp SFTP Pool

pysftp SFTP Pool

  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
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

import pysftp
import os
import sys
import time
import paramiko
from queue import Queue, Empty

# -----------------------------


from etc import config
import utils
from utils import logger_web
from utils import logger_lms as logger


# -----------------------------
broker=config.LMS["broker"]
notifier_list=config.Notifier
notifier_list2=config.Notifier2

# -----------------------------

class SFTPConnectionPool:
    """SFTP连接池"""
    def __init__(self,host,port,username,password,max_connections=20):
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        self.max_connections = max_connections
        self.pool=Queue(maxsize=max_connections)
        self.cnopts = paramiko.SSHClient()
        self.cnopts.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        # self.cnopts.hostkeys = None
        self._init_pool()

    def _init_pool(self):
        for _ in range(self.max_connections):
            conn=self._create_conn()
            if conn:
                self.pool.put(conn)
            else:
                logger.error("初始化SFTP连接池失败")

    def _create_conn(self):
        transport=paramiko.Transport((self.host,self.port))
        transport.connect(username=self.username,password=self.password)
        return paramiko.SFTPClient.from_transport(transport)

    def get_conn(self):
        try:
            return self.pool.get(timeout=10)
        except Empty:
            logger.error("SFTPConnPool no avaiable connections ...")

    def release_conn(self,conn):
        if conn:
            self.pool.put(conn) # 将对象放回连接池
        else:
            logger.warning("SFTPConnPool attempted to release a None connection")

    def close_all_conn(self):
        while not self.pool.empty():
            conn=self.pool.get()
            if conn:
                conn.close()
            else:
                logger.warning("SFTPConnPool Found a None connection in the pool")




class SFTPClient:
    def __init__(self, host,port, username, password, upload_dir, download_dir):
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        self.upload_dir = upload_dir
        self.download_dir = download_dir
        self.max_retries = 3
        self.retry_delay = 5
        self.pool=SFTPConnectionPool(host,port,username,password)

    def ensure_connected(self):
        """确保SFTP连接是活跃的,如果断开则重连"""
        sftp=self.pool.get_conn()
        if not sftp:
            return False
        try:
            sftp.listdir()
            return True
        except Exception as e:
            logger.error("SFTPClient connection check failed, error={}".format(e))
            self.pool.release_conn(sftp)
            time.sleep(3)
            return False

    def upload_file(self, local_file):
        logger.info(f"SFTPClient start upload file={local_file} to remote_path={self.upload_dir}")
        if not os.path.exists(local_file):
            logger.error("SFTPClient UploadFile ={} does not exist".format(local_file))
            return False
        for attempt in range(self.max_retries):
            try:
                if not self.ensure_connected():
                    continue
                sftp=self.pool.get_conn()
                sftp.chdir(self.upload_dir)
                filename = os.path.basename(local_file)
                sftp.put(local_file) # /root/project/lms_jpm/static/files/xxx_request.csv
                logger.info(f"SFTPClient Successfully upload file={filename} to remote_path={self.upload_dir}")
                return True
            except Exception as e:
                logger.error(f"SFTPClient Failed upload file={local_file}, attempt {attempt+1} error={e}")
                if attempt < self.max_retries-1:
                    logger.error(f"SFTPClient Retrying upload file={local_file}, seconds ...")
                    time.sleep(self.retry_delay)
        return False

    def search_file(self, file):
        logger.info(f"SFTPClient start search remote_path={self.download_dir}/{file} ...")
        for attempt in range(self.max_retries):
            try:
                self.ensure_connected()
                self.conn.chdir(self.download_dir)
                files = self.conn.listdir()
                # logger.info(f"----------listdir-----------------{self.download_dir}---------------------------")
                # logger.info(f"-------------------------{file}---------------------{attempt+1}--------------------")
                # logger.info(files)
                # logger.info("--------------------------------------------------------------------")
                # logger.info("--------------------------------------------------------------------")
                # logger.info("--------------------------------------------------------------------")
                if file in files:
                    # logger.info(f"SFTPClient search remote_path={self.download_dir}/{file} ****** find ******")
                    return True
                return False
            except Exception as e:
                logger.error(f"SFTPClient search failed remote_path={self.download_dir}/{file}"+
                    f", attempt= {attempt+1}, error={e}")
                if attempt < self.max_retries-1:
                    time.sleep(self.retry_delay)
        return False

    def download_file(self, file, local_path):
        logger.info(f"SFTPClient start download remote_file={file} to {local_path}")
        for attempt in range(self.max_retries):
            try:
                if not self.ensure_connected():
                    continue
                sftp=self.pool.get_conn()
                sftp.chdir(self.download_dir)
                sftp.get(file, local_path)
                logger.info(f"SFTPClient Successfully downloaded {file} to {local_path}")
                return True
            except Exception as e:
                logger.error(f"SFTPClient Download failed remote_file={file}, attempt= {attempt+1}, error={e}")
                if attempt < self.max_retries-1:
                    time.sleep(self.retry_delay)
                    if os.path.exists(f"{local_path}/{file}"):
                        os.remove(f"{local_path}/{file}")  # 删除可能的部分下载文件
        return False

016-pysftp SFTP

pysftp SFTP

  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
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

import pysftp
import os
import sys
import time
import gnupg

from etc import config
import utils
from utils import logger_web
from utils import logger_lms as logger


# -----------------------------
broker=config.LMS["broker"]
notifier_list=config.Notifier
notifier_list2=config.Notifier2
# -----------------------------

class SFTPClient:
    def __init__(self, host,port, username, password, upload_dir, download_dir,gpg_key_id='D7B7817A'):
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        self.upload_dir = upload_dir
        self.download_dir = download_dir
        self.sftp = None
        self.gpg = gnupg.GPG(gnupghome="/root/.gnupg")
        self.gpg_key_id=gpg_key_id
        self.max_retries = 3
        self.retry_delay = 5
        # 禁用主机密钥检查
        self.cnopts = pysftp.CnOpts()
        self.cnopts.hostkeys = None
        self.connect()

    def ensure_connected(self):
        """确保SFTP连接是活跃的,如果断开则重连"""
        try:
            self.sftp.listdir()
        except Exception as e:
            logger.error("SFTPClient connection check failed, error={}".format(e))
            self.connect()
            time.sleep(3)

    def connect(self):
        """建立SFTP连接,包含重试机制"""
        for attempt in range(self.max_retries):
            try:
                if self.sftp:
                    try:
                        self.sftp.close()
                    except Exception as e:
                        logger.error("SFTPClient during disconnect error: {}".format(e))
                self.sftp = pysftp.Connection(
                    host=self.host,
                    port=self.port,
                    username=self.username,
                    password=self.password,
                    cnopts=self.cnopts
                )
                logger.info("SFTPClient connected to {}, connected success ...".format(self.host))
                return True
            except Exception as e:
                logger.error("SFTPClient connection attempt {} failed, error={}".format(attempt+1, e))
                if attempt < self.max_retries-1:
                    logger.error("SFTPClient Retrying in {} seconds...".format(self.retry_delay))
                    time.sleep(self.retry_delay)
        return False

    def upload_file(self, local_path):
        logger.info("SFTPClient start upload file={} to remote_path={}".format(local_path, self.upload_dir))
        if not os.path.exists(local_path):
            logger.error("SFTPClient UploadFile ={} does not exist".format(local_path))
            return False

        for attempt in range(self.max_retries):
            try:
                self.ensure_connected()
                self.sftp.chdir(self.upload_dir)
                filename = os.path.basename(local_path)
                self.sftp.put(local_path)
                logger.info("SFTPClient Successfully upload file={} to remote_path={}".format(filename, self.upload_dir))
                self.close()
                utils.send_message('markdown', "{} SFTP upload_file".format(broker),
                           "## {} SFTP upload_file success\nFtpSide={}\nFtpUser={}\nfile={}\n".format(broker,
                            config.LMS['ftp_url'],config.LMS['ftp_user'],filename),notifier_list)
                local_csvfile=local_path.replace(".pgp",'')
                utils.weichat_send_file(local_csvfile)
                return True
            except Exception as e:
                logger.error("SFTPClient Failed upload file={}, attempt {} error={}".format(local_path, attempt+1, str(e)))
                if attempt < self.max_retries-1:
                    logger.error("SFTPClient Retrying upload file={}, seconds...".format(local_path))
                    time.sleep(self.retry_delay)
        return False

    def search_file(self, filename):
        logger.info("SFTPClient start search remote_path={}/{} ...".format(self.download_dir, filename))
        for attempt in range(self.max_retries):
            try:
                self.ensure_connected()
                self.sftp.chdir(self.download_dir)
                files = self.sftp.listdir()
                logger.info(f"----------listdir-----------------{self.download_dir}---------------------------")
                logger.info(f"-------------------------{filename}---------------------{attempt+1}--------------------")
                logger.info(files)
                logger.info("--------------------------------------------------------------------")
                logger.info("--------------------------------------------------------------------")
                logger.info("--------------------------------------------------------------------")
                if filename in files:
                    logger.info("SFTPClient search remote_path={}/{} ****** find ******".format(self.download_dir, filename))
                    return True
                return False
            except Exception as e:
                logger.error("SFTPClient search failed remote_path={}/{}, attempt {}, error={}".format(
                    self.download_dir, filename, attempt+1, str(e)))
                if attempt < self.max_retries-1:
                    time.sleep(self.retry_delay)
        return False

    def download_file(self, remote_filename, local_file):
        logger.info("SFTPClient start download remote_path={}/{} to {}".format(
            self.download_dir, remote_filename, local_file))
        for attempt in range(self.max_retries):
            try:
                self.ensure_connected()
                self.sftp.chdir(self.download_dir)
                self.sftp.get(remote_filename, local_file)
                logger.info("SFTPClient Successfully downloaded {} to {}".format(remote_filename, local_file))
                self.close()
                utils.send_message('markdown', "{} SFTP download_file".format(broker),
                           "## {} SFTP download_file success\nFtpSide={}\nFtpUser={}\nfile={}\n".format(broker,
                            config.LMS['ftp_url'],config.LMS['ftp_user'],remote_filename),notifier_list)
                return True
            except Exception as e:
                logger.error("SFTPClient Download failed remote_path={}/{}, attempt {}, error={}".format(
                    self.download_dir, remote_filename, attempt+1, str(e)))
                if attempt < self.max_retries-1:
                    time.sleep(self.retry_delay)
                    if os.path.exists(local_file):
                        try:
                            os.remove(local_file)  # 删除可能的部分下载文件
                        except Exception as e:
                            logger.error("SFTPClient Download failed remote_path={}/{}, remove partial download local_path={}, error={}".format(
                                self.download_dir, remote_filename, local_file, str(e)))
        return False

    def close(self):
        if self.sftp:
            try:
                self.sftp.close()
            except Exception as e:
                logger.error("SFTPClient close has error:{}".format(e))

009-C++标准库中的<algorithm>头文件提供的常用算法

Cpp标准库中的头文件提供的常用算法

1: 介绍

  • 在 c++中, <algorithm> 头文件提供了一系列用于操作序列(如 array,vector,列表 list)的算法;
  • 这些算法可以极大的帮助我们简单高效的处理数据,提高代码的可读性和可维护性;

2: 查找算法 search

2.1 std::find

  • std::find 是一个线性查找算法,用于在序列中查找特定元素;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    int val = 3;

    // 使用std::find查找val在vec中的位置
    auto it = std::find(vec.begin(), vec.end(), val);
    if (it != vec.end()) {
        std::cout << "找到元素 " << val << " 在位置 " << std::distance(vec.begin(), it) << std::endl;
    } else {
        std::cout << "未找到元素 " << val << std::endl;
    }
    return 0;
}

2.2 std::find_if

  • std::find_if 允许你根据特定条件在序列中查找元素;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include <algorithm>
#include <vector>
#include <iostream>

bool is_even(int i) {
    return (i % 2) == 0;
}

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 使用std::find_if查找第一个偶数元素
    auto it = std::find_if(vec.begin(), vec.end(), is_even);

    if (it != vec.end()) {
        std::cout << "找到第一个偶数 " << *it << " 在位置 " << std::distance(vec.begin(), it) << std::endl;
    } else {
        std::cout << "未找到偶数" << std::endl;
    }
    return 0;
}

3: 排序算法 sort

3.1 std::sort

  • std::sort 是一个高效的排序算法,通常实现为快速排序、堆排序或归并排序的混合体;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include <algorithm>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> vec = {5, 2, 3, 1, 4};

    // 使用std::sort对vec进行排序
    std::sort(vec.begin(), vec.end());

    // 输出排序后的向量
    for (int i : vec) {
        std::cout << i << " ";
    }
    std::cout << std::endl;
    return 0;
}

3.2 std::stable_sort

  • std::stable_sort 是一种稳定的排序算法,即相等元素的相对顺序在排序后保持不变;
  • std::stable_sort 用法与 std::sort 类似,但保证排序的稳定性。

4: 修改序列算法

4.1 std::for_each

  • std::for_each 用于对序列中的每个元素执行特定操作;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#include <algorithm>
#include <vector>
#include <iostream>

void print(int i) {
    std::cout << i << " ";
}

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 使用std::for_each打印vec中的每个元素
    std::for_each(vec.begin(), vec.end(), print);
    std::cout << std::endl;
    return 0;
}

4.1 std::transform

  • std::transform 用于对序列中的每个元素执行某种转换,并将结果存储到另一个序列中;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#include <algorithm>
#include <vector>
#include <iostream>
#include <functional> // 为了使用std::plus等函数对象

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    std::vector<int> result(vec.size());

    // 使用std::transform将vec中的每个元素加倍并存储到result中
    std::transform(vec.begin(), vec.end(), result.begin(), [](int x) { return x * 2; });

    // 输出转换后的结果向量
    for (int i : result) {
        std::cout << i << " ";
    }
    std::cout << std::endl;
    return 0;
}

5: 其他常见算法

5.1 std::unique_copy

  • std::unique_copy算法用于从一个输入序列中复制不重复的元素到一个输出序列。这个算法假定输入序列是已排序的,因为只有已排序的序列才能保证相邻的重复元素被识别并去除
  • 先排序;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include <algorithm>
#include <vector>
#include <iostream>
#include <iterator>

int main() {
    std::vector<int> source = {1, 2, 2, 3, 4, 4, 4, 5};
    std::vector<int> destination;

    // 注意:在这个例子中,std::back_inserter是一个插入迭代器,它将新元素添加到destination容器的末尾
    std::unique_copy(source.begin(), source.end(), std::back_inserter(destination));

    // 输出目标向量,应不包含重复的元素
    for (int val : destination) {
        std::cout << val << " ";
    }
    std::cout << std::endl;

    return 0;
}

5.2 std::merge

  • std::merge 算法用于合并两个已排序的序列,结果也是一个已排序的序列;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include <algorithm>
#include <vector>
#include <iostream>
#include <iterator>

int main() {
    std::vector<int> vec1 = {1, 3, 5, 7};
    std::vector<int> vec2 = {2, 4, 6, 8};
    std::vector<int> result(vec1.size() + vec2.size());

    std::merge(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), result.begin());

    // 输出合并后的结果向量
    for (int val : result) {
        std::cout << val << " ";
    }
    std::cout << std::endl;

    return 0;
}

5.3 集合算法:std::set_difference, std::set_intersection, std::set_union, std::set_symmetric_difference

  • 这些算法用于在两个已排序的序列之间执行集合操作。
  • std::set_difference:计算两个已排序范围的差集。
  • std::set_intersection:计算两个已排序范围的交集。
  • std::set_union:计算两个已排序范围的并集。
  • std::set_symmetric_difference:计算两个已排序范围的对称差集(即属于第一个范围但不属于第二个范围,以及属于第二个范围但不属于第一个范围的所有元素)。
  • 对于其他集合算法,使用方法是类似的,只是调用的函数名不同,以及它们处理集合运算的方式不同。这些算法在处理大量数据时可以显著提高效率,因为它们都利用了输入数据已排序的特性来优化性能

6 其他值得注意的算法

  • 除了之前提到的算法外,C++标准库还提供了许多其他有用的算法,这些算法在处理各种编程任务时都非常实用。

6.1. std::partition 和 std::stable_partition

std::partition 和 std::stable_partition 算法用于根据给定谓词对序列进行划分,使得满足谓词的元素出现在不满足谓词的元素之前。std::stable_partition 还保持了等价元素的相对顺序。

015-pip命令说明

[toc]

Table of Contents

1:pip 命令说明

1.1: 安装 pip

  • python -m pip --version:

1.2: 安装 Python 库

  • pip install requests: 它会自动处理库及其依赖关系

1.3: 升级库

  • pip list --outdated # 查看待升级库
  • pip upgrade <package_name> # 升级指定库

1.4: 卸载库

  • pip uninstall <package_name>

1.5: 搜索库

  • pip search <keyword>: 比如查找与机器学习相关的库,你可以输入 pip search machine learning

1.6: 查看已安装库详细信息

  • pip show <package_name>

1.7: 只下载库而不安装

  • 有时你可能需要离线环境安装包或者备份当前环境的依赖,那么可以使用 download 命令只下载不安装:
  • pip download <package_name>

1.8: 创建 requirements 文件

  • 在项目开发中,为了方便团队成员统一环境,我们可以创建一个包含所有依赖的 requirements 文件:
  • pip freeze > requirements.txt
  • 这会列出当前环境中所有已安装库及其版本,并保存到 requirements.txt 文件中。而要根据这个文件安装所有依赖,只需:
  • pip install -r requirements.txt

1.9: 指定库版本安装

  • 在某些情况下,你可能需要安装特定版本的库,比如安装 requests 库的 2.25.1 版本
  • pip install requests==2.25.1

1.10: 检查是否存在安全漏洞

  • pip 配合 Safety 工具可以检查已安装库的安全性:

040-Linux安装配置gitlab私有仓库

1: 安装 gitlab

1.1 安装

  • https://packages.gitlab.com/gitlab/gitlab-ce/install

  • 安装工具包: apt install policycoreutils-python-utils

  • 安装 gitlab: curl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash

  • sudo apt install gitlab-ce

  • 安装成功成功出现如下图所示:

1.2 配置

  • 更新配置 :gitlab-ctl reconfigure。装完成后,更新配置,稍微需要点时间,耐心等待一下,完成后,我们可以看到用户名和密码
  • 以下信息我们可以看到用户名和密码,用户名为:root,密码需要单独查看
  • 上面那个路径就是密码路径,查看密码:cat /etc/gitlab/initial_root_password

1.3 启动 gitlab

  • gitlab-ctl start;