2022年10月

这是 Xubuntu 22.10 Kinetic Kudu 及其新功能的快速总结。

Xubuntu 22.10 桌面

质量需要时间来建立。它适用于生活的各个方面,包括软件。

自 Xfce 4.16 发布以来,Xfce 4.17(开发版)已经被添加了许多新功能。这包括核心 Xfce、原生应用,GNOME 43、MATE 1.26 和 libadwaita。由于 Xfce 也是 GNOME 和 MATE 的组合,正确地合并和测试这些更改需要时间。

在 Xubuntu 22.10 Kinetic Kudu 版本中,你将体验到自 2020 年 12 月以来所做的所有改进:将近两年的错误修复和增强。

让我们快速查看一下时间表。目前,Xubuntu 22.10 beta 已经发布,并正在测试中(本问末尾提供了 ISO 链接)。最终版本预计于 2022 年 10 月 20 日发布。

Xubuntu 22.10 新功能

核心更新和 GNOME 框架

在其核心,Xubuntu 22.10 同其基于的 Ubuntu 22.10 一样,采用 Linux 内核 5.19。另外,Xfce 桌面版本是 Xfce 4.17。

4.17 版本是一个开发版,因为它是下一个大版本 Xfce 4.18 的基础,该版本 计划在今年圣诞节发布

让我们谈谈 GNOME 和相关应用。 Xubuntu 22.10 中的 Xfce 4.17 首次获得了带有 GNOME 43 更新的 libadwaita。这意味着默认的 GNOME 应用程序可以在 Xfce 桌面下正确呈现。

这就是说,GNOME 软件应用 Software 43 在 Xubuntu 22.10 的 Xfce 桌面下看起来很棒。如果你将其与 Xfce 原生外观和带有 CSD/SSD(例如 “ 磁盘应用 Disk ”)的 GNOME 应用进行比较,它们看起来都很顺眼。

我对 GNOME 软件应用 43 在 Xfce 桌面下的 libadwaita/GTK4 渲染效果如此之好感到惊讶。

在 Xubuntu 22.10 中一起使用三种不同的窗口

Xfce 应用

Xfce 桌面带来了自己的原生应用集。在此版本中,所有应用都从 4.16 升级到 4.17 版本。

值得注意的变化包括:Xfce 面板获得了对任务列表插件的中键单击支持,和托盘时钟中的二进制时间模式。PulseAudio 插件引入了一个新的录音指示器,可以过滤掉多个按钮按下事件。

Thunar 文件管理器获得了大量的底层功能和错误修复。如果你将 Thunar 4.16 与 Thunar 4.17 进行比较,它是变化巨大的。更改包括更新的上下文菜单、路径栏、搜索、导航等。你可以在 此处 阅读 Thunar 的所有更改日志。

此外,截屏应用 ScreenShooter 默认支持 WebP。蓝牙管理器 Blueman 在系统托盘新增配置文件切换器,并更新了 Catfish 文件搜索工具。

这是 Xfce 应用版本的更新列表和指向其更改日志的链接(如果你想进一步挖掘)。

外观和感觉

默认的 elementary-xfce 图标集(浅色和深色)得到了更新,带有额外的精美图标,让你的 Xfce 桌面焕然一新。默认的 Greybird GTK 主题对窗口装饰进行了必要的改进,并添加了 Openbox 支持。

你可能会注意到的重要且可见的变化之一是 ALT+TAB 外观。图标更大一些,眼睛更舒适,可以在深色背景下更快地切换窗口。

在 Xubuntu 22.10 的 elementary-xfce 中更新的图标集示例

ALT TAB 有更大的图标

上述更改使默认应用与其所基于的 Ubuntu 22.10 版本 保持一致。以下是 Xubuntu 22.10 中的更改概括。

概括

  • Linux 内核 5.19,基于 Ubuntu 22.10
  • Xfce 桌面版 4.17
  • 原生应用全部更新到 4.17
  • 核心与 GNOME 43、libadwaita、GTK4 保持一致
  • MATE 应用程序升级到 1.26
  • Mozilla Firefox 网页浏览器 105.0
  • Thunderbird 邮件客户端 102.3
  • LibreOffice 7.4.4.2

总结

Xfce 桌面最关键的整体变化将在 4.18 版本中到来。例如,最初的 Wayland 支持、更新的 glib 和 GTK 包。如果一切顺利,你可以在明年 4 月发布的 Xubuntu 中期待这些最好的变化。

最后,如果你想试用,可以从 这个页面 下载 Beta 镜像。


via: https://www.debugpoint.com/xubuntu-22-10-features/

作者:Arindam 选题:lkxed 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

微服务遵循领域驱动设计(DDD),与开发平台无关。Python 微服务也不例外。Python3 的面向对象特性使得按照 DDD 对服务进行建模变得更加容易。本系列的第 10 部分演示了如何将用户管理系统的查找服务作为 Python 微服务部署在 Kubernetes 上。

微服务架构的强大之处在于它的多语言性。企业将其功能分解为一组微服务,每个团队自由选择一个平台。

我们的用户管理系统已经分解为四个微服务,分别是添加、查找、搜索和日志服务。添加服务在 Java 平台上开发并部署在 Kubernetes 集群上,以实现弹性和可扩展性。这并不意味着其余的服务也要使用 Java 开发,我们可以自由选择适合个人服务的平台。

让我们选择 Python 作为开发查找服务的平台。查找服务的模型已经设计好了(参考 2022 年 3 月份的文章),我们只需要将这个模型转换为代码和配置。

Pythonic 方法

Python 是一种通用编程语言,已经存在了大约 30 年。早期,它是自动化脚本的首选。然而,随着 Django 和 Flask 等框架的出现,它的受欢迎程度越来越高,现在各种领域中都在应用它,如企业应用程序开发。数据科学和机器学习进一步推动了它的发展,Python 现在是三大编程语言之一。

许多人将 Python 的成功归功于它容易编码。这只是一部分原因。只要你的目标是开发小型脚本,Python 就像一个玩具,你会非常喜欢它。然而,当你进入严肃的大规模应用程序开发领域时,你将不得不处理大量的 ifelse,Python 变得与任何其他平台一样好或一样坏。例如,采用一种面向对象的方法!许多 Python 开发人员甚至可能没意识到 Python 支持类、继承等功能。Python 确实支持成熟的面向对象开发,但是有它自己的方式 -- Pythonic!让我们探索一下!

领域模型

AddService 通过将数据保存到一个 MySQL 数据库中来将用户添加到系统中。FindService 的目标是提供一个 REST API 按用户名查找用户。域模型如图 1 所示。它主要由一些值对象组成,如 User 实体的NamePhoneNumber 以及 UserRepository

图 1: 查找服务的域模型

让我们从 Name 开始。由于它是一个值对象,因此必须在创建时进行验证,并且必须保持不可变。基本结构如所示:

class Name:
    value: str
    def __post_init__(self):
        if self.value is None or len(self.value.strip()) < 8 or len(self.value.strip()) > 32:
            raise ValueError("Invalid Name")

如你所见,Name 包含一个字符串类型的值。作为后期初始化的一部分,我们会验证它。

Python 3.7 提供了 @dataclass 装饰器,它提供了许多开箱即用的数据承载类的功能,如构造函数、比较运算符等。如下是装饰后的 Name 类:

from dataclasses import dataclass

@dataclass
class Name:
    value: str
    def __post_init__(self):
        if self.value is None or len(self.value.strip()) < 8 or len(self.value.strip()) > 32:
            raise ValueError("Invalid Name")

以下代码可以创建一个 Name 对象:

name = Name("Krishna")

value 属性可以按照如下方式读取或写入:

name.value = "Mohan"
print(name.value)

可以很容易地与另一个 Name 对象比较,如下所示:

other = Name("Mohan")
if name == other:
    print("same")

如你所见,对象比较的是值而不是引用。这一切都是开箱即用的。我们还可以通过冻结对象使对象不可变。这是 Name 值对象的最终版本:

from dataclasses import dataclass

@dataclass(frozen=True)
class Name:
    value: str
    def __post_init__(self):
        if self.value is None or len(self.value.strip()) < 8 or len(self.value.strip()) > 32:
            raise ValueError("Invalid Name")

PhoneNumber 也遵循类似的方法,因为它也是一个值对象:

@dataclass(frozen=True)
class PhoneNumber:
    value: int
    def __post_init__(self):
        if self.value < 9000000000:
            raise ValueError("Invalid Phone Number")

User 类是一个实体,不是一个值对象。换句话说,User 是可变的。以下是结构:

from dataclasses import dataclass
import datetime

@dataclass
class User:
    _name: Name
    _phone: PhoneNumber
    _since: datetime.datetime

    def __post_init__(self):
        if self._name is None or self._phone is None:
            raise ValueError("Invalid user")
        if self._since is None:
            self.since = datetime.datetime.now()

你能观察到 User 并没有冻结,因为我们希望它是可变的。但是,我们不希望所有属性都是可变的。标识字段如 _name_since 是希望不会修改的。那么,这如何做到呢?

Python3 提供了所谓的描述符协议,它会帮助我们正确定义 getter 和 setter。让我们使用 @property 装饰器将 getter 添加到 User 的所有三个字段中。

@property
def name(self) -> Name:
    return self._name

@property
def phone(self) -> PhoneNumber:
    return self._phone

@property
def since(self) -> datetime.datetime:
    return self._since

phone 字段的 setter 可以使用 @<字段>.setter 来装饰:

@phone.setter
def phone(self, phone: PhoneNumber) -> None:
    if phone is None:
        raise ValueError("Invalid phone")
    self._phone = phone

通过重写 __str__() 函数,也可以为 User 提供一个简单的打印方法:

def __str__(self):
    return self.name.value + " [" + str(self.phone.value) + "] since " + str(self.since)

这样,域模型的实体和值对象就准备好了。创建异常类如下所示:

class UserNotFoundException(Exception):
    pass

域模型现在只剩下 UserRepository 了。Python 提供了一个名为 abc 的有用模块来创建抽象方法和抽象类。因为 UserRepository 只是一个接口,所以我们可以使用 abc 模块。

任何继承自 abc.ABC 的类都将变为抽象类,任何带有 @abc.abstractmethod 装饰器的函数都会变为一个抽象函数。下面是 UserRepository 的结构:

from abc import ABC, abstractmethod

class UserRepository(ABC):
    @abstractmethod
    def fetch(self, name:Name) -> User:
        pass

UserRepository 遵循仓储模式。换句话说,它在 User 实体上提供适当的 CRUD 操作,而不会暴露底层数据存储语义。在本例中,我们只需要 fetch() 操作,因为 FindService 只查找用户。

因为 UserRepository 是一个抽象类,我们不能从抽象类创建实例对象。创建对象必须依赖于一个具体类实现这个抽象类。数据层 UserRepositoryImpl 提供了 UserRepository 的具体实现:

class UserRepositoryImpl(UserRepository):
    def fetch(self, name:Name) -> User:
        pass

由于 AddService 将用户数据存储在一个 MySQL 数据库中,因此 UserRepositoryImpl 也必须连接到相同的数据库去检索数据。下面是连接到数据库的代码。注意,我们正在使用 MySQL 的连接库。

from mysql.connector import connect, Error

class UserRepositoryImpl(UserRepository):
    def fetch(self, name:Name) -> User:
        try:
            with connect(
                    host="mysqldb",
                    user="root",
                    password="admin",
                    database="glarimy",
                ) as connection:
                with connection.cursor() as cursor:
                    cursor.execute("SELECT * FROM ums_users where name=%s", (name.value,))
                    row = cursor.fetchone()
                    if cursor.rowcount == -1:
                        raise UserNotFoundException()
                    else:
                        return User(Name(row[0]), PhoneNumber(row[1]), row[2])
        except Error as e:
            raise e

在上面的片段中,我们使用用户 root / 密码 admin 连接到一个名为 mysqldb 的数据库服务器,使用名为 glarimy 的数据库(模式)。在演示代码中是可以包含这些信息的,但在生产中不建议这么做,因为这会暴露敏感信息。

fetch() 操作的逻辑非常直观,它对 ums_users 表执行 SELECT 查询。回想一下,AddService 正在将用户数据写入同一个表中。如果 SELECT 查询没有返回记录,fetch() 函数将抛出 UserNotFoundException 异常。否则,它会从记录中构造 User 实体并将其返回给调用者。这没有什么特殊的。

应用层

最终,我们需要创建应用层。此模型如图 2 所示。它只包含两个类:控制器和一个 DTO。

图 2: 添加服务的应用层

众所周知,一个 DTO 只是一个没有任何业务逻辑的数据容器。它主要用于在 FindService 和外部之间传输数据。我们只是提供了在 REST 层中将 UserRecord 转换为字典以便用于 JSON 传输:

class UserRecord:
    def toJSON(self):
        return {
            "name": self.name,
            "phone": self.phone,
            "since": self.since
        }

控制器的工作是将 DTO 转换为用于域服务的域对象,反之亦然。可以从 find() 操作中观察到这一点。

class UserController:

    def __init__(self):
        self._repo = UserRepositoryImpl()

    def find(self, name: str):
        try:
            user: User = self._repo.fetch(Name(name))
            record: UserRecord = UserRecord()
            record.name = user.name.value
            record.phone = user.phone.value
            record.since = user.since
            return record
        except UserNotFoundException as e:
            return None

find() 操作接收一个字符串作为用户名,然后将其转换为 Name 对象,并调用 UserRepository 获取相应的 User 对象。如果找到了,则使用检索到的 User` 对象创建UserRecord。回想一下,将域对象转换为 DTO 是很有必要的,这样可以对外部服务隐藏域模型。

UserController 不需要有多个实例,它也可以是单例的。通过重写 __new__,可以将其建模为一个单例。

class UserController:
    def __new__(self):
        if not hasattr(self, ‘instance’):
            self.instance = super().__new__(self)
        return self.instance

    def __init__(self):
        self._repo = UserRepositoryImpl()

    def find(self, name: str):
        try:
            user: User = self._repo.fetch(Name(name))
            record: UserRecord = UserRecord()
            record.name = user.name.getValue()
            record.phone = user.phone.getValue()
            record.since = user.since
            return record
        except UserNotFoundException as e:
            return None

我们已经完全实现了 FindService 的模型,剩下的唯一任务是将其作为 REST 服务公开。

REST API

FindService 只提供一个 API,那就是通过用户名查找用户。显然 URI 如下所示:

GET /user/{name}

此 API 希望根据提供的用户名查找用户,并以 JSON 格式返回用户的电话号码等详细信息。如果没有找到用户,API 将返回一个 404 状态码。

我们可以使用 Flask 框架来构建 REST API,它最初的目的是使用 Python 开发 Web 应用程序。除了 HTML 视图,它还进一步扩展到支持 REST 视图。我们选择这个框架是因为它足够简单。 创建一个 Flask 应用程序:

from flask import Flask
app = Flask(__name__)

然后为 Flask 应用程序定义路由,就像函数一样简单:

@app.route('/user/<name>')
def get(name):
    pass

注意 @app.route 映射到 API /user/<name>,与之对应的函数的 get()

如你所见,每次用户访问 API 如 http://server:port/user/Krishna 时,都将调用这个 get() 函数。Flask 足够智能,可以从 URL 中提取 Krishna 作为用户名,并将其传递给 get() 函数。

get() 函数很简单。它要求控制器找到该用户,并将其与通常的 HTTP 头一起打包为 JSON 格式后返回。如果控制器返回 None,则 get() 函数返回合适的 HTTP 状态码。

from flask import jsonify, abort

controller = UserController()
record = controller.find(name)
if record is None:
    abort(404)
else:
    resp = jsonify(record.toJSON())
    resp.status_code = 200
    return resp

最后,我们需要 Flask 应用程序提供服务,可以使用 waitress 服务:

from waitress import serve
serve(app, host="0.0.0.0", port=8080)

在上面的片段中,应用程序在本地主机的 8080 端口上提供服务。最终代码如下所示:

from flask import Flask, jsonify, abort
from waitress import serve

app = Flask(__name__)

@app.route('/user/<name>')
def get(name):
    controller = UserController()
    record = controller.find(name)
    if record is None:
        abort(404)
    else:
        resp = jsonify(record.toJSON())
        resp.status_code = 200
        return resp

serve(app, host="0.0.0.0", port=8080)

部署

FindService 的代码已经准备完毕。除了 REST API 之外,它还有域模型、数据层和应用程序层。下一步是构建此服务,将其容器化,然后部署到 Kubernetes 上。此过程与部署其他服务妹有任何区别,但有一些 Python 特有的步骤。

在继续前进之前,让我们来看下文件夹和文件结构:

+ ums-find-service
+ ums
- domain.py
- data.py
- app.py
- Dockerfile
- requirements.txt
- kube-find-deployment.yml

如你所见,整个工作文件夹都位于 ums-find-service 下,它包含了 ums 文件夹中的代码和一些配置文件,例如 Dockerfilerequirements.txtkube-find-deployment.yml

domain.py 包含域模型,data.py 包含 UserRepositoryImplapp.py 包含剩余代码。我们已经阅读过代码了,现在我们来看看配置文件。

第一个是 requirements.txt,它声明了 Python 系统需要下载和安装的外部依赖项。我们需要用查找服务中用到的每个外部 Python 模块来填充它。如你所见,我们使用了 MySQL 连接器、Flask 和 Waitress 模块。因此,下面是 requirements.txt 的内容。

Flask==2.1.1
Flask_RESTful
mysql-connector-python
waitress

第二步是在 Dockerfile 中声明 Docker 相关的清单,如下:

FROM python:3.8-slim-buster

WORKDIR /ums
ADD ums /ums
ADD requirements.txt requirements.txt
RUN pip3 install -r requirements.txt

EXPOSE 8080
ENTRYPOINT ["python"]
CMD ["/ums/app.py"]

总的来说,我们使用 Python 3.8 作为基线,除了移动 requirements.txt 之外,我们还将代码从 ums 文件夹移动到 Docker 容器中对应的文件夹中。然后,我们指示容器运行 pip3 install 命令安装对应模块。最后,我们向外暴露 8080 端口(因为 waitress 运行在此端口上)。

为了运行此服务,我们指示容器使用使用以下命令:

python /ums/app.py

一旦 Dockerfile 准备完成,在 ums-find-service 文件夹中运行以下命令,创建 Docker 镜像:

docker build -t glarimy/ums-find-service

它会创建 Docker 镜像,可以使用以下命令查找镜像:

docker images

尝试将镜像推送到 Docker Hub,你也可以登录到 Docker。

docker login
docker push glarimy/ums-find-service

最后一步是为 Kubernetes 部署构建清单。

在之前的文章中,我们已经介绍了如何建立 Kubernetes 集群、部署和使用服务的方法。我假设仍然使用之前文章中的清单文件来部署添加服务、MySQL、Kafka 和 Zookeeper。我们只需要将以下内容添加到 kube-find-deployment.yml 文件中:

apiVersion: apps/v1
kind: Deployment
metadata:
name: ums-find-service
labels:
app: ums-find-service
spec:
replicas: 3
selector:
matchLabels:
app: ums-find-service
template:
metadata:
labels:
app: ums-find-service
spec:
containers:
- name: ums-find-service
image: glarimy/ums-find-service
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: ums-find-service
labels:
name: ums-find-service
spec:
type: LoadBalancer
ports:
- port: 8080
selector:
app: ums-find-service

上面清单文件的第一部分声明了 glarimy/ums-find-service 镜像的 FindService,它包含三个副本。它还暴露 8080 端口。清单的后半部分声明了一个 Kubernetes 服务作为 FindService 部署的前端。请记住,在之前文章中,mysqldb 服务已经是上述清单的一部分了。

运行以下命令在 Kubernetes 集群上部署清单文件:

kubectl create -f kube-find-deployment.yml

部署完成后,可以使用以下命令验证容器组和服务:

kubectl get services

输出如图 3 所示:

图 3: Kubernetes 服务

它会列出集群上运行的所有服务。注意查找服务的外部 IP,使用 curl 调用此服务:

curl http://10.98.45.187:8080/user/KrishnaMohan

注意:10.98.45.187 对应查找服务,如图 3 所示。

如果我们使用 AddService 创建一个名为 KrishnaMohan 的用户,那么上面的 curl 命令看起来如图 4 所示:

图 4: 查找服务

用户管理系统(UMS)的体系结构包含 AddServiceFindService,以及存储和消息传递所需的后端服务,如图 5 所示。可以看到终端用户使用 ums-add-service 的 IP 地址添加新用户,使用 ums-find-service 的 IP 地址查找已有用户。每个 Kubernetes 服务都由三个对应容器的节点支持。还要注意:同样的 mysqldb 服务用于存储和检索用户数据。

图 5: UMS 的添加服务和查找服务

其他服务

UMS 系统还包含两个服务:SearchServiceJournalService。在本系列的下一部分中,我们将在 Node 平台上设计这些服务,并将它们部署到同一个 Kubernetes 集群,以演示多语言微服务架构的真正魅力。最后,我们将观察一些与微服务相关的设计模式。


via: https://www.opensourceforu.com/2022/09/python-microservices-using-flask-on-kubernetes/

作者:Krishna Mohan Koyya 选题:lkxed 译者:MjSeven 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

FFmpeg 是第一个干掉专有竞争软件的大规模开源软件

FFmpeg 被描述为多媒体的瑞士军刀。它集成了数百个视频、音频和图像解码器和编码器、多路复用器和解复用器、过滤器和设备。FFmpeg 是第一个在其细分市场上完全消除了专有软件的大规模 FOSS 项目之一。几乎所有的多媒体相关公司都依靠 FFmpeg 来完成他们的重任。在多媒体方面,FFmpeg 几乎是所有问题的解决方案。如果它不是,你更有可能去修补 FFmpeg,而不是去开发新的东西。顺便说一句,FFmpeg 的创始人 Fabrice Bellard 也是 QEMU 的创始人。

消息来源:Drew DeVault
老王点评:FFmpeg 简直是垄断性的成功。说起这个来,我记得有几家公司被列入了其耻辱榜。

Electron 上运行的 Windows 95 发布新版本

发布于 27 年前的 Windows 95 虽然早已停止支持,但仍被一些人认为是微软创造的最伟大的产品之一。有爱好者使用 Electron 开发了名为“Windows 95”复刻版应用,借助该框架,它可以在 Windows、macOS 和 Linux 上运行。该应用刚刚发布了最新版本 3.1.1,得益于底层框架 Electron 从 v18 升级到 v21,它带来了一些重大变化,比如支持最新的 Chromium 106,支持深色模式。

消息来源:GitHub
老王点评:当年第一次见到 Windows 95,那种震撼是只用过 DOS 和 Windows 3.1 的我不能想象的。

比特币网络花了一个半小时才产生了一个区块

根据区块浏览器的数据,最近比特币网络开采出的两个区块间隔了 85 分钟,有超过 13,000 笔交易被积压。上周,比特币经历了一次难度调整,以确保区块确认每 10 分钟进行一次。随着采矿难度飙升至 35.6 万亿,开采比特币的成本变得更高。闪电网络的创始人说,在不考虑难度变化的情况下,每隔 34 天会发生一次 85 分钟区块间隔。

消息来源:Coindesk
老王点评:这样的可靠性堪忧啊。

在本指南中,我们将逐步介绍如何在 Linux 中创建 LVM 分区。

LVM 代表 “ 逻辑卷管理 Logical Volume Management ”,它是专门为服务器管理 Linux 系统上的磁盘或存储的推荐方式。 LVM 分区的主要优点之一是我们可以实时扩展其大小而无需停机。 LVM 分区也可以缩小,但不推荐。

为了演示,我在我的 Ubuntu 22.04 系统上连接了 15GB 磁盘,我们将从命令行在该磁盘上创建 LVM 分区。

准备
  • 连接到 Linux 系统的原始磁盘
  • 具有 sudo 权限的本地用户
  • 预装 lvm2 包

事不宜迟,让我们深入了解这些步骤。

步骤 1、识别新连接的原始磁盘

登录到你的系统,打开终端并运行以下 dmesg 命令:

$ sudo dmesg | grep -i sd

在输出中,查找大小为 15GB 的新磁盘。

dmesg-command-new-attached-disk-linux

识别新连接的原始磁盘的另一种方法是通过 fdisk 命令:

$ sudo fdisk -l | grep -i /dev/sd

输出:

fdisk-command-output-new-disk

从上面的输出,可以确认新连接的磁盘是 /dev/sdb

步骤 2、创建 PV(物理卷)

在开始在磁盘 /dev/sdb 上创建 物理卷 Physical Volume (PV)之前,请确保已安装 lvm2 包。如果未安装,请运行以下命令:

$ sudo apt install lvm2     // On Ubuntu / Debian
$ sudo dnf install lvm2    // on RHEL / CentOS

运行以下 pvcreate 命令在磁盘 /dev/sdb 上创建 PV:

$ sudo pvcreate /dev/sdb
  Physical volume "/dev/sdb" successfully created.
$

要验证 PV 状态,运行:

$ sudo pvs /dev/sdb
或者
$ sudo pvdisplay /dev/sdb

pvdisplay-command-output-linux

步骤 3、创建 VG(卷组)

要创建 卷组 Volume Group (VG),我们将使用 vgcreate 命令。创建 VG 意味着将 PV 添加到其中。

语法:

$ sudo vgcreare <vg_name>  <pv>

在我们的例子中,命令是:

$ sudo vgcreate volgrp01 /dev/sdb
  Volume group "volgrp01" successfully created
$

运行以下命令以验证 VG(volgrp01)的状态:

$ sudo vgs volgrp01
或者
$ sudo vgdisplay volgrp01

上述命令的输出:

vgs-command-output-linux

以上输出确认大小为 15 GiB 的卷组 volgrp01 已成功创建,一个 物理扩展Physical Extend(PE)的大小为 4 MB。创建 VG 时可以更改 PE 大小。

步骤 4、创建 LV(逻辑卷)

lvcreate 命令用于从 VG 中创建 逻辑卷 Logical Volume LV。 lvcreate 命令的语法如下所示:

$ sudo lvcreate -L <Size-of-LV> -n <LV-Name>   <VG-Name>

在我们的例子中,以下命令将用于创建大小为 14 GB 的 LV:

$ sudo lvcreate -L 14G -n lv01 volgrp01
  Logical volume "lv01" created.
$

验证 LV 的状态,运行:

$ sudo lvs /dev/volgrp01/lv01
或者
$ sudo lvdisplay /dev/volgrp01/lv01

输出:

lvs-command-output-linux

上面的输出显示 LV(lv01)已成功创建,大小为 14 GiB。

步骤 5、格式化 LVM 分区

使用 mkfs 命令格式化 LVM 分区。在我们的例子中,LVM 分区是 /dev/volgrp01/lv01

注意:我们可以将分区格式化为 ext4 或 xfs,因此请根据你的设置和要求选择文件系统类型。

运行以下命令将 LVM 分区格式化为 ext4 文件系统。

$ sudo mkfs.ext4 /dev/volgrp01/lv01

mkfs-ext4-filesystem-lvm

执行下面的命令,用 xfs 文件系统格式化 LVM 分区:

$ sudo mkfs.xfs /dev/volgrp01/lv01

要使用上述格式化分区,我们必须将其挂载到某个文件夹中。所以,让我们创建一个文件夹 /mnt/data

$ sudo mkdir /mnt/data

现在运行 mount 命令将其挂载到 /mnt/data 文件夹:

$ sudo mount /dev/volgrp01/lv01 /mnt/data/
$ df -Th /mnt/data/
Filesystem                Type  Size  Used Avail Use% Mounted on
/dev/mapper/volgrp01-lv01 ext4   14G   24K   13G   1% /mnt/data
$

尝试创建一些没用的文件,运行以下命令:

$ cd /mnt/data/
$ echo "testing lvm partition" | sudo tee dummy.txt
$ cat dummy.txt
testing lvm partition
$
$ sudo rm -f  dummy.txt

完美,以上命令输出确认我们可以访问 LVM 分区。

要永久挂载上述 LVM 分区,请使用以下 echo 命令将其条目添加到 fstab 文件中:

$ echo '/dev/volgrp01/lv01  /mnt/data  ext4  defaults 0 0' | sudo  tee -a /etc/fstab
$ sudo mount -a

以上就是本指南的全部内容,感谢阅读。请在下面的评论区发表你的问题和反馈。


via: https://www.linuxtechi.com/how-to-create-lvm-partition-in-linux/

作者:James Kiarie 选题:lkxed 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux 中国 荣誉推出

LURE 是一个新的开源项目,它希望成为所有发行版的 AUR。

LURE 是一个新的开源项目,它希望成为所有发行版的 AUR!

AUR( Arch 用户仓库 Arch User Repository )是一个由社区驱动的基于 Arch 的 Linux 的发行版仓库。

简而言之: 它可以帮助你安装官方仓库中没有的软件包,并让你获得最新的版本。

我发现它对我在 Manjaro Linux 上的体验很有帮助。

从技术上讲,AUR 从源头构建一个软件包,然后利用软件包管理器(pacman)来安装它。

你也可以在我们的详细指南中探索更多关于它的信息。

什么是 AUR? 如何在 Arch 和 Manjaro Linux 中使用 AUR?

? 现在你对 AUR 有了一个基本的了解,有一个 新的开源项目 旨在将 AUR 的功能带到所有的发行版中。

这个项目被称为 “ Linux 用户仓库 Linux User REpository ”(LURE)。

? LURE 项目正处于 alpha 阶段,由创建者在几周前宣布。所以,它完全是一个正在进行的工作。

已经有这样的项目了?

lure 添加仓库

没有。

开发者们已经尝试做一个 AUR 的替代品,但是是针对特定的发行版。就像 makedeb 软件包仓库 是针对 Debian 的。

LURE 是一个雄心勃勃的想法,可以在你选择的任何发行版上工作。

它试图成为一个帮助你使用类似于 PKGBUILD 的脚本为你的发行版创建原生软件包的工具。

创建 PKGBUILD 为 Arch Linux 制作软件包

开发者在 Reddit 公告帖子 中提到了一些技术细节:

我的项目叫 LURE,是 “Linux 用户仓库”的简称。它构建原生软件包,然后使用系统软件包管理器安装它们,就像 AUR 一样。它使用一个类似于 AUR 的 PKGBUILD 的构建脚本来构建软件包。

它是用纯 Go 语言编写的,这意味着它在构建后没有任何依赖性,除了一些特权提升命令(sudodoas 等等)和任何一个支持的软件包管理器,目前支持 pacmanaptapk(Alpine Linux 上,不是安卓)、dnfyumzypper

听起来很棒!

LURE 项目Repo

你也可以在它的 GitHub 镜像 上探索更多信息。

使用 LURE

你不必安装一个额外的软件包管理器来使它工作,它可以自动与你系统的软件包管理器一起工作。

因此,如果它在其仓库(或任何其添加的仓库)中没有找到一个包,它就会转到系统的默认仓库,并从那里安装它。就像我用 lure 命令在我的系统上安装/移除 neofetch 一样。

lure neofetch remove

虽然该项目处于早期开发阶段,但它为各种发行版提供了 二进制包,以让你安装和测试它们。

目前,它的仓库包括一个来自创建者自己的项目。但你可以尝试添加一个仓库并构建/安装东西。

为了方便起见,我试着在它的仓库中安装软件包。

命令看起来像这样:

lure in itd-bin

在它的 官方文档页面,你可以读到更多关于它在构建/安装/添加存储库方面的用法。

未来版本的一些计划中的功能包括:

  • 自动安装脚本
  • 基于 Docker 的自动测试工具
  • 仓库的网页接口

让它变得更好

嗯,首先,这是一个优秀的项目。如果你是过去使用过 Arch 的人,或者想离开 Arch Linux,这将是一个很好的工具。

然而,对于大多数终端用户和非 Arch Linux 新手来说,像 Pamac GUI 软件包管理器 这样的软件包管理器支持 LURE 应该是锦上添花的。

当然,在目前的阶段,它需要开源贡献者的支持。所以,如果你喜欢这个想法,请随时为该项目贡献改进意见

*? 你对 LURE 有什么看法?请在下面的评论中分享你的想法! *


via: https://news.itsfoss.com/lure-aur/

作者:Ankush Das 选题:lkxed 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

AI 成为丹麦新成立的合成党党魁

合成党是今年 5 月丹麦成立的一个新的党派,倡导人类与 AI 的和谐共处。该党派正试图在今年 11 月的丹麦议会选举中赢得一个席位。令人吃惊的是,合成党的公众形象和挂名领袖是一个名叫 Leader Lars 的 AI 聊天机器人。它根据 1970 年以来丹麦各个边缘政党的政策编程,旨在代表 20% 不参加选举的丹麦人的价值观。它通过 Discord 与民众交流。但它不会参与投票。

消息来源:VICE
老王点评:这个党派唯一不足的地方就是,成员还是人类。?

AI 专家点评各大 AI

UNDARK 对纽约大学名誉教授 Gary Marcus 进行了采访,在采访中他对当前的几个主流 AI 进行了有趣的点评:GPT-3 “其实是一个自动完成系统,可以预测下一个单词和句子。就像你的手机一样,你输入一些东西,它就会继续。它并不真正理解它周围的世界。”谷歌的 LaMDA “没有知觉,它不知道自己在说什么东西”。无人驾驶汽车“仅仅记住你所见过的大量交通情况并不能表达你真正需要了解的世界”。OpenAI 的 DALL-E “利用了人类的非故意贡献,他们也许已经签署了‘服务条款’协议,但没有认识到这一切会导致什么”。

消息来源:Undark
老王点评:简直把当前热捧的 AI 批评的一无是处,人间清醒啊。

修好了电脑的 Linus Torvalds 呼吁内核开发人员别赶 Deadline

Linus Torvalds 发布了 Linux 内核 6.1 的第一个 rc 版本,对这个版本,Torvalds 说,“不算小,但比过去几个版本小”。内核的每一个新版本都有一个为期两周的合并窗口,“企鹅皇帝”说,“在我把我的机器整理好并赶上合并窗口后,我对各种迟到的拉取请求感到有些沮丧。我以前提到过这个,但是在合并窗口的最后几天收到相当多的拉动请求,这真的很烦人。”然后他抱怨内核开发人员们没有尽早提交代码,不要“在两周内匆匆忙忙地把一个分支放在一起,然后在第二周的星期五发给 Linus。……在截止日期前熬夜完成论文的做法在高中毕业后就应该被淘汰了。你知道我说是谁”。

消息来源:The Register
老王点评:有时候看内核邮件列表里面 Torvalds 每次的邮件也挺有意思的。