2022年12月

Atom 编辑器项目进入只读归档模式

2015 年,GitHub 在开源了 Atom 编辑器一年之后,发布了 1.0;而同一年,受 Atom 灵感影响的微软的 VS Code 编辑器发布,它同样采用了 Atom 的 Electron 框架。Atom 曾经吸引了数百万开发者使用。在微软 2018 年收购 GitHub 后,虽然 GitHub 曾经承诺不会放弃 Atom,但过去几年 Atom 除了安全更新外几乎没有什么改进。半年前,GitHub 宣布终止 Atom 项目,而现在它的仓库也被归档了。

消息来源:GitHub
老王点评:Atom 可能唯一剩下的重要遗产就是 Electron 框架了。

OpenAI 预计到 2024 年收入将达到 10 亿美元

最近大火的 ChatGPT 是 OpenAI 旗下产品,其已经为超过 100 万用户回答了查询。它是由 Elon Musk 和投资者 Sam Altman 共同创办的,得到了微软 10 亿美元的资金支持。OpenAI 最近的估值已达 200 亿美元,预计明年它的收入将达到 2 亿美元,到 2024 年将达到 10 亿美元。OpenAI 在 2019 年创建的“利润上限”结构是一种不寻常的限制。OpenAI 希望通过将支持者的回报限制在其投资的 100 倍,或在未来更少,来保障其使命。

消息来源:路透社
老王点评:预期在 AI 行业还有更多的造富机会。

Meta、微软、AWS 等合作构建开放地图数据

为了对抗谷歌在地图领域的主导地位,Meta、微软、AWS 和荷兰地图公司 TomTom 推动建立了 Overture 地图基金会,由 Linux 基金会正式主持。其使命是通过公开的数据集为新的地图产品提供动力,这些数据集可以在不同的应用和业务中使用和重用,每个成员都会把自己的数据和资源放进这个组合。

消息来源:Tech Crunch
老王点评:这种基础性的数据,显然不应该掌握在一两家公司手里。

Rust FFI 和 bindgen 工具是为 Rust 调用 C 库而设计的。Rust 很容易与 C 语言对话,从而与任何其它可以与 C 语言对话的语言对话。

为什么要从 Rust 调用 C 函数?简短的答案就是软件库。冗长的答案则触及到 C 在众多编程语言中的地位,特别是相对 Rust 而言。C、C++,还有 Rust 都是系统语言,这意味着程序员可以访问机器层面的数据类型与操作。在这三个系统语言中,C 依然占据主导地位。现代操作系统的内核主要是用 C 来写的,其余部分依靠汇编语言补充。在标准系统函数库中,输入与输出、数字处理、加密计算、安全、网络、国际化、字符串处理、内存管理等等,大多都是用 C 来写的。这些函数库所代表的是一个庞大的基础设施,支撑着用其他语言写出来的应用。Rust 发展至今也有着可观的函数库,但是 C 的函数库 —— 自 1970 年代就已存在,迄今还在蓬勃发展 —— 是一种无法被忽视的资源。最后一点是,C 依然还是编程语言中的 通用语:大部分语言都可以与 C 交流,透过 C,语言之间可以互相交流。

两个概念证明的例子

Rust 支持 FFI( 外部函数接口 Foreign Function Interface )用以调用 C 函数。任何 FFI 所需要面临的问题是调用方语言是否涵盖了被调用语言的数据类型。例如,ctypes 是 Python 调用 C 的 FFI,但是 Python 并没有包括 C 所支持的无符号整数类型。结果就是,ctypes 必须寻求解决方案。

相比之下,Rust 包含了所有 C 中的原始(即,机器层面)类型。比如说,Rust 中的 i32 类对应 C 中的 int 类。C 特别声明了 char 类必须是一个字节大小,而其他类型,比如 int,必须至少是这个大小(LCTT 译注:原文处有评论指出 int 大小依照 C 标准应至少为 2 字节);然而如今所有合理的 C 编译器都支持四字节的 int,以及八字节的 double(Rust 中则是 f64 类),以此类推。

针对 C 的 FFI 所面临的另一个挑战是:FFI 是否能够处理 C 的裸指针,包括指向被看作是字符串的数组指针。C 没有字符串类型,它通过结合字符组和一个非打印终止符(大名鼎鼎的 空终止符)来实现字符串。相比之下,Rust 有两个字符串类型:String&str (字符串切片)。问题是,Rust FFI 是否能将 C 字符串转化成 Rust 字符串——答案是 肯定的

出于对效率的追求,结构体指针在 C 中也很常见。一个 C 结构体在作为一个函数的参数或者返回值的时候,其默认行为是传递值(即,逐字节复制)。C 结构体,如同它在 Rust 中的对应部分一样,可以包含数组和嵌套其他结构体,所以其大小是不定的。结构体在两种语言中的最佳用法是传递或返回引用,也就是说,传递或返回结构体的地址而不是结构体本身的副本。Rust FFI 再一次成功处理了 C 的结构体指针,其在 C 函数库中十分普遍。

第一段代码案例专注于调用相对简单的 C 库函数,比如 abs(绝对值)和 sqrt(平方根)。这些函数使用非指针标量参数并返回一个非指针标量值。第二段代码案例则涉及了字符串和结构体指针,在这里会介绍工具 bindgen,其通过 C 接口(头文件)生成 Rust 代码,比如 math.h 以及 time.h。C 头文件声明了 C 函数的调用语法,并定义了会被调用的结构体。两段代码都能在 我的主页上 找到。

调用相对简单的 C 函数

第一段代码案例有四处 Rust 对标准数学库内的 C 函数的调用:两处分别调用了 abs(绝对值)和 pow(幂),两处重复调用了 sqrt(平方根)。这个程序可以直接用 rustc 编译器进行构建,或者使用更方便的命令 cargo build

use std::os::raw::c_int;  // 32位
use std::os::raw::c_double; // 64位

// 从标准库 libc 中引入三个函数。
// 此处是 Rust 对三个 C 函数的声明:
extern "C" {
  fn abs(num: c_int) -> c_int;
  fn sqrt(num: c_double) -> c_double;
  fn pow(num: c_double, power: c_double) -> c_double;
}

fn main() {
  let x: i32 = -123;
  println!("\n{x}的绝对值是: {}.", unsafe { abs(x) });

  let n: f64 = 9.0;
  let p: f64 = 3.0;
  println!("\n{n}的{p}次方是: {}.", unsafe { pow(n, p) });

  let mut y: f64 = 64.0;
  println!("\n{y}的平方根是: {}.", unsafe { sqrt(y) });

  y = -3.14;
  println!("\n{y}的平方根是: {}.", unsafe { sqrt(y) }); //** NaN = NotaNumber(不是数字)
}

顶部的两个 use 声明是 Rust 的数据类型 c_intc_double,对应 C 类型里的 intdouble。Rust 标准模块 std::os::raw 定义了 14 个类似的类型以确保跟 C 的兼容性。模块 std::ffi 中有 14 个同样的类型定义,以及对字符串的支持。

位于 main 函数上的 extern "C" 区域声明了 3 个 C 库函数,这些函数会在 main 函数内被调用。每次调用都使用了标准的 C 函数名,但每次调用都必须发生在一个 unsafe 区域内。正如每个新接触 Rust 的程序员所发现的那样,Rust 编译器极度强制内存安全。其他语言(特别是 C 和 C++)作不出相同的保证。unsafe 区域其实是说:Rust 对外部调用中可能存在的不安全行为不负责。

第一个程序输出为:

-123的绝对值是: 123.
9的3次方是: 729.
64的平方根是: 8.
-3.14的平方根是: NaN.

输出的最后一行的 NaN 表示 不是数字 Not a Number :C 库函数 sqrt 期待一个非负值作为参数,这使得参数 -3.14 生成了 NaN 作为返回值。

调用涉及指针的 C 函数

C 库函数为了提高效率,经常在安全、网络、字符串处理、内存管理,以及其他领域中使用指针。例如,库函数 asctime(ASCII 字符串形式的时间)期待一个结构体指针作为其参数。Rust 调用类似 asctime 的 C 函数就会比调用 sqrt 要更加棘手一些,后者既没有牵扯到指针,也不涉及到结构体。

函数 asctime 调用的 C 结构体类型为 struct tm。一个指向此结构体的指针会作为参数被传递给库函数 mktime(时间作为值)。此结构体会将时间拆分成诸如年、月、小时之类的单位。此结构体的 字段 field 类型为 time_t,是 int(32位)和 long(64 位)的别名。两个库函数将这些破碎的时间片段组合成了一个单一值:asctime 返回一个以字符串表示的时间,而 mktime 返回一个 time_t 值表示自 “ 纪元 Epoch 以来所经历的秒数,这是一个系统的时钟和时间戳的相对时间。典型的纪元设置为 1900 年或 1970 年,1 月 1 日 0 时 0 分 0 秒。(LCTT 校注:Unix、Linux 乃至于如今所有主要的计算机和网络的时间纪元均采用 1970 年为起点。)

以下的 C 程序调用了 asctimemktime,并使用了其他库函数 strftime 来将 mktime 的返回值转化成一个格式化的字符串。这个程序可被视作 Rust 对应版本的预热:

#include <stdio.h>
#include <time.h>

int main () {
  struct tm sometime;  /* 时间被打破细分 */
  char buffer[80];
  int utc;

  sometime.tm_sec = 1;
  sometime.tm_min = 1;
  sometime.tm_hour = 1;
  sometime.tm_mday = 1;
  sometime.tm_mon = 1;
  sometime.tm_year = 1; /*LCTT 校注:注意,相对于 1900 年的年数*/
  sometime.tm_hour = 1;
  sometime.tm_wday = 1;
  sometime.tm_yday = 1;

  printf("日期与时间: %s\n", asctime(&sometime));

  utc = mktime(&sometime);
  if( utc < 0 ) {
    fprintf(stderr, "错误: mktime 无法生成时间\n");
  } else {
    printf("返回的整数值: %d\n", utc);
    strftime(buffer, sizeof(buffer), "%c", &sometime);
    printf("更加可读的版本: %s\n", buffer);
  }

  return 0;
}

程序输出为:

日期与时间: Fri Feb  1 01:01:01 1901
返回的整数值: 2120218157
更加可读的版本: Fri Feb  1 01:01:01 1901

(LCTT 译注:如果你尝试在自己电脑上运行这段代码,然后得到了一行关于 mktime 的错误信息,然后又在网上随便找了个在线 C 编译器,复制代码然后得到了跟这里的结果有区别但是没有错误的结果,不要慌,我的电脑上也是这样的。导致本地机器上 mktime 失败的原因是作者没有设置 tm_isdst,这个是用来标记夏令时的标志。tm_isdst 大于零则夏令时生效中,等于零则不生效,小于零标记未知。加入 sometime.tm_isdst = 0= -1 后应该就能得到跟在线编译器大致一样的结果。不同的地方在于结果第一行我得到的是 Mon Feb ...,这个与作者代码中 sometime.tm_wday = 1 对应,这里应该是作者写错了;第二行我和作者和网上得到的数字都不一样,这大概是合理的,因为这与机器的纪元有关;第三行我跟作者的结果是一样的,1901 年 2 月 1 日也确实是周五,这是因为 mktime 其实会修正时间参数中不合理的地方。至于夏令时具体是如何影响 mktime 这个问题,我能查到的只有 mktime 的计算受时区影响,更底层的原因我也不知道了。)

总的来说,Rust 在调用库函数 asctimemktime 时,必须处理以下两个问题:

  • 将裸指针作为唯一参数传递给每个库函数。
  • 把从 asctime 返回的 C 字符串转化为 Rust 字符串。

Rust 调用 asctime 和 mktime

工具 bindgen 会根据类似 math.htime.h 之类的 C 头文件生成 Rust 支持的代码。下面这个简化版的 time.h 就可以用来做例子,简化版与原版主要有两个不同:

  • 内置类型 int 被用来取代别名类型 time_t。工具 bindgen 可以处理 time_t 类,但是会生成一些烦人的警告,因为 time_t 不符合 Rust 的命名规范:time_t 以下划线区分 timet;Rust 更偏好驼峰式命名方法,比如 TimeT
  • 出于同样的原因,这里选择 StructTM 作为 struct tm 的别名。

以下是一份简化版的头文件,mktimeasctime 在文件底部:

typedef struct tm {
  int tm_sec;  /* 秒 */
  int tm_min;  /* 分钟 */
  int tm_hour;   /* 小时 */
  int tm_mday;   /* 日 */
  int tm_mon;  /* 月 */
  int tm_year;   /* 年 */
  int tm_wday;   /* 星期 */
  int tm_yday;   /* 一年中的第几天 */
  int tm_isdst;  /* 夏令时 */
} StructTM;

extern int mktime(StructTM*);
extern char* asctime(StructTM*);

bindgen 安装好后,mytime.h 作为以上提到的头文件,以下命令(% 是命令行提示符)可以生成所需的 Rust 代码并将其保存到文件 mytime.rs

% bindgen mytime.h > mytime.rs

以下是 mytime.rs 中的重要部分:

/* automatically generated by rust-bindgen 0.61.0 */

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct tm {
  pub tm_sec: ::std::os::raw::c_int,
  pub tm_min: ::std::os::raw::c_int,
  pub tm_hour: ::std::os::raw::c_int,
  pub tm_mday: ::std::os::raw::c_int,
  pub tm_mon: ::std::os::raw::c_int,
  pub tm_year: ::std::os::raw::c_int,
  pub tm_wday: ::std::os::raw::c_int,
  pub tm_yday: ::std::os::raw::c_int,
  pub tm_isdst: ::std::os::raw::c_int,
}

pub type StructTM = tm;

extern "C" {
  pub fn mktime(arg1: *mut StructTM) -> ::std::os::raw::c_int;
}

extern "C" {
  pub fn asctime(arg1: *mut StructTM) -> *mut ::std::os::raw::c_char;
}

#[test]
fn bindgen_test_layout_tm() {
  const UNINIT: ::std::mem::MaybeUninit<tm> = ::std::mem::MaybeUninit::uninit();
  let ptr = UNINIT.as_ptr();
  assert_eq!(
  ::std::mem::size_of::<tm>(),
  36usize,
  concat!("Size of: ", stringify!(tm))
  );
  ...

Rust 结构体 struct tm,跟原本在 C 中的一样,包含了 9 个 4 字节的整型字段。这些字段名称在 C 和 Rust 中是一样的。extern "C" 区域声明了库函数 astimemktime 分别需要只一个参数,一个指向可变实例 StructTM 的裸指针。(库函数可能会通过指针改变作为参数传递的结构体。)

#[test] 属性下的其余代码是用来测试 Rust 版的时间结构体的布局。通过命令 cargo test 可以进行这些测试。问题在于,C 没有规定编译器应该如何对结构体中的字段进行布局。比如说,C 的 struct tm 以字段 tm_sec 开头用以表示秒;但是 C 不需要编译版本遵循这个排序。不管怎样,Rust 测试应该会成功,而 Rust 对库函数的调用也应如预期般工作。

设置好第二个案例并开始运行

bindgen 生成的代码不包含 main 函数,所以是一个天然的模块。以下是一个 main 函数初始化了 StructTM 并调用了 asctimemktime

mod mytime;
use mytime::*;
use std::ffi::CStr;

fn main() {
  let mut sometime  = StructTM {
    tm_year: 1,
    tm_mon: 1,
    tm_mday: 1,
    tm_hour: 1,
    tm_min: 1,
    tm_sec: 1,
    tm_isdst: -1,
    tm_wday: 1,
    tm_yday: 1
  };

  unsafe {
    let c_ptr = &mut sometime; // 裸指针

    // 调用,转化,并拥有
    // 返回的 C 字符串
    let char_ptr = asctime(c_ptr);
    let c_str = CStr::from_ptr(char_ptr);
    println!("{:#?}", c_str.to_str());

    let utc = mktime(c_ptr);
    println!("{}", utc);
  }
}

这段 Rust 代码可以被编译(直接用 rustc 或使用 cargo)并运行。输出为:

Ok(
    "Mon Feb  1 01:01:01 1901\n",
)
2120218157

对 C 函数 asctimemktime 的调用必须再一次被放在 unsafe 区域内,因为 Rust 编译器无法对这些外部函数的潜在内存安全风险负责。此处声明一下,asctimemktime 并没有安全风险。调用的两个函数的参数是裸指针 ptr,其指向结构体 sometime (在 stack 中)的地址。

asctime 是两个函数中调用起来更棘手的那个,因为这个函数返回的是一个指向 C char 的指针,如果函数返回 Mon 那么指针就指向 M。但是 Rust 编译器并不知道 C 字符串 (char 的空终止数组)的储存位置。是内存里的静态空间?还是 heap asctime 函数内用来储存时间的文字表达的数组实际上是在内存的静态空间里。无论如何,C 到 Rust 字符串转化需要两个步骤来避免编译错误:

  • 调用 Cstr::from_ptr(char_ptr) 来将 C 字符串转化为 Rust 字符串并返回一个引用储存在变量 c_str 中。
  • c_str.to_str() 的调用确保了 c_str 是所有者。

Rust 代码不会增加从 mktime 返回的整型值的易读性,这一部分留作课外作业给感兴趣的人去探究。Rust 模板 chrono::format 也有一个 strftime 函数,它可以被当作 C 的同名函数来使用,两者都是获取时间的文字表达。

使用 FFI 和 bindgen 调用 C

Rust FFI 和工具 bindgen 都能够出色地协助 Rust 调用 C 库,无论是标准库还是第三方库。Rust 可以轻松地与 C 交流,并透过 C 与其他语言交流。对于调用像 sqrt 一样简单的库函数,Rust FFI 表现直截了当,这是因为 Rust 的原始数据类型覆盖了它们在 C 中的对应部分。

对于更为复杂的交流 —— 特别是 Rust 调用像 asctimemktime 一样,会涉及到结构体和指针的 C 库函数 —— bindgen 工具是优秀的帮手。这个工具会生成支持代码以及所需要的测试。当然,Rust 编译器无法假设 C 代码对内存安全的考虑会符合 Rust 的标准;因此,Rust 必须在 unsafe 区域内调用 C。


via: https://opensource.com/article/22/11/rust-calls-c-library-functions

作者:Marty Kalin 选题:lkxed 译者:yzuowei 校对:wxy

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

理解 OSI 框架的基本概念,掌握计算机系统通信机制。

开放系统互联 Open Systems Interconnection (OSI)模型是一个定义计算机、服务器和用户如何在一个系统内通信的标准。它是第一个网络通信标准模型,在上世纪 80 年代早期,所有主流的计算机和通信公司都采用了这个标准。

OSI 模型提供了一种用于描述网络的通用语言,并以离散的块或层的方式来描述。

OSI 模型的各个层

该模型描述了计算机系统通过网络进行通信的七个层。

  • 7 应用层
  • 6 表示层
  • 5 会话层
  • 4 传输层
  • 3 网络层
  • 2 数据链路层
  • 1 物理层

每个层都有自己的工作方式和一系列跟其他层不同的协议。本文将逐个剖析这些层级。

应用层

应用层是在软件中实现的。它是与应用程序交互的层级。

用发送消息作为例子。发送消息的程序与应用层进行交互,并发送消息。接着,应用层向 OSI 模型的下一个层级(即表示层)发送消息。

表示层

来自应用层的数据被转发到表示层。表示层接收到文字、字符、字母、数字等形式的数据,并把它们转换为机器可识读的二进制格式数据。这个过程叫做编译。

在此阶段,ASCII(美国信息交换标准码)字符被转换为扩充的二进制编码的十进制交换码(EBCDIC)。转换后的数据在继续传输前,也会进行编码和加密过程,使用 SSL 协议进行加密和解密。

表示层的作用是抽象化,它假设下面的层级会处理它们收到的数据。它也负责压缩数据。数据的压缩可能是有损的,也有可能是无损的,这取决于很多因素,这不属于本文的讨论范围。

会话层

会话层的作用是建立和管理连接。该层级的主要工作是建立会话。例如,你登录网上商城,就在你的机器和服务器之间建立了会话。

会话层的作用是实现数据的发送和接收,完成后连接的会话就终止了。在一个会话建立前,会进行身份验证。与上一层类似,会话层也假设在它的工作完成后,下面的层级也会准确无误地处理数据。

传输层

传输层的作用是管理数据传输和其自身的关于数据如何传输的一些协议。从会话层传到这里的数据被分为更小的数据单元,这些数据单元称为片段。这个过程叫做“分段”。每个片段包含来源端口号、目标端口号和一个序列号。端口号用来识别发送数据的应用程序。注意,数据以块的形式传输。序列号用于把这些片段按正确的顺序排列。

传输层负责控制流量或在给定的时间内传输的数据量。它也负责错误控制,比如数据丢失、损坏等情况。它利用一种错误检测值,通常叫做校验和。传输层对每个数据片段加上校验和,就可以检查所发送的数据是否被正确接收。然后数据传输到网络层。

网络层

网络层的作用是跟其他网络进行通信。它把从一台机器接收到的数据片段传输给另一台位于不同网络的机器。路由器是作用于网络层的。

网络层的功能是逻辑寻址(就是确定 IP 地址)。它为发送方和接收方分配 IP 地址,数据包附带了这个地址,就可以被传输到正确的目标机器。接着网络层对数据包进行路由。负载均衡也是在网络层进行的,旨在确保不会发生过载。下一步,数据传输到数据链路层。

数据链路层

数据链路层支持跟其他设备直接通信。

它接收到来自网络层、包含发送方和接收方 IP 地址的数据包,进行物理寻址,然后将发送方和接收方的 MAC 地址分配给数据包,形成帧。

物理层

物理层由系统的所有硬件和物理设备(包括网线、导航系统、适配器等)组成。在这里,从前面层级接收到的数据都是 0 和 1 形式的。物理层把这些数据转换并通过各种方式(如果是光纤电缆,有电线、电信号、光信号;如果是 WIFI,则为无线电信号)传输至本地媒介。

注意,物理层作用于接收方的一端,把接收到的信号以帧的形式传输到数据链路层(把它转换回二进制数据形式)。然后帧传输到上面的层级,最终应用层(应用软件)会接收到需要的数据。

结语

当你需要描述网络架构或排除网络问题时,OSI 模型的相关知识会对你有所帮助。我希望本文能令你对这个模型的方方面面有清晰的理解。


via: https://opensource.com/article/22/10/osi-model-network-communications

作者:Anamika 选题:lkxed 译者:cool-summer-021 校对:wxy

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

华为开发者的补丁将一个内核函数的速度提升了 715 倍

正在开发中的 Linux 6.2 合并了华为开发者雷镇的一个补丁,将 kallsyms_lookup_name() 的查找速度提高了 715 倍。该函数用于根据名字查找一个符号的地址,能用于查找内核符号表中的任何符号。新的改进将算法复杂度从 O(n) 改进为 O(log(n)),极大地提升了查找速度,只是要多耗费一些内存。Linux 内核社区将此补丁评价为“Linux 的圣诞节礼物”。

消息来源:phoronix
老王点评:可喜可贺!顺便说一句,在 Linux 6.1 LTS 中,华为再次以内核补丁数排名第一。

X.org 紧急发布补丁,WayLand 也没逃开

这六个漏洞与 X.Org 服务器扩展中的安全问题有关,是围绕堆栈溢出、使用后释放、越界访问等类似问题,可能导致本地提权和远程代码执行。X.Org 服务器连夜发布了相关补丁。依赖于 X.Org 服务器核心部分的 XWayland 也同样受影响,随之发布了新的补丁。

消息来源:Phoronix
老王点评:老化的代码,可能存在很多潜在的漏洞。但是 Wayland 依然受影响是我没想到的。

谷歌发布开源软件安全漏洞扫描器

谷歌宣布推出 OSV-Scanner,这是一个免费的漏洞扫描器,可以在整个软件供应链中自动发现和修补漏洞。它声称这是最大的社区可编辑的开源漏洞数据库。OSV-Scanner 使开发者能够自动将代码和依赖关系与已知的漏洞列表相匹配,并确定是否有补丁或更新。去年,谷歌推出了开源漏洞(OSV)模式和 OSV.dev 漏洞数据库服务。

消息来源:Venture Beat
老王点评:开源软件漏洞管理是一个重要的、正在发展的市场,谷歌的这些服务瞄准的就是这个市场。

Linux Mint 是一款极好的 Linux 发行版,特别适合初学者。

我喜欢它仍然保持常见的 Ubuntu/Debian 习惯,但是它还做了一些 比 Ubuntu 更好的 工作,其中之一就是它没有使用 Snap。

然而,我不是 Cinnamon 桌面环境的粉丝,因为我从来没有真正地喜欢过 Windows XP 或 7 的默认设置。

当我寻求保持 Linux Mint 稳定的同时而提供 GNOME 的能力时,这便是我最终获得的结果:

install gnome in linux mint

不太炫,这就是我运行 GNOME 42.5 的 Linux Mint 21 。

如果你想在 Linux Mint 上安装 GNOME ,那么这篇指南非常适合你。

在 Linux Mint 上安装GNOME 之前所要知道的事

要在 Mint 上安装 GNOME,你务必需要有足够的理由。如果你只是为了尝鲜,可以在虚拟机中尝试。我使用 在 VirtualBox 中安装的 Linux Mint 来演示这篇教程。

安装除发行版提供的桌面环境之外的其他桌面环境,移除桌面环境部分会使其变成一件很复杂的事。

Cinnamon 使用了一些 GNOME 元素。如果你决定稍后移除 GNOME ,这可能会影响到 Cinnamon 的一部分功能。

这可能会导致缺少实战经验用户的恐慌。当然,在 TTY 屏幕中重新安装 Cinnamon 桌面环境可能是一种可行的解决方案。

最重要的一点是,如果你很容易惊慌地不知所措和不喜欢解决难题,那么你就不应该在你的主力计算机上做这些 “试验” 。

抛开这些顾虑,让我们看看在 Linux Mint 上获取 GNOME 的简单过程。

在 Linux Mint 上安装 GNOME 桌面环境

在这里,你有两个选项:1、你可以使用包含所有的 GNOME 实用程序的完整的 GNOME 桌面,2、你也可以使用包含极少数软件包的 GNOME 精简版本。

我都将讲解一下。

安装精简版本的 GNOME ,你需要安装一个名称为 vanilla-gnome-desktop 的软件包,使用下面给定的命令:

sudo apt install vanilla-gnome-desktop

如果你想要完整的 GNOME 体验 ,你可以简单地安装 gnome 软件包:

sudo apt install gnome

在你执行上述任一个命令后,在接下来的步骤中将会要求你选择首选的显示管理器。

choose display manager

gdm3 是 GNOME 桌面的显示管理器,而 Linux Mint 使用 lightdm 作为默认的显示管理器,这两种显示器都可以正常工作,但是,我建议你使用 gdm3 来获取完整的 GNOME 体验。

切换到 GNOME

在完成后,注销并按一次回车键,在这里,你将看到一个小齿轮图标。从这里选择 “GNOME” :

choose gnome while logging in

现在,你拥有以 Linux Mint 为基础的 GNOME 桌面环境!

额外提示:如何应用整体风格一致的主题

你可以继续使用 Cinnamon 桌面的主题,但是它们大多不能如前工作,因此,我建议使用 GNOME 桌面的主题(例如 Adwaita )来保持桌面环境的一致性。

对我而言,其默认的字体没有一点效果。并且,我更喜欢 Fedora 提供的一些字体。因此,从系统菜单打开 GNOME 调整 GNOME tweaks ,并作出如下更改:

change fonts in ubuntu to have vanilla gnome experience

这里是我使用的一些设置:

  • Cantarell Regular (11) 用于界面和文档文本。
  • Noto Sans Mono Regular (13) 用于等宽字体文本。
  • Cantarell Bold (11) 用于窗口标题。

它们的结果是,比默认的 Ubuntu 字体方案要好得多。

既然你有了 GNOME ,你可以使用我们的详细指南来安装和 更改 Linux 上的 GNOME 主题,来使其成为你所梦想的样子。

总结

如你所见,在 Linux Mint 上安装 GNOME 是非常简单的。正如我先前所提到的那样,移除部分可能会使事情复杂化,因为这可能会移除一些 Cinnamon 所需要的一些 GNOME 软件包。

你现在的主力计算机系统是什么?我的是 Pop!\_OS 。


via: https://itsfoss.com/install-gnome-linux-mint/

作者:Sagar Sharma 选题:lkxed 译者:robsean 校对:wxy

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

将文档写作加入到 DevOps 的生命周期中。

 title=

DevOps 正在挑战技术文档的规范,这在 IT 历史上是前所未有的。从自动化到提高交付速度,再到拆除瀑布式软件开发生命周期模型,这意味着业务和技术文档写作的理念需要做出巨大改变。

以下是 DevOps 对技术文档写作不同方面的影响。

技术写手的角色变化

技术写手必须适应 DevOps。好消息是,许多技术写手已经加入到开发团队中,并且拥有合作关系和不断增长的产品知识的技术写手很具优势。

但是如果一个技术写手习惯于独立工作,并依赖于领域专家的草稿作为文档的基础,那么就需要做一些调整。

进行一些投资,以确保文档和其他与项目有关的内容开发工作获得所需的工具、结构和支持。从改变 技术写手聘用方式 开始。以 DevOps 的速度 编写文档需要重新思考内容规划,并打破 DevOps 团队和支持项目的技术写手之间长期存在的隔阂。

DevOps 使开发团队摆脱了传统文档实践的束缚。首先,文档 完成的定义 必须改变。一些企业的文化使技术写手成为软件开发的被动参与者。DevOps 提出了新的要求:随着 DevOps 文化的转变,技术写手的角色也应发生变化。技术写手需要(且必须适应)DevOps 提供的透明度。他们必须融入 DevOps 团队。取决于组织如何塑造这个角色,将技术写手带入团队可能会带来技能上的挑战。

文档标准、方法和规格

虽然 DevOps 还没有影响到技术文档本身,但开源社区已经加强了对应用编程接口(API)文档的帮助,已经有不同规模的企业的 DevOps 团队正在使用这些文档。

用于记录 API 的开源规范和工具是个非常值得关注的领域。我想这是由于 谷歌文档季 的影响,它使开源软件项目能够获得专业的技术写作人才来解决他们最关键的文档项目。

开源 API 属于 DevOps 文档讨论的一部分。云原生应用集成需求的重要性正在上升。OpenAPI 规范(一个定义和记录 API 的开放标准)是在 DevOps 环境下 API 文档的良好资源。然而,该规范会导致文档的创建和更新过程变得很费时,这使其饱受批评。

曾经也有短暂尝试过创建 持续文档 Continuous Documentation ,并且还有一个来自 CA(现在的 Broadcom)的创建 DocOps 框架的运动。然而,DocOps 从来没有作为一个行业运动流行起来。

DevOps 文档标准的现状意味着 DevOps 团队(包括技术写手)需要在项目的最初阶段就开始创建文档。要做到这一点,你需要把文档作为一个敏捷故事和(同样重要的)管理期望,并且把它与年度绩效评估放在一起执行。

文档工具

文档的编写应该以一种所有团队成员都可以使用的格式或平台在线进行。MediaWiki、DokuWiki、TikiWiki 和其他 开源维基 为 DevOps 团队提供了一个编写和维护文档的中央仓库。

让团队选择他们的维基平台,就像让他们选择他们的其他持续集成/持续开发(CI/CD)工具链一样。开源维基强大之处在于其可扩展性。例如,DokuWiki 包括一系列的扩展,你可以通过安装这些扩展来创建一个符合你的 DevOps 团队的创作要求的平台。

如果你有足够的野心来加强你的团队的编写和协作能力,Nextcloud(一个开源的云协作套件)是一个让你的 DevOps 团队上网并给他们提供编写文档所需工具的选择。

DevOps 最佳实践

文档在 DevOps 转型中也发挥着作用。例如,你会想要记录组织从 DevOps 实现效率和流程增益的最佳实践,这些信息太重要了,不能靠着 DevOps 团中之间口耳相传。如果你所在的组织有多个 DevOps 团队,那么文档就是统一的力量,它可以促进最佳实践的标准化,并设置了衡量代码质量的基准指标。

一般情况下,开发人员承担了记录 DevOps 实践的工作。即使他们的组织有技术写手,他们也可能跨开发团队工作。因此,开发人员和系统管理员能够捕捉、记录和交流他们的最佳实践是很重要的。这里有一些朝正确的方向发展的提示:

  • 提前花时间为 DevOps 最佳实践创建标准模板。不要陷入复制在线模板的陷阱。采访利益相关者和团队来创建一个符合团队需求的模板。
  • 寻找一些创造性的信息收集的方法,例如记录团队会议和使用聊天系统日志来作为文档的基础。
  • 建立一个用于发布最佳实践的维基。使用维基可以跟踪编辑和更新。这样的平台可以帮助团队在最佳实践发生变化时进行更新和维护。

当在构建 CI/CD 工具链时记录依赖关系是非常明智的。尤其是当加入新的团队成员时,你会发现这些记录非常有用,另外当团队成员忘记一些事情时,这也是一种保险。

最后,自动化对 DevOps 利益相关者和从业者都很有吸引力。在自动化中断之前,一切都很有趣。拥有自动化运行手册、管理指南和其他内容的文档(并且是最新的)意味着无论何时发生故障,员工都可以让自动化重新工作。

最后一些想法

DevOps 对于技术文档来说是一个积极的因素。它将内容开发纳入 DevOps 生命周期,并打破组织文化中开发人员和技术作者之间的隔阂。在没有技术写手的情况下,团队就可以使用工具来加快文档创作的速度,以与 DevOps 的速度相匹配。

你的组织将如何把文档加入到 DevOps 生命周期?请在评论区分享你的经验。


via: https://opensource.com/article/21/3/devops-documentation

作者:Will Kelly 选题:lujun9972 译者:Veryzzj 校对:校对者ID

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