2024-08-23

Linux的历史可以追溯到1991年,由芬兰大学的学生Linus Torvalds开始编写。Linux是一种开源的操作系统内核,它是Unix操作系统的一个免费和开放源码的版本。

Linux的发展历程大致如下:

  1. 1991年:Linus Torvalds开始编写Linux内核。
  2. 1994年:第一个Linux内核发布,只有大约1000行代码。
  3. 1996年:Linux 1.0发布,包含了基本的内核和一些外围程序。
  4. 1998年:Linux 2.0发布,引入了完全符合POSIX标准的内核。
  5. 2003年:Linux内核2.6.0发布,这是2.6版本的开始,引入了重要的改进和新特性。
  6. 2008年:Linux内核3.0发布,这是3.x版本的开始,引入了更多的新特性和改进。
  7. 2011年:Linux内核3.3发布,引入了包括Full-ESXi在内的一系列重要的改进。
  8. 2013年:Linux内核3.10发布,成为了主流发行版的默认内核。
  9. 2014年:Linux内核3.13发布,引入了内存错误检测的改进。
  10. 2016年:Linux内核4.0发布,这是一个重要的里程碑,标志着Linux内核进入了新的时代。

Linux的发展和成功部分得益于其开源特性,这允许全世界的开发者和用户对其进行研究、修改和改进。开发者可以查看Linux内核的源代码,并对其进行更改,以满足特定的需求。这个过程也促进了软件开发的分布式协作。

2024-08-23

在Linux中更新内核可以通过以下几种方式:

  1. 使用包管理器更新:

    大多数Linux发行版使用包管理器来管理内核。你可以通过包管理器来更新内核。例如,在基于Debian的系统中,你可以使用以下命令:




sudo apt-get update
sudo apt-get upgrade
sudo apt-get dist-upgrade

在基于RPM的系统中,如Fedora,你可以使用以下命令:




sudo dnf update
  1. 手动下载并安装内核:

    如果你需要特定版本的内核或者包管理器中没有你需要的版本,你可以从Linux内核官方网站(https://www.kernel.org/)手动下载内核源码,编译并安装。

下载内核源码:




wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.17.tar.xz

解压源码:




tar -xvf linux-5.10.17.tar.xz

进入目录:




cd linux-5.10.17

配置内核选项:




make menuconfig

编译内核:




make -j $(nproc)

安装内核:




sudo make modules_install
sudo make install

更新引导加载程序:




sudo update-grub
  1. 使用第三方内核管理工具:

    有些第三方工具,如KspliceELRepo,提供了更新内核的更简便方法。

例如,在基于RHEL的系统中使用ELRepo更新内核:




sudo yum install https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm
sudo yum --enablerepo=elrepo-kernel install kernel-ml
sudo grub2-set-default 0
sudo reboot

注意:手动更新内核可能导致系统不稳定或不兼容。始终确保你理解你正在做什么,并在执行之前备份重要数据。

2024-08-23

以下是60条常用的Linux命令,每条命令后面都附带了说明和示例:

  1. ls - 列出目录内容

    
    
    
    ls -l /home # 列出/home目录下的所有文件及详细信息
  2. cd - 切换目录

    
    
    
    cd /home # 切换到/home目录
  3. touch - 创建空文件

    
    
    
    touch newfile.txt # 创建一个名为newfile.txt的空文件
  4. cat - 查看文件内容

    
    
    
    cat file.txt # 显示file.txt文件的内容
  5. cp - 复制文件或目录

    
    
    
    cp file.txt /home # 将file.txt复制到/home目录下
  6. mv - 移动或重命名文件或目录

    
    
    
    mv file.txt /home # 将file.txt移动到/home目录
  7. rm - 删除文件或目录

    
    
    
    rm file.txt # 删除file.txt文件
  8. grep - 文本搜索

    
    
    
    grep "text" file.txt # 在file.txt中搜索包含"text"的行
  9. find - 在文件系统中查找文件

    
    
    
    find /home -name "file.txt" # 在/home目录下查找名为file.txt的文件
  10. gzip/gunzip - 压缩和解压缩文件

    
    
    
    gzip file.txt # 压缩file.txt文件
    gunzip file.txt.gz # 解压file.txt.gz文件
  11. tar - 打包和解压文件

    
    
    
    tar -cvf archive.tar /home # 将/home目录打包成archive.tar文件
    tar -xvf archive.tar # 解压archive.tar文件
  12. useradd - 创建新用户

    
    
    
    useradd username # 创建一个名为username的新用户
  13. passwd - 修改用户密码

    
    
    
    passwd username # 修改username用户的密码
  14. su - 切换用户身份

    
    
    
    su username # 切换到username用户身份
  15. chmod - 改变文件或目录权限

    
    
    
    chmod 755 file.txt # 设置file.txt文件的权限为755
  16. chown - 改变文件或目录的所有者

    
    
    
    chown username:username file.txt # 改变file.txt文件的所有者和群组为username
  17. df - 检查磁盘空间

    
    
    
    df -h # 显示磁盘空间使用情况(人类可读格式)
  18. du - 检查文件和目录的磁盘使用情况

    
    
    
    du -sh /home # 显示/home目录的总磁盘使用量(人类可读格式)
  19. top - 显示实时进程

    
    
    
    top # 显示当前运行的进程及其CPU和内存使用情况
  20. ps - 显示静态进程

    
    
    
    ps aux # 显示当前运行的所有进程
  21. kill -
2024-08-23



# 1. 查询当前活动的公共区域的所有规则。
sudo firewall-cmd --list-all
 
# 2. 添加一个新的服务,并允许其通过防火墙。
sudo firewall-cmd --permanent --add-service=my-new-service
sudo firewall-cmd --reload
 
# 3. 为特定的区域添加一个端口。
sudo firewall-cmd --permanent --zone=internal --add-port=8080/tcp
sudo firewall-cmd --reload
 
# 4. 删除之前添加的服务。
sudo firewall-cmd --permanent --remove-service=my-new-service
sudo firewall-cmd --reload
 
# 5. 为特定的区域添加一个接口。
sudo firewall-cmd --permanent --zone=external --add-interface=eth1
sudo firewall-cmd --reload
 
# 6. 为特定的区域添加一个IP地址。
sudo firewall-cmd --permanent --zone=dmz --add-source=192.168.1.0/24
sudo firewall-cmd --reload
 
# 7. 为特定的区域添加一个网络。
sudo firewall-cmd --permanent --zone=work --add-masquerade
sudo firewall-cmd --reload
 
# 8. 为特定的区域添加一个路由。
sudo firewall-cmd --permanent --zone=external --add-forward-port=port=80:proto=tcp:toport=8080
sudo firewall-cmd --reload
 
# 9. 为特定的区域添加一个ICMP类型。
sudo firewall-cmd --permanent --zone=home --add-icmp-block=echo-reply
sudo firewall-cmd --reload
 
# 10. 查询特定的区域是否允许某服务。
sudo firewall-cmd --zone=public --query-service=http
 
# 11. 更改默认区域。
sudo firewall-cmd --set-default-zone=internal
sudo firewall-cmd --reload
 
# 12. 查询当前区域的策略。
sudo firewall-cmd --zone=internal --list-all
 
# 13. 查询所有区域的策略。
sudo firewall-cmd --list-all-zones
 
# 14. 查询特定的区域是否允许某端口。
sudo firewall-cmd --zone=external --query-port=8080/tcp
 
# 15. 更改特定区域的接口。
sudo firewall-cmd --zone=external --change-interface=eth0
sudo firewall-cmd --reload
 
# 16. 更改特定区域的默认策略。
sudo firewall-cmd --zone=public --set-target=ACCEPT
sudo firewall-cmd --reload
 
# 17. 查询特定的区域是否允许某IP。
sudo firewall-cmd --zone=internal --query-source=192.168.0.0/24
 
# 18. 查询特定的区域是否启用了某种网络服务。
sudo firewall-cmd --zone=dmz --query-service=ssh
 
# 19. 查询特定的区域是否启用了某种ICMP类型。
sudo firewall-cmd --zone=home --query-icmp-block=echo-request
 
# 20. 查询特定的区域是否启用了某种防火墙特性。
sudo firewall-cmd --zone=work --query-masquerade

这个脚本提供了一个简化的视图,展示了如何使用firewall-cmd命令来管理Linux防火墙的不同方面。每个命令都有明确的注释,以便理解其用途和复杂性。这个例子涵盖了添加和删除服务、端口、接口、IP地址、网络、路由、ICMP类型和其他防火墙特性的操作。

2024-08-23

在Linux系统中,信号的处理机制涉及到信号的保存和递达。信号的保存是指在信号处理期间,如果当前信号处理还没有完成,新的相同信号到达时,如何处理。信号的递达是指信号从内核传递到进程的过程。

在用户空间,进程可以通过安装信号处理函数来处理信号。当信号发生时,内核会将信号添加到进程的信号队列中,并在适当的时候,如进程的内核态代码执行结束、用户态执行结束等,从队列中取出信号执行处理函数。

在内核中,信号的保存通常是通过一个位图实现的,用来标记哪些信号需要被保存和递达。内核会在处理信号时,对信号的保存和递达做相应的处理。

以下是一个简化的信号保存和递达的代码示例:




#include <signal.h>
#include <stdio.h>
 
// 信号处理函数
void sig_handler(int sig) {
    printf("Caught signal %d\n", sig);
    // 处理信号...
}
 
int main() {
    // 注册信号处理函数
    struct sigaction sa;
    sa.sa_handler = &sig_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sigaction(SIGINT, &sa, NULL);
 
    // 等待信号
    while(1) {
        pause(); // 暂停进程,直到信号到达
    }
 
    return 0;
}

在这个例子中,我们注册了SIGINT信号的处理函数sig_handler。当用户按下Ctrl+C产生SIGINT信号时,sig_handler会被调用来处理这个信号。如果在sig_handler执行期间,另一个SIGINT信号到达,它会被阻塞直到当前的信号处理完成。这是大多数Unix系统的默认行为,也是我们通常期望的信号处理方式。

2024-08-23

md5sum是一个在Linux系统中用来计算和校验UNIX或Linux系统下一个文件的MD5值的工具。MD5全称是Message-Digest Algorithm 5,一种广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value)。

使用方法:

  1. 计算文件的MD5值:



md5sum filename
  1. 校验文件的MD5值是否和指定的值相同:



md5sum -c filename.md5

其中,filename.md5是一个包含文件名和其对应MD5值的文本文件,格式如下:




MD5 (filename) = md5-checksum

例如,你有一个文件叫做example.txt,你可以使用以下命令来生成它的MD5值:




md5sum example.txt > example.txt.md5

然后,你可以使用以下命令来校验example.txt的MD5值是否和example.txt.md5文件中的值相同:




md5sum -c example.txt.md5

如果值相同,命令会输出:




example.txt: OK

如果值不同,命令会输出:




example.txt: FAILED

并且,md5sum命令会在校验失败时返回一个非零退出状态。

2024-08-23

在Linux中,可以使用signalsigaction函数来设置信号处理器。以下是使用sigaction函数设置信号处理器的例子:




#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
 
void handle_signal(int sig) {
    printf("Caught signal %d\n", sig);
    // 清理资源,停止程序等
    exit(0);
}
 
int main() {
    struct sigaction sa;
    sa.sa_handler = &handle_signal;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
 
    if (sigaction(SIGINT, &sa, NULL) == -1) {
        perror("sigaction");
        exit(1);
    }
 
    // 程序继续执行其他任务...
    while(1) {
        sleep(1);
    }
 
    return 0;
}

在这个例子中,程序设置了SIGINT信号(当用户按下Ctrl+C时产生)的处理函数handle_signal。当信号被捕获,它会打印出信号编号并退出程序。程序使用sigaction函数而不是signal函数,因为sigaction提供了更多的灵活性和信息。

2024-08-23



#include <stdio.h>
#include <stdlib.com>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
 
#define BUF_SIZE 30
 
int main(int argc, char *argv[]) {
    int sockfd;
    struct sockaddr_in servaddr;
    char buf[BUF_SIZE];
    int ret;
 
    if (argc != 3) {
        printf("usage: %s <IP> <port>\n", argv[0]);
        exit(1);
    }
 
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1) {
        perror("socket creation failed");
        exit(1);
    }
 
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(atoi(argv[2]));
    inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
 
    while (1) {
        printf("Enter message(q to quit): ");
        fgets(buf, BUF_SIZE, stdin);
        if (!strncmp(buf, "q", 1)) {
            break;
        }
 
        sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr*)&servaddr, sizeof(servaddr));
 
        ret = recvfrom(sockfd, buf, BUF_SIZE-1, 0, NULL, NULL);
        if (ret == -1) {
            perror("recvfrom error");
            exit(1);
        }
        buf[ret] = '\0';
        printf("Received message: %s\n", buf);
    }
 
    close(sockfd);
    return 0;
}

这段代码展示了如何使用UDP协议在Linux环境下创建一个简单的网络客户端。它首先检查命令行参数是否正确,然后创建一个UDP套接字。用户可以输入消息并发送到服务器,然后等待接收回应。如果输入“q”,客户端将退出。这个例子教导如何使用UDP套接字发送和接收数据,是学习网络编程的基础。

2024-08-23

以下是一个简化的部署V2rayA的步骤和示例代码:

  1. 安装Docker和Docker Compose。



sudo apt update
sudo apt install -y docker.io docker-compose
  1. 创建一个目录用于存放V2rayA的配置文件。



mkdir -p ~/v2raya/config
  1. ~/v2raya/config目录中创建一个.env文件,用于设置环境变量。



nano ~/v2raya/config/.env

文件内容示例:




V2RAYA_ADMIN_USERNAME=admin
V2RAYA_ADMIN_PASSWORD=admin
V2RAYA_API_USERNAME=api
V2RAYA_API_PASSWORD=api
V2RAYA_API_SECRET=api
V2RAYA_EMAIL=your_email@example.com
V2RAYA_DOMAIN=your_domain.com
V2RAYA_HOST=your_host_ip
V2RAYA_PORT=443
V2RAYA_LEVEL=0
  1. ~/v2raya目录中创建docker-compose.yml文件。



nano ~/v2raya/docker-compose.yml

文件内容示例:




version: '3'
services:
  v2raya:
    image: xjjdog/v2raya:latest
    container_name: v2raya
    environment:
      - V2RAYA_ADMIN_USERNAME=${V2RAYA_ADMIN_USERNAME}
      - V2RAYA_ADMIN_PASSWORD=${V2RAYA_ADMIN_PASSWORD}
      - V2RAYA_API_USERNAME=${V2RAYA_API_USERNAME}
      - V2RAYA_API_PASSWORD=${V2RAYA_API_PASSWORD}
      - V2RAYA_API_SECRET=${V2RAYA_API_SECRET}
      - V2RAYA_EMAIL=${V2RAYA_EMAIL}
      - V2RAYA_DOMAIN=${V2RAYA_DOMAIN}
      - V2RAYA_HOST=${V2RAYA_HOST}
      - V2RAYA_PORT=${V2RAYA_PORT}
      - V2RAYA_LEVEL=${V2RAYA_LEVEL}
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./config:/root/.config
    restart: unless-stopped
  1. ~/v2raya/config目录中,克隆V2rayA的配置仓库。



cd ~/v2raya/config
git clone https://github.com/v2rayA/v2rayA-config.git
  1. ~/v2raya目录中,使用Docker Compose启动V2rayA服务。



cd ~/v2raya
docker-compose up -d
  1. (可选)如果你想要更新V2rayA,可以进入~/v2raya/config目录,然后使用Git拉取最新的配置。



cd ~/v2raya/config/v2rayA-config
git pull
  1. (可选)如果你想要更新V2rayA的镜像,可以修改docker-compose.yml文件中的镜像标签,并重新启动服务。

以上步骤和代码提供了一个简洁的方式来部署V2rayA,并且能够通过Git来管理配置更新。

2024-08-19

在Linux中,进程是运行着的程序的一个实例。每个进程都有自己的地址空间,包括文本、数据和栈区域。进程也拥有自己的系统资源,如文件描述符和信号处理等。

在Linux中,可以使用ps命令查看当前系统的进程状态,ps -aux可以查看所有进程的详细信息,ps -ef可以以全格式显示所有进程。

例如,你可以使用以下命令来查看所有进程:




ps -aux

另外,你可以使用top命令实时查看系统中进程的资源占用情况。




top

如果你想要杀死某个进程,可以使用kill命令,后面跟上进程ID。




kill 1234

其中,1234是你想要杀死的进程的ID。

如果你想要以更强制的方式结束进程,可以使用kill -9,其中的-9表示SIGKILL信号,它会立即结束进程。




kill -9 1234

在编写C/C++程序时,可以使用fork()函数创建一个新的进程,exec()函数族用来执行新的程序。

例如,下面的C程序创建一个子进程,然后用exec()函数族来执行一个新的程序:




#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int main() {
    pid_t pid = fork();
 
    if (pid == -1) {
        // 错误处理
        perror("fork failed");
        exit(EXIT_FAILURE);
    }
    else if (pid == 0) {
        // 子进程
        printf("子进程 PID: %d\n", getpid());
 
        // 用 execlp 替换当前进程的映像,执行新的程序
        execlp("/bin/ls", "ls", (char*)NULL);
 
        // 如果exec函数调用成功,下面的代码将不会被执行
        // 如果exec调用失败,则可以在此处添加错误处理代码
        perror("execlp failed");
        exit(EXIT_FAILURE);
    }
    else {
        // 父进程
        printf("父进程 PID: %d\n", getpid());
        wait(NULL); // 等待子进程结束
    }
 
    return 0;
}

以上代码首先使用fork()创建一个子进程,然后在子进程中使用execlp()执行ls命令列出当前目录下的文件。在父进程中,使用wait()系统调用等待子进程结束。

这只是Linux进程的一个简单介绍,实际上进程管理在操作系统中是一个复杂且重要的部分,涉及到内存管理、进程调度等多个方面。