Leon Ding Blog - linux
type: channel
link: https://blog.leonding.me/tag/linux/
items: Java 原生化的未来 Graal AOT 编译器
items: SELinux 和 journalctl 工具
items: Java 虚拟机 JVM 内部设计
items: Linux 编译安装 PHP 环境
items: RIAD 磁盘冗余阵列
items: Linux 命令必知必会
items: 使用 RHEL 内核参数修改 Root 密码
items: 如何选择 Linux 发行版本
items: Linux 中 Shell 编程详解

Java 原生化的未来 Graal AOT 编译器
type: item
date: 2024-07-17T22:35:00+08:00
description: Java 这门语言与生俱来的显著特性就是“一次编译，到处运行”，这种功能得益于 JVM 平台的支持，Java 程序通常通过将其打包为 JAR 或 WAR 包，并依赖 JVM 和 Servlet 容器来运行。其底层运行时 JVM 采用 JIT（即时编译）模式来执行程序代码，JVM 会在运行时进行编译优化和动态执行代码，这通常会导致较高的内存占用。这样的好处是采用 JIT 可以热更新和热部署程序，并且 JVM 可以在运行期间对程序进行动态分析，来实时优化程序以达到最好的性能状态。Cloud Native 面临的问题随着云计算的发展，服务端程序的运行和部署方式发生了巨大变化，特别是在云原生（Cloud Native）场景下，服务器程序被打包成一个个容器运行。在这种环境下，传统方式容器化的 Java 程序面临着打包后的镜像文件过大的问题。镜像文件中需要包含 JRE 和各种第三方库，导致镜像体积庞大，占用更多的磁盘空间。目前云计算的计费方式也发生了改变，采用按需分配的实时计费方式，根据程序的内存占用和运行时间计费。这与传统 IDC 自托管式机房中长时间运行服务器程序形成鲜明对比，按需分配的计费方式显然更具性价比，因此优化 Java 程序在容器环境中的运行方式变得尤为重要。Serverless 面临的问题传统的 JVM 工作原理要求程序员先将编写的 Java 程序打包为 JAR 或 WAR 包，这是普通 Java 开发者所能接触到的程序编译和构建阶段。然而当程序运行起来之后，底层的 JVM 会进行许多复杂的操作，包括内存管理、垃圾回收、即时编译等。需要先启动 JRE 中的 JVM 来加载 Tomcat 服务器所需的字节码，再加载 WAR 包中的字节码文件到 Servlet 容器中运行服务，这个过程非常耗时。下图为整个传统 Java 程序从源代码到程序运行各个阶段的工作流程：下图为传统的 Java 运行时执行程序的生命周期，首先应用的开发者将 *.java 源代码编译为 bytecode 和 jar 依赖包通过 maven 构建打包为一个单独的 jar 包。当执行 java -jar xxx.jar 命令时，首先要启动 JRE 中的 JVM 程序，因为 JVM 本身也是一款单独程序对应着 $JAVA_HOME\bin 目录中的 java ，当 JVM 启动之后会在系统中创建一个进程，将要运行的 jar 程序包和 JRE 标准库中 class 文件加载入 JVM 内存中，并且找到 main 方法开始解释执行。当程序运行一段时间之后 JVM 充分获取了 Java 程序的一些执行数据信息，开始对程序进行 JIT 及时编译优化程序，当程序被 JIT 优化之后的程序才能达到和 C/C++ 这种直接编译为 Native Code 程序的性能。在云计算推崇的 Serverless 架构场景下，Java 的 JIT 模式并不适合，Serverless 应用程序需要能够快速启动以响应事件驱动的请求，并且在空闲时自动关机销毁，释放在服务请求期间所使用的内存。然而，这种需求与传统的 Java 程序运行模式背道而驰，使得 Java 在 Serverless 场景中显得不适用，这就是被业界称为的 冷启动 问题。为了解决这一痛点，Oracle Labs 推出一款新的 JDK 产品 GraalVM JDK ，相比传统的 JDK 该产品内置 Java 静态编译工具和一款新的虚拟机，和传统的 JVM 不一样 GraalVM 是支持多语言进行混合编程的虚拟机，这也是它一大亮点。GraalVM 中的静态编译工具不仅是支持将 Java 编译为二进制可执行文件，还支持 JavaScript 和 Python 等其他语言的编译优化功能，本文只关注于 GraalVM 对 Java 程序进行 AOT（Ahead-Of-Time）编译的解决方案。使用 GraalVM 对 Java 程序进行 AOT 编译的解决方案，可以显著缩短启动时间并降低内存占用，使 Java 程序更适合在 Serverless 环境中运行，通过 AOT 编译，编译器生成一个 Native Code 二进制文件，即对应平台架构的机器代码程序。这种方式无需像 JIT 那样依赖于 JVM 运行，在内存和磁盘占用上有显著改善。下图为 AOT 编译工作流程，在编译阶段会程序进行静态分析，通过它内置工具分析 Java 源代码中依赖关系，将其所有依赖和代码执行逻辑都进行提前编译为机器代码，缺点也很明显可能会失去在 JIT 模式下的动态反射功能。如上图，在 AOT 模式下将在运行时的过程放到在程序构建阶段，构建阶段会对 Java 程序执行静态代码分析和依赖可达性分析，将其所有的依赖软件包都编译生产所属平台对应的可执行二进制文件。AOT…

SELinux 和 journalctl 工具
type: item
date: 2023-03-17T19:05:00+08:00
description: [scode type="lblue"]传统的 Linux 安全机制靠着默认的用户权限、所属组、其他组、 ACL 等功能来实现权限控制，而目前还有另外一套安全机制 SELinux 机制来管理系统安全性，相比默认的权限控制 SELinux 的机制更为强制，默认的用户权限是靠着用户或者超级管理员设置和管理，而 SELinux 强制访问控制机制是由操作系统内核强制实施的，从而使系统更加安全。如果开启了 SELinux 每当操作的时候，SELinux 都会检测是否进程系统调用和网络套节字合法，如果不符合 SELinux 默认的权限就会被拒绝和终止。[/scode]SELinux 提供了一种安全的策略语言，管理员可以使用它来定义系统安全策略。这种策略语言是相当复杂的，但是可以通过使用预定义的策略模块进行简化。这些策略模块是一组预定义的规则集，可以保护常见的应用程序和服务，如 Apache Web 服务器、MySQL 数据库等。总的来说，SELinux 可以帮助管理员保护系统免受恶意攻击和安全漏洞的影响，从而提高系统的安全性和稳定性。然而，由于 SELinux 是一种高级的安全机制，其配置和管理需要一定的技能和经验。一般情况下很少自己起编写 SELinux 的安全策略文件，只会临时或者配置 SELinux 默认的安全策略级别信息，SELinux 配置文件路径 /etc/selinux/config 中，目前很多发行版本已经默认启动该功能。级别说明enforcing默认启动，强制实行安全策略，如果不符合要求就会被禁止permissive该级别会提示用户操作不符合安全策略，但是不会拒绝操作disabled直接禁止功能，因此也不会占用系统资源而策略文件存放在 /etc/selinux/targeted/policy 中，是针对系统的安全策略进行定义的文件。SELinux 有两大策：域（domain）的概念允许定义哪些进程可以访问某些文件和目录；上下文 (context) 默认会给每个系统资源文件设置一个标签，而 SELinux 安全功能就要根据策略文件来检测进程和上下文的关系，从而来控制哪些进程可以访问什么资源。# 查看进程域 ps -Z # 查看资源上下文 ls -Z # 查看目录 ls -Zd /xxx/dir # 查看 selinux 状态 sestatus[scode type="yellow"]在 SELinux 上下文包括以下字段： user（用户）、role（角色）、type（类型）和 security level（安全级别），例如有一个策略规则允许 Apache作为 httpd_t 运行的 Web 服务器进程，访问通常位于 /var/www/html/ 和其他 Web 服务器目录中上下文的文件和目录 httpd_sys_content_t ，但是策略中没有允许规则适用于通常位于 /mysql 和 /data/msyql/ 中的文件，因此不允许访问，即使 Apache 被破坏，一个恶意的脚本可以访问它，也无法访问 /data/msyql/ 目录 。[/scode]因为有默认安全规则配置文件的存在，创建新文件或者移动文件修改文件会导致进程域和上下文不相符的情况，SELinux 默认就会拒绝此类操作导致不符合预期的效果，例如把 nginx 默认的网站目录设置为其他目录导致无法正常运行。此时就要使用下面命令修改进程上下文，使得 nginx 能正常访问到文件：semanage fcontext -a -t httpd_sys_content_t /wwwroot semanage fcontext -a -t httpd_sys_content_t /wwwroot/* # 如果是网络描述符资源，例如端口上下文 semange fcontext -a -t http_port_t -p tcp 8080 # 生效刚刚到修改 restorecon -Rv /wwwroot # 查找符合 http 端口 semanage port -l | grep http[scode type="yellow"]SELinux 默认提供多个命令可以协助帮助设置权限和查看 SELinux 目前运行状态和参数信息：[/scode]命 令作用说明setenforce临时修改 SELinux 状态getenforce获取当前系统 SELinux 状态getsebool [-a]查询 SElinux 策略内各项规则的布尔值setsebool [-P]设置策略并且永久生效修改之后 nginx 进程就能成功访问到 /wwwroot 目录中的文件了， SELinux 没有阻挡读取文件的请求，SELinux 修改的日志相信会存储在 /var/log/audit/audit…

Java 虚拟机 JVM 内部设计
type: item
date: 2023-03-09T23:06:00+08:00
description: 大多数开发者或多或少都使用过 Java 这门编程语言，Java 这门编程语言最大的特性就是一次编写到处运行，这就使得开发者在编写了 Java 源代码之后通过 Java Compiler 编译出来的程序就可以在不同平台架构上运行。不管是 x86 还是 ARM 的 CPU 都运行正常无误，熟悉计算机 CPU 架构都知道不同 CPU 核心使用的不同架构和指令集，如果想要编写一次程序到处运行那就得需要使用交叉编译来完成，但是 Java 打破这一点，这得益于 JVM 的存在，Java 源代码不是将源代码直接编译成为对应平台机器码，而是自己定义一套指令集规则也就是对应的 Java Bytecode 标准，再通过将其字节码文件放到 JVM 上运行，最终 JVM 充当一个翻译员将其通过 JIT 的方式运行程序。[scode type="green"]JVM 有自己完善的硬体架构，如处理器、堆栈、寄存器等，还具有相应的指令系统。JVM 屏蔽了与具体操作系统平台相关的信息；本质上就是对现有的物理硬件的软件抽象的实现，可以作为一种编程语言的虚拟机，实际上不只是专用于 Java 语言，只要生成的编译文件符合 JVM 对加载编译文件格式要求，任何语言都可以由 JVM 编译运行。目前实现这些标准虚拟机有很多，例如 HotSpot 、 JRockit 、 IBM OpenJ9 、 GraalVM 这些都是相关的虚拟机实现产品。[/scode]Java 跨平台原理编写 Java 程序的源文件都是以 .java 为后缀名的文件，下面则为一个 Java 源代码文件要想运行它必须通过 Java 编译器来生成对应的字节码 .class 文件，从而让不同平台的 JVM 加载 .class 文件来运行程序：这里值得注意的是 Java 现在每 6 个月就有一次更新，每次都会有新的语言特性添加，不同版本的 Java 编译器可能生成的代码文件在不同 JVM 有不同效果，例如低版本的 JVM 不能运行高版本的 Java 编译器生成的 .class 文件，反过来则是可以的，不过这些都是小问题可以通过 AOT 编译成对应平台机器码运行，也可以使用一些第三方提供程序版本代码迁移工具 EMT4J 来完成。在 JDK 整个开发工具包中其实有两套编译器，大多数程序员所使用的 javac 编译器，此编译器只是将编写的 java 源文件编译生成为 JVM 能认识的字节码；而在 JVM 中又有一套 JIT 编译器，针对的是更高性能程序场景使用的，会把字节码再次编译成为机器码。JVM 主体架构当 Java 程序需要运行的时，此时就得需要 JVM 了，JVM 内部大致会和下图接近，首先前面通过 Java Compiler 生成的 .class 文件会把加载到虚拟机内存中，首先头一次执行是通过 JVM 内置 Interpreter 解析执行代码，这个过程 JVM 的解析器会把字节码里面指令翻译成对应平台的指令进行运行。另外 JVM 中内置另外 2 个 JIT Compiler 分别为 C1 和 C2，这两个即时编译器是针对长时间运行的热点代码进行优化的编译器，JVM 的设计者在设计的就考虑到一些程序代码运行效率的问题，前面提到的通过解析器执行代码性能肯定不能和 C 这种原生编译成机器码的程序性能相比，所以设计者针对热点代码会采用 C1 和 C2 编译器进行编译较为底层次的机器码来执行。[scode type="yellow"]使用解释器执行时，当某一行代码被执行了几次，这行代码会被打上 warm 的标签，当某一行代码被执行了很多次，这行代码会被打上 Hot🔥 的标签成为热点代码，这和 JVM GC 分代设计方式类似，通过分代来解决不频繁 GC 放到老年代。[/scode]在运行时将热点函数编译为汇编代码，当程序再次运行到经过实时编译的函数时，就可以执行经过编译和优化的汇编代码，而不再需要解释执行了。由于编译是在运行时进行的，因此 JIT 编译器可以获得代码实际运行的路径、热点和变量值等信息，基于此可以做出非常激进的编译优化，从而获得执行效率更高的代码。何为热点代码？例如下面有一段代码就为热点代码，当然现实中程序热点代码可能更为复杂：public class HotSpotExample { public static void main(String[] args) { long startTime = System.currentTimeMillis(); int iterations = 100000000; for (int i = 0; i < iterations; i++) { // 热点代码块 int result = compute(i); if (result % 2 == 0) {…

Linux 编译安装 PHP 环境
type: item
date: 2023-03-09T18:48:00+08:00
description: 最近打算把博客基础环境迁移到 typecho ，其实在 2017 年为的博客就是使用 typecho 搭建的，但是 2019 年考虑到动态网站并且还是基于 php 的博客系统的安全性问题，我就迁移到了静态博客系统 hexo 上，最后 2020 年又迁移到 hugo 上，虽然静态博客系统可以抵抗 xss 反射和 xss 持久化攻击，但是部分功能目前满足不了我，决定迁移会到 typecho 系统上，本篇博客记录一下如何配置 php 运行环境。php-fpm 环境作为一个基本的动态的 web 服务来说必须有要数据库和 http 服务器支持，所以这里就诞生了一些基于开源软件的解决方案，例如 LNMP 的架构，php 本身只是一个动态类型的脚本语言不能作为 http 服务器，这里通过将 php-fpm 和 nginx 整合到一起来提供动态网站的服务。nginx 和 postgresql 服务器采用通过 rpm 软件包的方式安装，相比于通过源代码编译安装的方式要简单多一点，也不需要等待很长的编译时间，而 php-fpm 为了稳定性采用源代码的方式进行编译安装，首先运行下面命令：# 安装 nginx yum install -y nginx相对于 nginx 而 postgresql 数据库安装要复杂，postgresql 目前有很多版本，安装要去官方网站查询对应的版本，并且还需要设置最新的 yum 仓库信息：# 安装 postgresql # Install the repository RPM: sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm # Disable the built-in PostgreSQL module: sudo dnf -qy module disable postgresql # Install PostgreSQL: sudo dnf install -y postgresql15-server # Optionally initialize the database and enable automatic start: sudo /usr/pgsql-15/bin/postgresql-15-setup initdb sudo systemctl enable postgresql-15 sudo systemctl start postgresql-15nginx 和 postgresql 配置完成之后，接下来将需要进行编译安装 php-fpm 环境，先要解决相关依赖包问题，如何下载 php8 最新版本源码包：# 安装依赖的软件包 sudo yum groupinstall "Development Tools" # 下载 php8 的源码包 wget https://www.php.net/distributions/php-8.2.3.tar.gz # 解压源代码和进入目录 tar zxf php-8.2.3.tar.gz && cd php-8.2.3接下来要对 php-fpm 进行源代码编译安装，首先我们要对进行参数设置支持数据库模块，这里要支持 psql 模块，如果使用的是 mysql 使用 --with-mysql 参数，需要指定 psql 的安装目录 :./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc --with-pdo-pgsql=/usr/pgsql-15 --with-pgsql=/usr/pgsql-15 --with-freetype --with-jpeg --with-zlib --enable-bcmath --enable-shmop --enable-sysvsem --with-curl --enable-mbstring --with-openssl --with-mhash --enable-pcntl --enable-sockets --with-ldap-sasl --with-xmlrpc --enable-soap --with-gettext --enable-fpm --with-zip --enable-gd --with-webp在此过程中会不断检测依赖软件关系和版本，如果遇到版本较低软件可以手动安装和更新，不知道包在 yum 仓库的完整包名可以使用 search 查看：如果默认 yum 不能正常搜索到软件包，可以尝试手动下载对应的软件包安装，第…

RIAD 磁盘冗余阵列
type: item
date: 2023-03-03T11:23:00+08:00
description: 传统保存备份数据的方式是把某个数据文件拷贝到多个磁盘上保存多个副本，或者采用云盘的方式存储，而在 Linux 中通过一个类似于的功能，可以将多块物理磁盘组成一个逻辑的磁盘单位使用，RAID 代表独立磁盘冗余阵列或廉价磁盘冗余阵列，RAID 的目的是将文件的数据分布在多个磁盘上，这样单个磁盘故障就不会丢失该数据。RAID 技术在计算机中最重要的就是数据，而数据在持久化之后就会被存储到硬盘上，此时对硬件质量和安全性就提出更高要求，例如如果硬盘出现故障之后数据就无法被正常读取导致丢失，RAID 技术就简单来说就是把多块硬盘组成一个整体，从而提升数据可靠性和读写效率问题，缺点明显就是浪费多空间。目前实现 RAID 技术有两种方案，一种软件的方式来实现，另外一种通过硬件的方式，很多在线商城可以购买到支持 RAID 硬盘阵列盒子 有物理设计支持；共同的特点是就是需要多块磁盘，最低需要为 2 块磁盘，不同的 RAID 方案有不同磁盘个数要求。RIAD 0 级别最少需要 2 块硬盘，安全性低，数据依次写入到所有的硬盘中，不具备备份数据和容错能力，其中一块出现异常整个数据就会受到影响，数据可以并行读取和写入不同磁盘中。RIAD 1 级别最少需要 2 块硬盘，安全性高，数据同步写入到所有的硬盘中，数据被冗余存储在多个硬盘中，有一块硬盘可用数据就不会受到影响，以 2 块硬盘为例空间利用率只有 50% ，但是读取数据性能会提升。RIAD 5 级别最少需要 3 块硬盘，和前面方式不同的是采用一种经过数学上一种奇偶数校验来到达数据的完备性，会把真实数据依次存储在不同硬盘中，并且将数据的奇偶数信息存储在不同的硬盘中，当某块硬盘出现问题时，可以通过奇偶数校验反向还原出来原始的数据信息，此种方案能有效提高硬盘利用率和读写效率，也是数据安全性高的。RIAD 1-0 级别是组合了 RIAD 0 和 RIAD 1 两个级别的产物，先对数据采用 RIAD 1 的方式来存储，最后再将其使用 RIAD 0 的方式组合，形成了高可读写和高数据完备性的方案，只要不是损坏的同一阵列的硬盘，那么最高可允许 50% 硬盘损坏而还能正常提供服务。RIAD 的级别远不止这么多，但是最为常用也就这几个，目前使用最多还是 RIAD 5 和 RIAD 10 级别能提供读写性能也能提高数据的安全性，至于怎么创建磁盘阵列可以查看 mdadm 命令。其他资料Virtual Data OptimizerStandard RAID levels软件 RAID 配置 | 储存管理指南 | SUSE

Linux 命令必知必会
type: item
date: 2023-02-03T13:55:00+08:00
description: 我个人接触 Linux 比较早，最开始喜欢研究网络安全相关的话题，所以第一次使用的 Linux 系统是 Kali Linux，虽然现在有很多的 Linux 发行版本，但大多都是还是使用命令行进行操作的。和 MacOS 不同 Linux 大部分软件生态还是没有 Apple MacOS 完整，这里只的是图形界面和第三方公司开发的软件，而且大部分软件都是一些命令行下的软件，作为一名开发者都有必要掌握一些基础的 Linux 操作命令，这些都是类 Unix 系统，大部分基础命令是相通的，所以介绍同样常用的命令。代替鼠标的命令在 Windows 很少有人使用的 DOS 命令行进行操作，但是在 Linux 下最为常见的是使用命令行，当然 Windows 也可以完全使用的 CMD 命令进行操作来控制电脑，但是大部分人还是使用视窗界面和鼠标。如果计算机操作系统没有图形化界面那么估计到现在还没有普及起来呢。最为常见为目录切换和文件查看，文件和目录创建、文件移动和文件复制、文件下载和文件编辑等操作，下面介绍：# 使用 cd 可以切换目录 cd /home/auula # 返回上一层目录 cd .. # 使用相对路径切换 cd ../../xxx # 快速返回到家目录 cd ~创建文件和创建目录：# 创建一个文件 touch Hello.java # 更新一些文件最后访问时间 touch -d Hello.java # 创建一个目录 mkdir /home/xxxx # 递归创建目录 mkdir -p /home/a/b/c文件移动和创新命名都为同一个 mv 命令：# 将目录a到b中 mv /aaaxx/a /bbbxx/b # 重新命名 mv a.tar b.tar文件复制操作：# 将a.txt文件复制到b目录中 cp /xxxx/a.txt /xxx/b # 使用递归复制 cp -r /xxx/aaa/*.txt /xxx/bbb/从远程的网络服务器上下载程序压缩包，可以有很多种方式，最常见上 wget：# wget 下载文件 -b 后台运行 -c 支持断点续传 wget -b -c https://blog.ibyte.me/mirror/trojan-install.sh查看当前工作目录的位置，和当前命令下有什么文件：# 当前位置信息 pwd # 查看当前目录下有什么文件，包括隐藏文件 ls -al查看某个文件内容，如果文件内容太多可以分页查看：# 查看某个文件的内容 cat /xxx/Hello.java # 通过分页查看某个文件的内容 more /xxx/Hello.java当在一个多层次顶层目录中，查看当前目录下的所有子目录：# 查看当前目录，打印目录结构树 tree .查看文件属性信息和文件夹属性信息：# 查看文件属性信息 file Hello.java # stat 查看文件夹和文件信息 stat directory对文本文件内容高级操作：# 查看文件的行数和字节树 wc -l /etc/passwd # 替换文件内容的字符串 cat Hello.java | tr S X对文件内容进行匹配过滤，和比较两个文件内容差异：# 查看符合批评 root 字符串的内容 cat /etc/shadow | grep root # 查看两个文件内容的差异 diff -brief a.java b.java在 Linux 系统中所有的东西都被抽象成了文件，所以如果要删除某个文件得注意！删除文件和目录命令如下：# 删除某个目录，如果目录中有其他文件夹和文件会交互式删除 rm /xxxx # 强制删除，通配符 rm -rf /xxxx/*.go在 Linux 中安装软件传统的方式上通过源代码的方式进行编译安装，这种方式要求管理员自己解决各个软件包的依赖关系，还有一种方式采用的不同 Linux 发行版本中提供软件包管理工具来管理软件。目前为两大主流的发行版本，基于 Debian 和 Redhat 版本的，对于量大不同的包管理工具 deb 和 rpm，这里为主要介绍 rpm 的方式：# 安装某个 rpm 软件包 rpm -ivh xxxx.rpm # 查找安装目录 rpm -ql package | grep bin # 查找某个全包名 rpm -qa | grep java # 卸载某个软件包 rpm -y remove package 在命令行模式没有图形化界面来查看时间，如果需要查看当前系统时间，可以使用 date 命令：# 格式化输出当前系统时间 date "+%Y-%m-%d %H:%M:%S %p" # 当前已经过去多少天 date "+%j" # 设置当前系统时间 date -s "20221101 8:30:00" # 设置时区 time…

使用 RHEL 内核参数修改 Root 密码
type: item
date: 2023-01-10T12:47:00+08:00
description: 大部分商用服务器都使用类似于 Redhat Enterpris Linux 版本的 Linux 系统作为服务器运行环境，Linux 是允许多个用户远程登录操作的系统。部分企业的 Linux 服务器可能运行时长很长，数年之久，而大多数时采用是普通用户进行管理运维的，而相对于 Root 超级管理员用户则是配置系统关键环境和更新系统、安装更新软件包时所需要用到，如果时间长或者前一任管理员离职了，Root 超级管理员用户密码没有对接或者忘记就需要重置 Root 超级管理员用户的密码。部分 Linux 发行版本切换到 Root 超级管理员用户会提示一句话: 权限越多，责任越大！ 可见 Root 超级管理员用户重要性。目前重置 Root 用户的密码方案适用于类 Redhat Enterpris Linux 发行版本的操作系统，例如 CentOS 系统。重置密码使用如下命令，查看系统是否支持此博文介绍的重置密码方法：[root@localhost ~]# cat /etc/redhat-release CentOS Stream release 9 [root@localhost ~]#如果你是在物理服务器机架上，可以把显示器和键盘接上服务器设备上，而对应部分使用的公有云服务商的 VPS 可以在管理页面启动 VNC 进行连接管理。重启服务器在停留在开机页面时，按下键盘上的 E 键，会进入内核信息修改页面，找到 linux 开头哪一行的末尾处加 rd.break 参数， 然后按住 Ctrl + X 组合键确认修改。系统过几秒钟就会刷新进入到紧急救援模式，在命令行中输入一下命令：mount -o remount,rw /sysroot chroot /sysroot passwd touch /.autorelabel整个过程如下截图，会提示输入新的 Root 账号的新密码，如果密码字符串组合很简单，会意思密码过于简单，不允许被设置。最后连续按住键盘上的 Ctrl + D 组合按键，系统会退出重启，最后输入新密码登录到系统完成重置。

如何选择 Linux 发行版本
type: item
date: 2023-01-08T14:54:00+08:00
description: 作为一名极客肯定会使用 Linux 操作系统，并且作为一名合格的程序员应该必须会使用 Linux 操作系统，Linux 是泛指一些基于 Linux Kernel 二次开发的操作系统，目前当今世界上有很多的 Linux 发行版本，那么小白程序员如何选择一个适合自己的 Linux 操作系统呢？这篇文章笔者就会重点介绍一下。作为一名后端程序员的会我推荐是使用基于 RedHat 衍生出来的发行版本，RedHat 是当今世界上最成功的开源软件公司，其最初的发家核心软件产品就是 RedHat Enterprise Linux ，这是基于 Linux Kernel 内核开发出常用商用操作系统，很多的商用公司都在使用这款操作系统，该系统有稳定保证还有配套一些商用技术服务支持的，也有 RedHat 公司整个软件生态的支持。红帽公司为了提升他们产品在 Linux 发行版本中独特性，还设计一套完善认证课程体系，例如：初级的 RHCSA 、中级的 RHCE 、 高级的 RHCA ，如果作为一名程序员能考取这方面的职业技能证书，那么就可以证明自己在 Linux 运维管理方面有很高的技术技能，相应的在职场上技术能力高度最好体现。发行版本首先介绍就是 Oracle Enterprise Linux 发行版本，这个是由 Oracle 公司维护并且提供商业化技术支持 Linux 企业发行版本，和 RedHat Enterprise Linux 软件生态完全兼容。CentOS 是另外一个社区免费企业级 Linux 发行版本，因为 Linux Kernal 是使用 GNU 通用公共许可证（GPL） 发布源代码，因此任何人都可以运行、研究、修改和重新分发源代码，而 CentOS 则是按照相关法律条文合法合规的基于 RedHat Enterprise Linux 源代码发行的社区免费版本，主要就是移除一些 RedHat 的商标，软件生态和 Oracle Linux 和 RedHat Enterprise Linux 相互兼容。另外一个企业级为德国 SUSE 公司提供的 OpenSUSE Enterpris Linux 版本，也是提供的企业级 Linux 技术支持的服务的公司，SUSE Linux Enterprise 产品比上游 openSUSE 接受了更严格的测试社区产品，目的是只有成熟、稳定的包含组件的版本才能进入发布的企业产品。Ubuntu 是基于 Debian 以桌面应用为主的 Linux 发行版，也有 Server 版本但是大部分还是以桌面版本为主，主要产品面向个人电子产品的，有智能手机和智能电视系统，也提供一些付费的技术服务支持业务。这里 Ubuntu 主打的个人 PC 设备桌面操作系统，而上面的 RedHat Enterpris Linux 和 Oracle Enterpris Linux 、 CentOS Enterpris Linux 、 SUSE Enterpris Linux 都针对大型商用服务器市场的，面向都是数据中心的超级计算机的操作系统，和 Ubuntu 最大区别就是软件安装的方式，Ubuntu 有 GUI 的应用商店来下载安装应用程序，而后者企业级大部分是不使用图形界面进行操作的，而是终端设备连接到服务器进行运维管理。如果是个人作为开发机使用的推荐使用 Ubuntu 发行版本，而如果企业级推荐 Enterpris Linux 因为这些包管理工具和软件大部分都是兼容的，在 Linux 系统上早期版本软件的方式是通过软件源代码进行编译安装的，要解决很多依赖关系问题，而针对这些大部分企业发行版本采用的是基于 RPM 的 YUM 、DNF) 软件包管理工具，不同发行版本修改其软件源即可。其他资料如何选择适合的 Linux 发行版？什么是 Linux？ | Linux 新手课程为什么很多大佬在使用Linux？

Linux 中 Shell 编程详解
type: item
date: 2022-04-25T16:02:00+08:00
description: 什么是 Shell？Shell 这里指的是 Uinx 中 Shell 解释器，而不是某跨国公司品牌的 shell 名称，这才使得人搞混了。在常用的 Linux 系统中 Shell 是一种介于系统内核和用户之间的命令解释器程序，用户可以通过输入命令通过 Shell 解析器执行命令从而达到操作计算机内核作用。如果经常使用类 UNIX 系统的话，如果掌握 Shell Script 会大大提高一下工作效率，常用的系统资源管理自动化操作，都可以使用编写 Shell 脚本来完成，而且好处是大多数操作系统默认都有自带的解释器。每个操作系统的默认自带的解释器都有很多种，可以通过下面这个命令来查看支持的解释器列表：$: cat /etc/shells # List of acceptable shells for chpass(1). # Ftpd will not allow users to connect who are not using # one of these shells. /bin/bash /bin/csh /bin/ksh /bin/sh /bin/tcsh /bin/zsh #我默认使用的这个，功能强大于普通bash /usr/local/bin/zsh最常用的解释器也就是/bin/bash，下面可以编写一个简单的脚本，内容如下：#!/bin/bash echo "Hello Shell Script！" # 执行会打印这句话变量的使用在 Shell 脚本中也有变量的概念，也内置一些变量方便编写脚本的时候使用，例如$HOME、$USER、$PWD、$SHELL... 在 Shell 脚本中的变量也简单，没有类型系统所有数据都字符串类型，无法参入运算，但是有区分只读静态变量，如下：#!/bin/bash variable = "这是一个普通的变量" echo $variable readonly immutable = 1024 # 只读不可变 zsh: read-only variable: immutable unset variable # 取消设置的值 echo $variable如果需要把当前脚本文件里面的变量导出给其他脚本使用的话，那就需要将变量导出为全局变量，使用关键字 export ：#!/bin/bash GLOBAL = "全局变量" export GLOBAL这样在其他的 Shell 环境变量就可以访问到这个变量了。特殊变量 $n 这里的 n 表示数字，从 0 开始的可以是很多个，但是 1-9 可以使用 $n ，但是超过之后访问其值必须加上大括号 ${10} 这样才能访问到，一般这使用与脚本文件外部传入参数获取使用。另外一个如果需要得到外部传入参数个数需要使用 $# 它返回就是参数个数。如果需要获取全部输入的参数直接使用 $@ ，它就获取到所有传入的参数。#!/bin/bash echo "args length: $#" echo "$0 $1 $2" args=("$@") echo "first : ${args[0]}" echo "second : ${args[1]}"output:$: sh shell-args.sh 1 2 3 args length: 3 shell-args.sh 1 2 first : 1 second : 2还有一个比较特殊的 $? ，它可以检查上次执行命令是否出错，它会检查上次命令执行返回结果，如果结果为 0 则表示正常运行退出，反之则认为是程序非正常退出，当然退出错误码可以自定义，例如修改一个不可变变量：#!/bin/bash readonly immutable=1024 echo $? #0 immutable=2048 echo $? #1运算符上面介绍 Shell 脚本中变量的使用，但是变量的缺点就是没有类型系统，所有的变量都是字符串如果需要进行计算那么就不可能的。为了解决数值运算的问题，在 Shell 中运算使用的关键字 expr 命令，例如 expr n + x 加法计算。expr 命令是一个手工命令行计数器，用于在 UNIX/LINUX 下求表达式变量的值，一般用于整数值也可用于字符串，运算的时候用空格隔开每个项，特殊字符需要转义的使用 \ ，对包含空格和其他特殊字符的字符串要用引号括起来。#!/bin/bash expr 10 + 10 #加法计算 expr 20 - 10 #减法计算 expr 10 \* 10 #乘法计算 expr 50 / 5 #除法计算 expr 8 % 7 #取余计算特殊的字符串运算：#!/bin/bash expr length "text content" # 计算长度 12 expr substr "thi…