旧的笔记

这是我第三次把这个笔记搬运了。

其中大部分为 AI 生成的,对当时的我有意义的内容。本来该将这个博客分开,挂上不同的标签,便于查阅,但是马上要回家了,我就暂时不干了。

杂乱的内容整理

今天大致将原来所学过的知识整理一下,防止AI掉线
也算是回忆一下

c++ 有关操作

多线程编程

单线程调用多个函数

C++多线程可以一个线程调用多个函数。下面是一个简单的例子:

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
#include <iostream>
#include <thread>

// 函数1:打印数字
void printNumber(int number) {
std::cout << "Printing number: " << number << std::endl;
}

// 函数2:打印字符串
void printString(const std::string& str) {
std::cout << "Printing string: " << str << std::endl;
}

int main() {
// 创建一个线程并调用两个函数
std::thread myThread([](){
printNumber(42);
printString("Hello, world!");
});

// 等待线程执行完毕
myThread.join();

return 0;
}

在上面的示例中,我们创建了一个线程myThread,该线程同时调用了printNumberprintString两个函数。在main函数中,我们使用join等待线程执行完毕。当程序运行时,会输出以下结果:

1
2
Printing number: 42
Printing string: Hello, world!

这表明两个函数在同一个线程中被顺序调用。注意,这里的调用顺序是不确定的,因为线程的执行顺序取决于操作系统的调度策略。

select 监视函数用法和读写操作

select 函数用法

select函数是一个在Unix和类Unix系统上常用的系统调用,用于在一组文件描述符上等待某种事件的发生。它主要用于实现I/O多路复用,允许程序同时监视多个文件描述符,一旦其中任何一个文件描述符准备好进行读、写或者出现异常,select函数就会返回,从而允许程序进行相应的I/O操作。

select函数的基本用法如下:

1
2
3
4
5
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
  • nfds 是待监视的文件描述符集合中所有文件描述符的最大值加1。
  • readfdswritefdsexceptfds 分别是待监视的文件描述符集合,用于监视读、写和异常情况。
  • timeout 是一个指向 struct timeval 结构的指针,用于设置超时时间。

以下是一个简单的例子,说明如何使用select函数来监视文件描述符集合中的文件描述符:

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
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
fd_set readfds;
struct timeval tv;
int retval;

// 清空并设置文件描述符集合
FD_ZERO(&readfds);
FD_SET(STDIN_FILENO, &readfds);

// 设置超时时间为5秒
tv.tv_sec = 5;
tv.tv_usec = 0;

// 监视文件描述符集合中的文件描述符
retval = select(STDIN_FILENO + 1, &readfds, NULL, NULL, &tv);

if (retval == -1) {
perror("select()");
} else if (retval) {
printf("Data is available now.\n");
// 在这里进行读操作
} else {
printf("No data within 5 seconds.\n");
}

return 0;
}

在这个例子中,我们使用select函数来监视标准输入(STDIN_FILENO),并设置了一个5秒的超时时间。如果在5秒内有数据可读,select函数将返回一个大于0的值,表示有数据可读;否则,将返回0,表示超时;如果出现错误,将返回-1。

其中,select所需fd产生方法:

在这段代码中,FD_ZEROFD_SET 是宏,通常用于操作文件描述符集合。这些宏通常是为了方便地操纵文件描述符集合而定义的。以下是它们的用法:

  • FD_ZERO(fd_set *set):用于将指定的文件描述符集合清空,即将其所有位都设置为0。

  • FD_SET(int fd, fd_set *set):用于将指定的文件描述符加入到文件描述符集合中。

在上述代码中,首先通过调用 FD_ZERO(&readfds)readfds 文件描述符集合清空,以确保其中不包含任何文件描述符。接着,通过调用 FD_SET(STDIN_FILENO, &readfds) 将标准输入文件描述符 STDIN_FILENO 加入到 readfds 文件描述符集合中,以便在接下来的 select 调用中监视标准输入。

STDIN_FILENO 是一个宏定义,通常用于表示标准输入的文件描述符。在 POSIX 系统中,它的值通常是 0。因此,当我们使用 STDIN_FILENO 时,实际上是在使用文件描述符 0,表示标准输入流。

读写操作

readwrite 函数是在 Unix 和类 Unix 系统上用于进行文件 I/O 操作的函数。

  • read 函数的用法:

    1
    ssize_t read(int fd, void *buf, size_t count);

    这个函数用于从文件描述符 fd 所指向的文件中读取 count 个字节的数据到 buf 中。它返回实际读取的字节数,如果返回值为 0,表示已经到达文件末尾,返回值为 -1 表示出现了错误。

  • write 函数的用法:

    1
    ssize_t write(int fd, const void *buf, size_t count);

    这个函数用于将 buf 中的 count 个字节数据写入到文件描述符 fd 所指向的文件中。它返回实际写入的字节数,如果返回值为 -1,表示出现了错误。

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main() {
int fd = open("output.txt", O_CREAT | O_WRONLY, 0644);
if (fd == -1) {
perror("open");
return 1;
}

const char *buffer = "Hello, World!\n";
ssize_t bytes_written = write(fd, buffer, strlen(buffer));
if (bytes_written == -1) {
perror("write");
} else {
printf("Successfully wrote %zd bytes\n", bytes_written);
}

close(fd);
return 0;
}

在这个例子中,我们首先使用 open 函数打开一个名为 “output.txt” 的文件,然后使用 write 函数将字符串 “Hello, World!\n” 写入到这个文件中。最后关闭文件描述符。

字符串操作

简略掌握

在C++中,有许多用于操作字符串的函数。以下是一些常用的字符串操作函数,以及它们的详细用法:

  1. **std::string::length**:这个函数返回字符串的长度,即字符串中的字符数。例如:
1
2
std::string str = "Hello, World!";
std::cout << str.length(); // 输出 13
  1. **std::string::substr**:这个函数用于从字符串中提取子字符串。它有两个版本,一个版本接受一个参数,另一个版本接受两个参数。例如:
1
2
3
4
5
std::string str = "Hello, World!";
std::string sub1 = str.substr(0); // 从第一个位置开始提取子字符串
std::string sub2 = str.substr(0, 3); // 从第一个位置开始提取3个字符的子字符串
std::cout << sub1 << std::endl; // 输出 "Hello, World!"
std::cout << sub2 << std::endl; // 输出 "Hel"
  1. **std::string::find**:这个函数用于在字符串中查找子字符串。如果找到了,它会返回子字符串的第一个字符在字符串中的位置;如果没有找到,它会返回std::string::npos。例如:
1
2
3
4
5
6
7
std::string str = "Hello, World!";
size_t pos = str.find("World");
if (pos != std::string::npos) {
std::cout << "Found at position " << pos << std::endl; // 输出 "Found at position 7"
} else {
std::cout << "Not found" << std::endl;
}
  1. **std::string::replace**:这个函数用于替换字符串中的子字符串。例如:
1
2
3
std::string str = "Hello, World!";
str.replace(0, 5, "Hi"); // 用"Hi"替换从第一个位置开始的5个字符
std::cout << str << std::endl; // 输出 "Hi, World!"
  1. **std::string::erase**:这个函数用于删除字符串中的字符。它有两个版本,一个版本接受一个参数,另一个版本接受两个参数。例如:
1
2
3
std::string str = "Hello, World!";
str.erase(0, 5); // 删除从第一个位置开始的5个字符
std::cout << str << std::endl; // 输出 "World!"
  1. **std::string::c_str**:这个函数用于返回一个指向以空字符结尾的字符数组的指针,这个字符数组包含了字符串的内容。例如:
1
2
3
std::string str = "Hello, World!";
const char* cstr = str.c_str();
std::cout << cstr << std::endl; // 输出 "Hello, World!"

erase 用法

在C++中,erasestd::string类的一个成员函数,用于从字符串中删除指定位置的字符或一定范围内的字符。它有多种用法,以下是一些详细的例子:

  1. 删除单个字符:你可以使用erase来删除字符串中的单个字符。例如,以下代码将从字符串str的第一个位置开始删除一个字符:
1
2
3
std::string str = "Hello";
str.erase(0, 1); // 删除从第一个位置开始的一个字符
std::cout << str; // 输出 "ello"
  1. 删除一定范围内的字符:你也可以使用erase来删除字符串中的一定范围内的字符。例如,以下代码将从字符串str的第一个位置开始删除3个字符:
1
2
3
std::string str = "Hello";
str.erase(0, 3); // 删除从第一个位置开始的3个字符
std::cout << str; // 输出 "lo"
  1. 删除所有满足条件的字符:你可以使用erasestd::remove_if算法来删除字符串中所有满足某个条件的字符。例如,以下代码将从字符串str中删除所有的空格:
1
2
3
std::string str = "Hello World";
str.erase(std::remove_if(str.begin(), str.end(), ::isspace), str.end());
std::cout << str; // 输出 "HelloWorld"

在这个例子中,std::remove_if算法会将满足::isspace条件的字符移到字符串的末尾,然后erase函数会删除这些字符。

substr 用法举例

在C++中,substrstd::string类的一个成员函数,用于从字符串中提取子字符串。它有两个版本,一个版本接受一个参数,另一个版本接受两个参数。以下是详细的例子:

  1. 接受一个参数的版本:这个版本的substr函数接受一个参数,这个参数是从哪个位置开始提取子字符串。例如,以下代码将从字符串str的第一个位置开始提取子字符串:
1
2
3
std::string str = "Hello, World!";
std::string sub = str.substr(0); // 从第一个位置开始提取子字符串
std::cout << sub; // 输出 "Hello, World!"
  1. 接受两个参数的版本:这个版本的substr函数接受两个参数,第一个参数是从哪个位置开始提取子字符串,第二个参数是提取多少个字符。例如,以下代码将从字符串str的第一个位置开始提取3个字符的子字符串:
1
2
3
std::string str = "Hello, World!";
std::string sub = str.substr(0, 3); // 从第一个位置开始提取3个字符的子字符串
std::cout << sub; // 输出 "Hel"

在这个例子中,substr函数从字符串str的第一个位置开始提取3个字符的子字符串,然后将这个子字符串赋值给sub

stof/stoi 用法举例

std::stof是C++标准库中的一个函数,用于将字符串转换为单精度浮点数(float)。它的用法如下:

1
float stof (const string& str, size_t* idx = 0);
  • str:要转换为浮点数的字符串。
  • idx:可选参数,指向存储转换结束位置的指针。

以下是一个示例,演示了如何使用std::stof函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <string>

int main() {
std::string str = "3.14159";
size_t idx; // 用于存储转换结束位置的索引
float f = std::stof(str, &idx);

std::cout << "The converted float is " << f << std::endl;
std::cout << "The index of the next character after the float is " << idx << std::endl;

return 0;
}

在这个示例中,我们将字符串”3.14159”转换为浮点数,并打印出转换后的浮点数以及转换结束位置的索引。

当使用std::stoi时,你需要提供以下参数:

  1. 字符串:这是要转换为整数的输入字符串。
  2. 指向size_t类型对象的指针(可选):用于存储转换后的最后一个字符的索引。如果不需要此信息,可以将其设置为nullptr。
  3. 基数(可选,默认为10):指定数字的进制。例如,如果你想解析一个十六进制数字,你可以将基数设置为16。

下面是一个简单的例子:

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <string>

int main() {
std::string str = "12345";
size_t pos; // 用于存储转换后的最后一个字符的索引
int num = std::stoi(str, &pos);
std::cout << "The integer value is: " << num << std::endl;
std::cout << "The index of the last character processed is: " << pos << std::endl;
return 0;
}

在这个例子中,字符串”12345”被转换为整数12345并存储在变量num中。变量pos将包含转换后的最后一个字符的索引。

运算符重载

在C++中,可以通过重载()运算符来实现仿函数(Function Object)。一个常见的示例是实现一个加法仿函数,让其能够像函数一样接受整数参数并返回加法结果。以下是一个简单的示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include &ltiostream&gt

class Adder {
public:
int operator()(int x) {
return x + 10;
}
};

int main() {
Adder adder;
int result = adder(5); // 实际上调用了 adder.operator()(5)

std::cout &lt&lt "Result: " &lt&lt result &lt&lt std::endl; // 输出: Result: 15

return 0;
}

在这个例子中,Adder类重载了()运算符,使得我们可以像调用函数一样使用Adder类的对象adder,并传入一个整数参数。当我们调用adder(5)时,实际上会调用Adder类中重载的()运算符函数,这个函数接受一个整数参数并返回x + 10的结果,最终输出结果为15。

linux 有关整理

这里我就挑几个重要的写
太多了,来不及粘贴

ssh 协议连接

这个命令是用于通过SSH协议(Secure Shell)连接到远程主机的命令。具体来说,ssh non@192.168.51.8的含义如下:

  • ssh: 是用于启动SSH客户端的命令。
  • non: 这是一个用户名,表示您希望使用用户名non来连接到远程主机。
  • 192.168.51.8: 这是远程主机的IP地址或主机名,表示您希望连接到IP地址为192.168.51.8的远程主机。

因此,当您运行ssh non@192.168.51.8时,您正在尝试使用用户名non通过SSH连接到IP地址为192.168.51.8的远程主机。如果输入密码正确并且远程主机允许该用户通过SSH登录,您将成功建立连接并获得远程主机的Shell访问权限。

通过SSH协议(Secure Shell)连接到服务器或电脑是一种安全的远程访问方式,可以在不安全的网络环境下进行加密通信。下面是通过SSH连接到服务器或电脑的一般步骤:

连接到服务器或电脑的步骤:

  1. 打开终端:在本地计算机上打开终端或命令行界面。

  2. 输入SSH命令:使用以下命令连接到目标主机:

    1
    ssh username@hostname

    其中,username是您在远程主机上的用户名,hostname是远程主机的IP地址或域名。

  3. 输入密码:如果是第一次连接,系统可能会询问是否要添加主机到已知主机列表中,输入yes后会要求输入密码。

  4. 输入密码:输入您的远程主机密码(密码不会显示在屏幕上)。

  5. 成功连接:如果密码正确,您将会成功连接到远程主机,可以开始在远程主机上执行命令。

SSH连接原理:

  • 加密通信:SSH通过加密技术确保通信过程中的数据传输安全,包括身份验证、命令传输和数据传输等。

  • 公钥加密:SSH使用公钥加密技术来进行身份验证和建立安全连接。当您连接到远程主机时,客户端和服务器之间会交换公钥,然后使用这些密钥来加密通信。

  • 安全认证:在连接时,SSH要求用户提供密码或者使用公钥进行认证。这种方式可以防止未经授权的用户访问远程主机。

  • 端到端加密:SSH协议提供端到端的加密,确保数据在传输过程中不会被窃取或篡改。

总的来说,SSH协议通过加密通信、安全认证和端到端加密等技术,为用户提供了一种安全、加密的远程访问方式,使得用户可以在不安全的网络环境下安全地访问远程主机。ii

linux 联网操作:

Linux服务器连接到互联网通常需要配置网络连接。以下是连接Linux服务器到互联网的一般步骤:

  1. 检查网络连接:首先,确保服务器的网络接口是正常连接的,可以通过以下命令检查网络接口状态:

    1
    ifconfig
  2. 配置网络接口:您可以通过编辑网络配置文件来配置网络接口。在大多数Linux发行版中,网络配置文件通常位于/etc/network/interfaces或者/etc/sysconfig/network-scripts/ifcfg-<interface>

  3. 配置IP地址:为服务器分配一个IP地址,可以是静态IP地址或者动态分配IP地址(DHCP)。

  4. 配置网关:设置默认网关,以便服务器知道如何路由到互联网。

  5. 配置DNS:配置DNS服务器,以便服务器能够解析域名。

  6. 重启网络服务:在完成配置后,您可能需要重启网络服务以使更改生效。您可以使用以下命令重启网络服务:

    1
    sudo systemctl restart networking
  7. 测试连接:最后,您可以通过ping命令测试服务器是否能够访问互联网。例如,尝试ping一个已知的互联网地址:

    1
    ping www.google.com

通过以上步骤,您可以配置Linux服务器的网络连接,使其能够连接到互联网并进行通信。如果您遇到任何问题,可以检查网络配置文件以及网络连接状态,以便进行故障排除。

bashrc 配置bash

要让Linux命令窗口永久具有颜色高亮效果,您可以通过修改终端配置文件来实现。具体步骤可能会因终端类型和Linux发行版而有所不同,以下是一般步骤:

步骤:

  1. 找到终端配置文件:不同的终端可能会使用不同的配置文件。一般来说,常见的终端配置文件包括:

    • Bash shell~/.bashrc~/.bash_profile
    • Zsh shell~/.zshrc
    • GNOME终端:可以在终端的首选项中设置
    • 其他终端:具体取决于您使用的终端类型
  2. 编辑配置文件:使用文本编辑器打开相应的配置文件,添加设置文本颜色的命令。例如,您可以添加类似下面的命令来设置提示符为绿色:

    1
    export PS1="\[\033[0;32m\][\u@\h \W]\$ \[\033[0m\]"

    这个命令会将提示符设置为绿色。

  3. 保存并生效:保存配置文件并使更改生效。您可以通过执行以下命令使更改生效:

    1
    source ~/.bashrc
  4. 重新打开终端:关闭当前终端窗口并重新打开一个新的终端窗口,您应该能看到新的颜色设置生效。

注意事项:

  • 在编辑配置文件时,请确保您知道您在做什么,以免意外导致终端无法正常工作。
  • 不同的终端可能需要不同的设置语法和命令,具体取决于您使用的终端类型。
  • 永久更改终端颜色可能会影响可读性,因此请谨慎选择颜色设置。

请根据您使用的终端类型和个人喜好,调整颜色设置以满足您的需求。

注意事项:

bashrc 位置不同,作用范围也不同,分为home和root

root可以sudo -i开启root模式

bashrc还可以搞快捷键

docker/docker-compose 整理

工作原理

Docker Compose 是一个用于定义和运行多个 Docker 容器应用的工具。它通过一个单独的 YAML 文件(通常命名为docker-compose.yml)来配置应用的服务,然后使用这个文件来创建和管理这些服务。Docker Compose 可以大大简化多容器应用的部署和管理过程。

Docker Compose 的工作原理:

  1. 编写 docker-compose.yml 文件:用户首先需要编写一个 docker-compose.yml 文件,该文件定义了应用的服务、网络、卷等配置。在这个文件中,用户可以指定每个服务的镜像、端口映射、环境变量、依赖关系等信息。

  2. 启动容器:用户使用 docker-compose up 命令来启动应用程序。Docker Compose 将会根据docker-compose.yml文件中的配置来启动所需的容器。

  3. 构建镜像:如果在 docker-compose.yml 中指定的镜像不存在,Docker Compose 将会根据 Dockerfile 来构建镜像。Dockerfile 是一个包含了构建镜像所需指令的文本文件,定义了如何构建 Docker 镜像。Docker Compose 会自动查找当前目录下的 Dockerfile 来构建镜像。

  4. 容器间通信:Docker Compose 会自动创建一个默认网络,所有在同一个 docker-compose.yml 文件中定义的服务都会连接到这个网络上。这样,不同的容器就可以通过服务名相互通信。

如何通过 .yml 文件构建镜像和容器:

  1. 构建镜像:在 docker-compose.yml 文件中,可以使用 build 关键字指定构建镜像所需的信息,比如 Dockerfile 的路径。例如:

    1
    2
    3
    4
    5
    services:
    myservice:
    build:
    context: .
    dockerfile: Dockerfile
  2. 构建容器:在 docker-compose.yml 文件中,定义了服务后,可以使用 docker-compose up 命令来构建并启动容器。如果镜像不存在,Docker Compose 会自动根据 Dockerfile 构建镜像,然后启动容器。

Dockerfile 在 Docker Compose 中的作用:

Dockerfile 是用来构建 Docker 镜像的脚本文件,定义了镜像的内容和构建方式。在 Docker Compose 中,Dockerfile 主要用于构建镜像,以及指定镜像的基础环境和依赖。

当在 docker-compose.yml 文件中使用 build 关键字指定了 Dockerfile 的路径后,Docker Compose 将会根据这个 Dockerfile 来构建镜像。Dockerfile 中的指令将会按顺序执行,以构建出最终的镜像。Docker Compose 可以根据 Dockerfile 中的指令构建出多个镜像,每个服务都可以有自己的 Dockerfile。

总之,Dockerfile 在 Docker Compose 中的作用是定义镜像的构建过程,包括基础镜像、依赖安装、文件拷贝等操作,以供 Docker Compose 使用。

二者关系

docker-compose.ymlDockerfile 是 Docker 中的两个不同概念,它们通常用于不同的目的并且不会直接冲突。

  • Dockerfile: 用于构建 Docker 镜像的文件,其中包含了构建镜像所需的指令,比如基础镜像、安装软件、设置环境变量、拷贝文件等。通过执行 docker build 命令可以根据 Dockerfile 构建出一个镜像。

  • docker-compose.yml: 用于定义和运行多个 Docker 容器的配置文件,可以一次性启动多个容器,并且定义了容器之间的关系、网络设置、卷挂载等。通过执行 docker-compose up 命令可以根据 docker-compose.yml 启动整个应用的容器组。

虽然它们有不同的作用,但在某些情况下,docker-compose.yml 文件中也可以包含一些与 Dockerfile 相关的指令,比如 build 指令用于构建镜像。下面是一个简单的示例:

假设有一个应用,需要构建一个镜像并运行两个容器:一个是 Web 服务器,一个是数据库。

Dockerfile 可能如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 基于官方的 Node 镜像
FROM node:14

# 设置工作目录
WORKDIR /app

# 拷贝应用代码到工作目录
COPY . .

# 安装依赖
RUN npm install

# 暴露端口
EXPOSE 3000

# 启动应用
CMD ["npm", "start"]

docker-compose.yml 可能如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
version: '3'
services:
web:
build: .
ports:
- "3000:3000"
depends_on:
- db
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: example

在这个示例中,docker-compose.yml 中的 build: . 指令告诉 docker-compose 使用当前目录下的 Dockerfile 构建 web 服务的镜像。这样可以通过 docker-compose up 一次性启动两个容器,而不需要手动执行 docker builddocker run 命令。

因此,虽然 docker-compose.yml 中可以包含一些与 Dockerfile 相关的指令,但它们的作用和目的不同,不会直接冲突。

奇怪的命令和软件安装

apt install 安装路径

在默认情况下,apt install 命令会将软件包安装到系统中预定义的目录结构中。在大多数情况下,Debian和Ubuntu系统中的软件包通常会被安装到以下目录中:

  • 可执行文件通常会被安装到 /usr/bin/ 目录下。
  • 库文件通常会被安装到 /usr/lib/ 目录下。
  • 配置文件通常会被安装到 /etc/ 目录下。
  • 文档通常会被安装到 /usr/share/doc/ 目录下。
  • 其他资源文件通常会被安装到 /usr/share/ 目录下。

需要注意的是,具体的安装路径可能会因软件包而异,有些软件包可能会有自定义的安装路径。如果你想要查看特定软件包的安装路径,可以使用dpkg命令来查询已安装软件包的文件列表,例如:

1
dpkg -L package_name

这将列出特定软件包安装的文件路径。

自动联网更新时间

以ntp为例,或者可以使用chrony

安装ntp

  1. 检查并更新你的系统时间
    你可以使用 date 命令查看当前系统时间:

    1
    date

    如果时间不正确,你可以使用 sudo 权限手动设置正确的时间,或者更好的是,使用 NTP(网络时间协议)自动同步时间。

  2. 使用 NTP 自动同步时间
    安装 ntp 服务:

    1
    sudo apt install ntp

    安装完成后,NTP 服务会启动并尝试自动同步你的系统时间。

  3. 手动设置系统时间
    如果你不想使用 NTP,也可以手动设置系统时间。例如,设置为 2023年10月1日12:00可以使用:

    1
    sudo date --set="2023-10-01 12:00:00"

    确保使用你的本地时间。

  4. **重新运行 sudo apt update**:
    在调整时间之后,重新运行更新命令:

    1
    sudo apt update

启动ntp

  1. 确定初始化系统管理器
1
ps --no-headers -o comm 1

如果返回的不是systemd,你需要用我的方法init

  1. 确定启动名称
1
ls /etc/init.d/

查看最接近nfds的名称,这是我的:

1
2
3
4
5
6
root@姒克禹:/home/cofallen/Code/Cpp# ls /etc/init.d/
apparmor cups kmod procps ufw
apport dbus lightdm pulseaudio-enable-autospawn unattended-upgrades
bluetooth hwclock.sh ntpsec rsync uuidd
console-setup.sh irqbalance plymouth saned whoopsie
cron keyboard-setup.sh plymouth-log screen-cleanup x11-commo

一眼看出ntpsec是吧。

  1. 启动进程
1
2
3
root@姒克禹:/home/cofallen/Code/Cpp# sudo service ntpsec start
* Starting NTP server ntpd 2024-05-20T22:18:10 ntpd[20837]: INIT: ntpd ntpsec-1.2.2: Starting
2024-05-20T22:18:10 ntpd[20837]: INIT: Command line: /usr/sbin/ntpd -p /run/ntpd.pid -c /etc/ntpsec/ntp.conf -g -N -u ntpsec:ntpsec

git 文件

.git 文件夹是 Git 仓库的核心,它包含了跟踪项目版本历史和管理文件更改所需的所有信息。以下是 .git 文件夹中一些重要文件和文件夹的解释:

  1. branches:

    • 包含指向各个分支头部的指针文件。
  2. hooks:

    • 包含客户端或服务器上的钩子脚本,这些脚本在特定的重要动作发生时会被执行。
  3. info:

    • 包含全局性的排除文件(global exclude file)。
  4. objects:

    • 存储所有数据内容的地方。Git 使用一种称为“哈希”的机制来对内容进行索引,这些内容可以是文件内容或者目录结构。
  5. refs:

    • 存储指向数据(如提交对象)的提交对象(commit objects)的指针。这里也包含了远程仓库的引用。
  6. config:

    • 包含了本地仓库的配置信息,例如用户信息、远程仓库地址等。
  7. HEAD:

    • 指示当前所在分支的符号引用。
  8. index:

    • 包含了暂存区的内容,用于记录下一次提交的文件状态。
  9. logs:

    • 包含引用日志,可以用来查看每个引用的更新历史。

这些文件和文件夹组成了 Git 仓库的基本结构,负责跟踪文件变化、存储元数据和配置信息、以及维护分支和标签等重要功能。


旧的笔记
https://cofallen.github.io/2024/07/15/old/
作者
cofallen
发布于
2024年7月15日
更新于
2024年7月16日
许可协议