标签 Flutter 下的文章

Canonical 是否计划用这个基于 Flutter 的应用程序取代 Ubuntu 软件中心?也许是,也许不是。

Ubuntu 通常被认为 是最适合初学者的发行版之一,但默认的软件中心(GNOME 软件中心 Software Center )需要更多的打磨才能使其成为令人愉悦的体验。

为什么?嗯,它很慢而且占用资源很多,所以大多数用户不会费心使用它,或者使用感受很糟糕。

是的,多年来它可能有所改善,但仍远非良好的体验。

它看起来像是来自 Canonical 的贡献者,而其他人已经联手为 Ubuntu 软件中心开发一个轻量级、基于 Flutter 的替代方案!

等等,它 不是官方替代品。但是,我想知道它是否打算很快取代 Ubuntu 软件中心??

? 使用 Flutter 制作的 “Ubuntu 软件”

ubuntu software built with flutter

这个使用 Flutter 实现的 “ Ubuntu 软件 Ubuntu Software ”旨在实现轻量级、自适应和快速,提供比传统软件更好的用户体验。

但首要因素必须是可用性,对吧?因为最后,你只是为了安装软件。而且,你想快速完成,没有任何麻烦。

当我在我的系统上尝试它时,我注意到“我的应用程序”下有一个单独的 “Snaps” 和 “Deb 包”部分:

separate section for deb and snap packages in ubuntu software

这应该便于处理单个应用程序中的不同包。毕竟,这是我一直想要的!

轻松安装/管理应用程序的统一体验,是不是要求太多了? ?

但是应用信息和安装页面呢?好吧,它已经过重新设计,带有微妙的动画以增强体验。

app info section in unofficial ubuntu software

自适应布局简直就是锦上添花。这有点类似于 elementary OS 7 为我们准备的:

elementary OS 7 准备添加响应式应用程序,并移植到 GTK 4

所以,它看起来像是对未来的一个深思熟虑的实现,对吧?

adaptive layout in unofficial ubuntu software center

它会取代 Ubuntu 软件吗?

虽然项目贡献者将其标记为 Ubuntu 软件中心的非官方替代品,但我认为它更像是一个尝试作为替代品的实验。

考虑到负责 Ubuntu 上 Flutter 的高级工程师 @Canonical JP Nurmi 参与其中,这将是一件值得期待的事情

我们现在唯一能做的就是“预测”。随着事情的发展,这似乎有更多的机会成为官方的。

想尝试这个基于 Flutter 的商店吗?

你可以前往它的 GitHub 页面 并按照构建说明让它运行。请注意,截至目前,它正在大力开发中。

下载 Ubuntu 软件

对于正在积极开发的东西来说,它的效果相当好。

? 我希望当前的软件中心被取代。你怎么看?在下面的评论中让我知道你的想法!


via: https://news.itsfoss.com/unofficial-flutter-ubuntu-software/

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

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

保护开源软件需要多少钱?OpenSSF 称 1.5 亿美元

在华盛顿特区刚刚举行的第二届开源软件安全峰会上,OpenSSF 宣布了一项雄心勃勃、多管齐下的计划,有 10 个关键目标,以更好地保护整个开源软件生态系统。OpenSSF 估计,其计划在两年内将需要约 1.5 亿美元的资金,目前成员已经认捐了 3000 万美元。

消息来源:venturebeat
老王点评:确实,开源软件有一些历史问题需要专门投入人力和资金解决夯实一下。真要是花了这么多钱能解决大部分主要问题,也是好的。

DeepMind 的最新人工智能可以执行 600 多项任务

DeepMind 本周发布了一个名为 Gato 的“通用”人工智能系统,一个可以被教导执行许多不同类型任务的系统。研究人员训练 Gato 完成了 604 项任务,包括给图像加标题,进行对话,用真正的机器人手臂堆积积木,以及玩雅达利游戏等等。Gato 不一定总是能很好地完成这些任务,DeepMind 称,Gato 在一半以上的时间里表现得比专家好。Gato 的参数比 GPT-3 的 1700 亿个参数要小几个数量级,只有 12 亿个。

消息来源:techcrunch
老王点评:虽然距离通用人工智能还有一定距离,在理解和学习人类所能完成的任何任务的能力方面还远远不够,但是也是很可喜的进步了。

谷歌发布 Flutter 3

谷歌在几年前创建了 Flutter,目的是做一个跨平台的软件框架。Flutter 可以为安卓、iOS 构建应用程序,而且都来自同一个共享的代码库。Flutter 在今年 2 月份为 Windows 平台提供了稳定支持,但 macOS 和 Linux 仍然只处于测试阶段。在今年的谷歌 I/O 大会上宣布的 Flutter 3,对 macOS 和 Linux 的应用构建也提供了稳定支持。对 Linux 的支持是与 Canonical 合作提供的,Canonical 已经用 Flutter 开发了一些关键应用,包括软件安装和固件更新。

消息来源:xda
老王点评:正如谷歌注意到的,跨平台不仅仅是生成各个平台的二进制,更重要的是,要符合各个平台的体验。

谷歌的 UI 工具包 Flutter 在创建移动、网页和桌面的跨平台应用程序方面越来越受欢迎。

Flutter 不是一种编程语言,而是一个软件开发工具包。Dart 是 Flutter SDK 下面使用的编程语言。

Flutter 是谷歌开源的 Fuchsia OS、谷歌 STADIA 以及许多其他软件和移动应用背后的主要框架。

如果你想使用 Flutter 进行开发,本教程将帮助你在 Ubuntu 和其他类似 Linux 发行版上搭建好你的环境。

在 Ubuntu 和其他 Linux 上用 Snap 安装 Flutter

在 Linux 上安装 Flutter 最简单的方法是使用 Snap。如果你使用的是 Ubuntu,你已经有了 Snap。对于其他发行版,请确保 启用 Snap 支持

打开终端 并在终端中使用以下命令来安装 Flutter:

sudo snap install flutter --classic

你会在你的终端上看到类似这样的东西:

一旦安装完成,就是验证它的时候了。不仅仅是 Flutter 的安装,还要验证 Flutter 正常运行所需满足的每一个依赖关系。

验证 Flutter 的依赖项

为了验证 Flutter 正确工作所需的每一个依赖项,Flutter 有一个内置选项:

Flutter doctor

这个过程开始看起来像这样:

而它完成时像这样:

正如你所看到的,我们需要 Android Studio 来工作。所以让我们来安装它。我们该怎么做呢?用 Snap 在 Linux 上安装 Android Studio 也是毫不费力的。

安装并设置好 Android Studio

在终端中,使用下面的命令来安装 Android Studio:

sudo snap install android-studio --classic

安装完毕后,从我们的操作系统菜单中打开 Android Studio。

就快完成了。现在是配置 Android Studio 的时候了。

点击下一步,如果你不想让事情复杂化,就选择“ 标准 standard ”。

选择你喜欢的主题(我喜欢“ 暗色 Darcula ”的)。

确认一切正常,然后点击“ 下一步 Next ”。

最后,点击“ 完成 Finish ”按钮。

然后等待,直到下载完成。

创建一个 Hello World Flutter 应用样本

在 Android Studio 中,进入项目,选择“ 新建 Flutter 项目 New Flutter Project ”。Flutter SDK 路径会默认设置。

在这里,神奇的事情开始出现了,这是你设置你的项目名称的地方,在这个例子中,它将被称为 “hello\_world”。

让我们选择三个可用的平台。Android、iOS 和 Web。最后,点击“ 完成 Finish ”。

项目中的主文件位于 lib/main.dart,如下图所示:

选定后,擦除文件中包含的所有内容,并将其改为本示例代码:

// Copyright 2018 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Welcome to Flutter'),
        ),
        body: const Center(
          child: Text('Hello World'),
        ),
      ),
    );
  }
}

重要的是,这只是向你展示 Flutter 是如何工作的,如果你确信要学习这种美丽而不可思议的语言,这里有 文档 可以看到更多关于它的信息。尝试它!

最后,选择 “Chome Web” 设备,并点击“ 运行 Run ”按钮,如下图所示;并看到神奇的效果!

你可以如此快速地创建一个 Flutter 项目,真是不可思议。跟你的 Hello World 项目打个招呼吧。

最后...

如果你想在短时间内做出漂亮的移动和网页界面的贡献,Flutter 和 Dart 是完美的。

现在你知道了如何在 Ubuntu Linux 上安装 Flutter,以及如何用它创建你的第一个应用程序。我很高兴可以为你写这篇文章,希望对你有所帮助,如果你有任何问题,请通过留言或给我发邮件来告诉我,祝你好运!

本教程由 Marco Antonio Carmona Galván 提供,他是物理学和数据科学专业的学生。


via: https://itsfoss.com/install-flutter-linux/

作者:Marco Antonio Carmona Galván 选题:lujun9972 译者:wxy 校对:wxy

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

了解如何创建 Flutter 应用的界面以及如何在它们之间进行数据传递。

Flutter 是一个流行的开源工具包,它可用于构建跨平台的应用。在文章《用 Flutter 创建移动应用》中,我已经向大家展示了如何在 Linux 中安装 Flutter 并创建你的第一个应用。而这篇文章,我将向你展示如何在你的应用中添加一个列表,点击每一个列表项可以打开一个新的界面。这是移动应用的一种常见设计方法,你可能以前见过的,下面有一个截图,能帮助你对它有一个更直观的了解:

 title=

Flutter 使用 Dart 语言。在下面的一些代码片段中,你会看到以斜杠开头的语句。两个斜杠(//)是指代码注释,用于解释某些代码片段。三个斜杠(///)则表示的是 Dart 的文档注释,用于解释 Dart 类和类的属性,以及其他的一些有用的信息。

查看Flutter应用的主要部分

Flutter 应用的典型入口点是 main() 函数,我们通常可以在文件 lib/main.dart 中找到它:

void main() {
 runApp(MyApp());
}

应用启动时,main() 会被调用,然后执行 MyApp()MyApp 是一个无状态微件(StatelessWidget),它包含了MaterialApp() 微件中所有必要的应用设置(应用的主题、要打开的初始页面等):

class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     title: 'Flutter Demo',
     theme: ThemeData(
       primarySwatch: Colors.blue,
       visualDensity: VisualDensity.adaptivePlatformDensity,
     ),
     home: MyHomePage(title: 'Flutter Demo Home Page'),
   );
 }
}

生成的 MyHomePage() 是应用的初始页面,是一个有状态的微件,它包含包含可以传递给微件构造函数参数的变量(从上面的代码看,我们传了一个 title 变量给初始页面的构造函数):

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

有状态微件(StatefulWidget)表示这个微件可以拥有自己的状态:_MyHomePageState。调用 _MyHomePageState 中的 setState() 方法,可以重新构建用户界面:

class _MyHomePageState extends State<MyHomePage> {
 int _counter = 0; // Number of taps on + button.

 void _incrementCounter() { // Increase number of taps and update UI by calling setState().
   setState(() {
     _counter++;
   });
 }
 ...
}

不管是有状态的,还是无状态的微件,它们都有一个 build() 方法,该方法负责微件的 UI 外观。

@override
Widget build(BuildContext context) {
 return Scaffold( // Page widget.
   appBar: AppBar( // Page app bar with title and back button if user can return to previous screen.
     title: Text(widget.title), // Text to display page title.
   ),
   body: Center( // Widget to center child widget.
     child: Column( // Display children widgets in column.
       mainAxisAlignment: MainAxisAlignment.center,
       children: <Widget>[
         Text( // Static text.
           'You have pushed the button this many times:',
         ),
         Text( // Text with our taps number.
           '$_counter', // $ sign allows us to use variables inside a string.
           style: Theme.of(context).textTheme.headline4,// Style of the text, “Theme.of(context)” takes our context and allows us to access our global app theme.
         ),
       ],
     ),
   ),
        // Floating action button to increment _counter number.
   floatingActionButton: FloatingActionButton(
     onPressed: _incrementCounter,
     tooltip: 'Increment',
     child: Icon(Icons.add),
   ),
 );
}

修改你的应用

一个好的做法是,把 main() 方法和其他页面的代码分开放到不同的文件中。要想将它们分开,你需要右击 lib 目录,然后选择 “New > Dart File” 来创建一个 .dart 文件:

 title=

将新建的文件命名为 items_list_page

切换回到 main.dart 文件,将 MyHomePage_MyHomePageState 中的代码,剪切并粘贴到我们新建的文件。然后将光标放到 StatefulWidget 上(下面红色的下划线处), 按 Alt+Enter 后出现下拉列表,然后选择 package:flutter/material.dart

 title=

经过上面的操作我们将 flutter/material.dart 包添加到了 main.dart 文件中,这样我们就可以使用 Flutter 提供的默认的 material 主题微件。

然后, 在类名 MyHomePage 右击,“Refactor > Rename...”将其重命名为 ItemsListPage

 title=

Flutter 识别到你重命名了 StatefulWidget 类,它会自动将它的 State 类也跟着重命名:

 title=

回到 main.dart 文件,将文件名 MyHomePage 改为 ItemsListPage。 一旦你开始输入, 你的 Flutter 集成开发环境(可能是 IntelliJ IDEA 社区版、Android Studio 和 VS Code 或 VSCodium),会给出自动代码补完的建议。

 title=

按回车键即可完成输入,缺失的导入语句会被自动添加到文件的顶部。

 title=

到此,你已经完成了初始设置。现在你需要在 lib 目录创建一个新的 .dart 文件,命名为 item_model。(注意,类命是大写驼峰命名,一般的文件名是下划线分割的命名。)然后粘贴下面的代码到新的文件中:

/// Class that stores list item info:
/// [id] - unique identifier, number.
/// [icon] - icon to display in UI.
/// [title] - text title of the item.
/// [description] - text description of the item.
class ItemModel {
 // class constructor
 ItemModel(this.id, this.icon, this.title, this.description);

 // class fields
 final int id;
 final IconData icon;
 final String title;
 final String description;
}

回到 items_list_page.dart 文件,将已有的 _ItemsListPageState 代码替换为下面的代码:

class _ItemsListPageState extends State<ItemsListPage> {

// Hard-coded list of [ItemModel] to be displayed on our page.
 final List<ItemModel> _items = [
   ItemModel(0, Icons.account_balance, 'Balance', 'Some info'),
   ItemModel(1, Icons.account_balance_wallet, 'Balance wallet', 'Some info'),
   ItemModel(2, Icons.alarm, 'Alarm', 'Some info'),
   ItemModel(3, Icons.my_location, 'My location', 'Some info'),
   ItemModel(4, Icons.laptop, 'Laptop', 'Some info'),
   ItemModel(5, Icons.backup, 'Backup', 'Some info'),
   ItemModel(6, Icons.settings, 'Settings', 'Some info'),
   ItemModel(7, Icons.call, 'Call', 'Some info'),
   ItemModel(8, Icons.restore, 'Restore', 'Some info'),
   ItemModel(9, Icons.camera_alt, 'Camera', 'Some info'),
 ];

 @override
 Widget build(BuildContext context) {
   return Scaffold(
       appBar: AppBar(
         title: Text(widget.title),
       ),
       body: ListView.builder( // Widget which creates [ItemWidget] in scrollable list.
         itemCount: _items.length, // Number of widget to be created.
         itemBuilder: (context, itemIndex) => // Builder function for every item with index.
             ItemWidget(_items[itemIndex], () {
           _onItemTap(context, itemIndex);
         }),
       ));
 }

 // Method which uses BuildContext to push (open) new MaterialPageRoute (representation of the screen in Flutter navigation model) with ItemDetailsPage (StateFullWidget with UI for page) in builder.
 _onItemTap(BuildContext context, int itemIndex) {
   Navigator.of(context).push(MaterialPageRoute(
       builder: (context) => ItemDetailsPage(_items[itemIndex])));
 }
}


// StatelessWidget with UI for our ItemModel-s in ListView.
class ItemWidget extends StatelessWidget {
 const ItemWidget(this.model, this.onItemTap, {Key key}) : super(key: key);

 final ItemModel model;
 final Function onItemTap;

 @override
 Widget build(BuildContext context) {
   return InkWell( // Enables taps for child and add ripple effect when child widget is long pressed.
     onTap: onItemTap,
     child: ListTile( // Useful standard widget for displaying something in ListView.
       leading: Icon(model.icon),
       title: Text(model.title),
     ),
   );
 }
}

为了提高代码的可读性,可以考虑将 ItemWidget 作为一个单独的文件放到 lib 目录中。

现在唯一缺少的是 ItemDetailsPage 类。在 lib 目录中我们创建一个新文件并命名为 item_details_page。然后将下面的代码拷贝进去:

import 'package:flutter/material.dart';

import 'item_model.dart';

/// Widget for displaying detailed info of [ItemModel]
class ItemDetailsPage extends StatefulWidget {
 final ItemModel model;

 const ItemDetailsPage(this.model, {Key key}) : super(key: key);

 @override
 _ItemDetailsPageState createState() => _ItemDetailsPageState();
}

class _ItemDetailsPageState extends State<ItemDetailsPage> {
 @override
 Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(
       title: Text(widget.model.title),
     ),
     body: Center(
       child: Column(
         children: [
           const SizedBox(height: 16),
           Icon(
             widget.model.icon,
             size: 100,
           ),
           const SizedBox(height: 16),
           Text(
             'Item description: ${widget.model.description}',
             style: TextStyle(fontSize: 18),
           )
         ],
       ),
     ),
   );
 }
}

上面的代码几乎没什么新东西,不过要注意的是 _ItemDetailsPageState 里使用了 widget.item.title 这样的语句,它让我们可以从有状态类中引用到其对应的微件(StatefulWidget)。

添加一些动画

现在让我们来添加一些基础的动画:

  1. 找到 ItemWidget 代码块(或者文件)
  2. 将光标放到 build() 方法中的 Icon() 微件上
  3. Alt+Enter,然后选择“Wrap with widget...”

 title=

输入 Hero,然后从建议的下拉列表中选择 Hero((Key key, @required this, tag, this.create))

 title=

下一步, 给 Hero 微件添加 tag 属性 tag: model.id

 title=

最后我们在 item_details_page.dart 文件中做相同的修改:

 title=

前面的步骤,其实我们是用 Hero() 微件对 Icon() 微件进行了封装。还记得吗?前面我们定义 ItemModel 类时,定义了一个 id field,但没有在任何地方使用到。因为 Hero 微件会为其每个子微件添加一个唯一的标签。当 Hero 检测到不同页面(MaterialPageRoute)中存在相同标签的 Hero 时,它会自动在这些不同的页面中应用过渡动画。

可以在安卓模拟器或物理设备上运行我们的应用来测试这个动画。当你打开或者关闭列表项的详情页时,你会看到一个漂亮的图标动画:

 title=

收尾

这篇教程,让你学到了:

  • 一些符合标准的,且能用于自动创建应用的组件。
  • 如何添加多个页面以及在页面间传递数据。
  • 如何给多个页面添加简单的动画。

如果你想了解更多,查看 Flutter 的 文档(有一些视频和样例项目的链接,还有一些创建 Flutter 应用的“秘方”)与 源码,源码的开源许可证是 BSD 3。


via: https://opensource.com/article/20/11/flutter-lists-mobile-app

作者:Vitaly Kuprenko 选题:lujun9972 译者:ywxgod 校对:wxy

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

Equinix 推出“时间即服务”

许多行业和云服务都依赖于精确、可靠和安全的时间同步。传统的、基于天线的 GPS 授时基础设施解决方案可能难以安装,并会带来安全漏洞。同时,从互联网上利用公开 NTP 服务器授时也有网络安全风险。

数字基础设施公司 Equinix 正在推出的 Precision Time 服务旨在解决这个挑战。Equinix 管理和维护一个由 GPS 天线、带有原子钟保持器的时间服务器及主时钟组成的冗余堆栈。新服务支持 NTP 和 PTP 等网络授时协议。该服务提供 50 微秒的 SLA,要比大多数时间同步精度要求高得多。

连时间都能成为服务,听起来有趣,但是其实有一定的必要性。

2020 年三分之二的 Google 搜索没有带来进一步点击

2019 年的一项研究发现,50.33% 的 Google 搜索没有导致外链点击。2020 年这一比例进一步提高到三分之二左右。这一数据来自 SimilarWeb 对 2020 年 51 万亿次 Google 搜索的分析。在这些搜索中,33.59% 点击了搜索结果,1.59% 点击了付费搜索结果,其余 64.82% 则是零点击。

看来通用搜索引擎的有效性越来越差了,难怪现在有很多垂直搜索引擎出现。

Canonical 将谷歌的 Flutter 视为未来桌面和移动应用的默认选择

Flutter 是一个使用 Dart 语言的框架,可以开发跨 Android、iOS、Windows、Linux、macOS 和 Web 的应用,不过 macOS 和 Linux 版本尚处于测试阶段。尽管如此,为了扩大 Linux 应用生态系统,Ubuntu 的开发商 Canonical 上个月还是宣布将用 Flutter 构建新的桌面安装程序,并向开发者表示“Flutter 是 Canonical 未来创建的桌面和移动应用的默认选择”。

Flutter 的性能比 Electron 等替代品更好,虽然它的性能不如原生开发平台,但它跨操作系统开发的能力超过了这种差异。跨平台开发不仅仅意味着 Linux 开发者可以为其他平台编写应用,还意味着任何其他平台的 Flutter 开发者都可以将他们的应用贡献给 Linux,从而扩大 Linux 应用生态系统。

这是一个看起来不错的选择,但是 Flutter 并不是第一个以跨平台为主要卖点的框架,而之前的类似框架并未真正给 Linux 带来多少重要应用,所以将来的发展需要拭目以待。

写字的纸条就能骗过 OpenAI 的物体识别

OpenAI 的研究人员发现了一种令人震惊的简单方法来蒙蔽他们的对象识别软件,而且只需要笔和纸就可以进行。只要在一张纸上写上 “iPod” 的字样,贴在一只苹果上,就能骗过他们最新的计算机视觉模型 CLIP,该软件会错误地将这个水果归类为音乐播放器。

研究人员认为,像这样的攻击远非单纯的学术问题,通过利用模型强大的文字阅读能力,即使是手写文字的照片也经常可以欺骗模型。OpenAI 的模型是使用文本的图片以及从互联网上搜刮的物体图像进行训练的,因此被所谓这种“排版攻击”误导也不足为奇。

这种所谓的“智能”,有时候还是很笨拙的,没有“智慧”的“智能”始终也只是算法和数据而已。

谷歌的多平台应用框架 Flutter 发布 2.0,支持 Web 应用

Flutter 允许开发者创建一个单一的代码库,可以为 Android、iOS、Windows、macOS 和 Linux、Web 和嵌入式设备生成应用,不过桌面操作系统的支持还不稳定。最重要的是,Flutter 2.0 从主要是一个移动平台,拓展到现在可以真正实现跨移动、桌面、Web 和嵌入式的可移植性。

谷歌的大量应用都依赖于 Flutter,这包括 Google One、Google Pay、Nest Hub、Google Ads、Google Shopping、Google Analytics、Cloud Search 等等。

这样一个重要的里程碑版本,值得开发者们学习了解一下。不过,新东西太多了,感觉有点学不过来了。

RHEL 自助服务的价格翻了一番,但是软件没变

2019 年红帽公司下线了其 RHEL Server 自助服务(RH0197181),而被 RHEL Server 入门级自助服务(RH00005)所取代。它们的售价都是 349 美元,但只有停售那款才允许使用最低程度的虚拟功能。现在客户发现,需要支付两倍以上的费用(每年 799 美元)才能在虚拟机中运行 RHEL。换言之,你想不要红帽的技术支持就运行虚拟机,也必须多花一倍的钱,哪怕你真的不需要那些技术支持。

在红帽公司停止其免费的 CentOS 之后,该公司已经明确表示,它对那些只付很少费用或不付费用的用户没有什么兴趣。即便是为了安抚不满的 CentOS 用户而推出的 RHEL 开发者订阅,根据使用条款,不允许用在企业生产环境。而现在,对 RHEL 商业客户也开始层层加码,我觉得,可能红帽的营收压力太大了。