PostgreSQL编译安装常见报错整理

PostgreSQL源码安装时如果相关依赖包缺失会导致编译失败,以下是常见的依赖包缺失问题,及解决办法。 依赖安装: yum install -y perl-ExtUtils-Embed readline-devel zlib-devel pam-devel ...
继续阅读 »

PostgreSQL源码安装时如果相关依赖包缺失会导致编译失败,以下是常见的依赖包缺失问题,及解决办法。


依赖安装:


yum install -y perl-ExtUtils-Embed readline-devel zlib-devel pam-devel libxml2-devel libxslt-devel openldap-devel python-devel gcc-c++   openssl-devel cmake

问题1:


checking for flags to link embedded Perl... Can't locate ExtUtils/Embed.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .).BEGIN failed--compilation aborted.

configure: error: could not determine flags for linking embedded Perl.This probably means that ExtUtils::Embed or ExtUtils::MakeMaker is not installed.

解决:


yum install perl-ExtUtils-Embed

问题2:


configure: error: readline library not found  If you have readline already installed, see config.log for details on the failure.  
It is possible the compiler isn't looking in the proper directory. Use --without-readline to disable readline support.

解决:


yum install readline  readline-devel

问题3:


checking for inflate in -lz... no configure: error: zlib library not found
If you have zlib already installed, see config.log for details on the failure. It is possible the compiler isn't looking in the proper directory.
Use --without-zlib to disable zlib support.

解决:


yum install zlib zlib-devel

问题4:


checking for CRYPTO_new_ex_data in -lcrypto... no
configure: error: library 'crypto' is required for OpenSSL

解决:


yum -y install opensll openssl-devel

问题5:


checking for pam_start in -lpam... no
configure: error: library 'pam' is required for PAM

解决:


yum -y install pam pam-devel

问题6:


checking for xmlSaveToBuffer in -lxml2... no
configure: error: library 'xml2' (version >= 2.6.23) is required for XML support

解决:


yum -y install libxml2 libxml2-devel

问题7:


checking for xsltCleanupGlobals in -lxslt... no
configure: error: library 'xslt' is required for XSLT support

解决:


yum -y install libxslt  libxslt-devel

问题8:


checking for ldap.h... no
configure: error: header file is required for LDAP

解决:


yum -y install openldap  openldap-devel

问题9:


checking for Python.h... no
configure: error: header file is required for Python

解决:


yum -y install python-devel

问题10:


Error when bootstrapping CMake: Cannot find appropriate C++ compiler on this system.
Please specify one using environment variable CXX.
See cmake_bootstrap.log for compilers attempted.

解决:


yum -y install gcc-c++

插件报错:


2020-05-06 06:17:12.624 UTC [1] FATAL:  could not access file "pglogical": No such file or directory
2020-05-06 06:17:12.624 UTC [1] LOG: database system is shut down

解决参考: https://www.cnblogs.com/lottu/p/10972773.html , pg_pathman: https://www.cnblogs.com/guoxiangyue/p/10894467.html

收起阅读 »

常见系统glibc版本列表

操作系统 操作系统位数 Glibc版本 Centos4.0 32bit ldd (GNU libc) 2.3.4 Centos5.0 32bit ldd (GNU libc) 2.5 Centos3.1 64bit ldd (GNU libc) 2.3.2 C...
继续阅读 »























































































操作系统 操作系统位数 Glibc版本
Centos4.0 32bit ldd (GNU libc) 2.3.4
Centos5.0 32bit ldd (GNU libc) 2.5
Centos3.1 64bit ldd (GNU libc) 2.3.2
Centos3.3 64bit ldd (GNU libc) 2.3.2
Centos4.0 64bit ldd (GNU libc) 2.3.4
Centos5.0 64bit ldd (GNU libc) 2.5
Centos6.0 64bit ldd (GNU libc) 2.12
Centos6.5 64bit ldd (GNU libc) 2.12
Centos7.* 64bit ldd (GNU libc) 2.17
Redhat6.5 64bit ldd (GNU libc) 2.12
Redhat7.0 64bit ldd (GNU libc) 2.17
Redhat7.3 64bit ldd (GNU libc) 2.17
Debian6.0 32bit ldd (Debian EGLIBC 2.11.3-4) 2.11.3
Debian7.0 32bit ldd (Debian EGLIBC 2.13-38+deb7u12) 2.13
Debian7.0 64bit ldd (Debian EGLIBC 2.13-38+deb7u12) 2.13
Suse9.0 32bit ldd (GNU libc) 2.3.5
Suse9.1 64bit ldd (GNU libc) 2.3.3
Suse10.0 32bit ldd (GNU libc) 2.4
Suse10.0 64bit ldd (GNU libc) 2.3.5
Suse11.0 64bit ldd (GNU libc) 2.11.1
Suse12.0 64bit ldd (GNU libc) 2.19
OpenSuse42 64bit ldd (GNU libc) 2.19
fedora22 64bit ldd (GNU libc) 2.22
ubuntu12 64bit ldd (Ubuntu EGLIBC 2.15-0ubuntu10.6) 2.15
ubuntu14 64bit ldd (Ubuntu EGLIBC 2.19-0ubuntu6.9) 2.19
Asianux Server 3 64bit ldd (GNU libc) 2.5
Power Linux 6.5 64bit ldd (GNU libc) 2.12
Power Linux7.3 64bit ldd (GNU libc) 2.17

以后在补充一些常见系统过得Glibc版本。

收起阅读 »

linux下LD_LIBRARY_PATH介绍

LD_LIBRARY_PATH是Linux环境变量名,该环境变量主要用于指定查找共享库(动态链接库)时除了默认路径之外的其他路径。 非常多的软件没有root权限安装会比较困难,主要就是因为各种系统库文件,也就是LD_LIBRARY_PATH这个环境变量里面的文...
继续阅读 »

LD_LIBRARY_PATH是Linux环境变量名,该环境变量主要用于指定查找共享库(动态链接库)时除了默认路径之外的其他路径。


非常多的软件没有root权限安装会比较困难,主要就是因为各种系统库文件,也就是LD_LIBRARY_PATH这个环境变量里面的文件。比如前面我提到的lancet软件需要的库文件如下:


-llzma -lbz2 -lz -ldl -lpthread -lcurl -lcrypto -lbamtools

可以使用 ls /usr/lib |grep lib 查看自己是否有需要的库文件,当然还需查看其它库文件目录:echo $LD_LIBRARY_PATH 里面一般可以看到七八个已经定义好的库文件搜索路径。


当执行函数动态链接.so时,如果此文件不在缺省目录下 /lib和/usr/lib,那么就需要指定环境变量LD_LIBRARY_PATH 假如现在需要在已有的环境变量上添加新的路径名,则采用如下方式: LD_LIBRARY_PATH=NEWDIRS:$LD_LIBRARY_PATH (newdirs是新的路径串), 实例如下:


export LD_LIBRARY_PATH=/export/apps/anaconda2/2.4.1/lib/:$LD_LIBRARY_PATH

一般报错:


/usr/bin/ld: cannot find -llzma
collect2: error: ld returned 1 exit status
make[1]: *** [lancet] Error 1
make[1]: Leaving directory `/home/bobo/biosoft/lancet/lancet/src'
cp: cannot stat `lancet': No such file or directory

其实就是gcc编辑器找不到我们系统的liblzma这个库文件,就是我们的LD_LIBRARY_PATH定义的所有路径里面都没有这个liblzma这个库文件。


验证gcc编辑器能否找到指定库文件的方法是:


gcc -llzma --verbose

需要找到系统的库文件地址

事实上,我们的机器肯定是有这个库文件的,只不过是不在LD_LIBRARY_PATH定义的所有路径里面,简单查找如下:


locate liblzma 
/export/apps/anaconda2/2.4.1/lib/liblzma.a
/export/apps/anaconda2/2.4.1/lib/liblzma.la
/export/apps/anaconda2/2.4.1/lib/liblzma.so
/export/apps/anaconda2/2.4.1/lib/liblzma.so.5
/export/apps/anaconda2/2.4.1/lib/liblzma.so.5.0.5

为了解决我,我们需要添加:


export LD_LIBRARY_PATH=/export/apps/anaconda2/4.0.0/lib/:$LD_LIBRARY_PATH
export LIBRARY_PATH=/export/apps/anaconda2/4.0.0/lib/:$LIBRARY_PATH

为什么修改LD_LIBRARY_PATH呢

因为运行时动态库的搜索路径的先后顺序是:
1.编译目标代码时指定的动态库搜索路径;
2.环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
3.配置文件/etc/ld.so.conf中指定的动态库搜索路径;
4.默认的动态库搜索路径/lib和/usr/lib;

这个顺序是compile gcc时写在程序内的,通常软件源代码自带的动态库不会太多,而我们的/lib和/usr/lib只有root权限才可以修改,而且配置文件/etc/ld.so.conf也是root的事情,我们只好对LD_LIBRARY_PATH进行操作啦。


永久性添加

每次我使用该软件都需要临时修改库文件,因为上面的方法是临时设置环境变量 LD_LIBRARY_PATH ,重启或打开新的 Shell 之后,一切设置将不复存在。


为了让这种方法更完美一些,可以将该 LD_LIBRARY_PATH 的 export 语句写到系统文件中,例如 /etc/profile、/etc/export、~/.bashrc 或者 ~/.bash_profile 等等,取决于你正在使用的操


虽然LD_LIBRARY_PATH很方便,但是还是推荐大家在编译的时候指定-rpath来执行相对路径来找到动态链接库文件。

收起阅读 »

Prometheus配置文件热加载

Promtheus的TSDB时序数据库在存储了大量的数据后,每次重启Prometheus进程的时间会越来越慢, 而且日常运维工作中会经常调整Prometheus的配置文件信息,比如一些静态配置,实际上Prometheus提供了在运行时热加载配置信息的功能,在这...
继续阅读 »

Promtheus的TSDB时序数据库在存储了大量的数据后,每次重启Prometheus进程的时间会越来越慢, 而且日常运维工作中会经常调整Prometheus的配置文件信息,比如一些静态配置,实际上Prometheus提供了在运行时热加载配置信息的功能,在这里介绍一下。


Prometheus配置热加载提供了2种方法:


  1. kill -HUP pid 发送SIGHUP信号方法
  2. 通过Prometheus服务API接口,发送发送一个POST请求到/-/reload

Tips: 从 Prometheus2.0 开始,热加载功能是默认关闭的,如需开启,需要在启动 Prometheus 的时候,添加 --web.enable-lifecycle 参数。



我个人更倾向于采用curl -XPOST http://localhost:9090/-/reload 的方式,因为每次reload过后, pid会改变,使用kill方式需要找到当前进程号。


如果配置热加载成功,Prometheus会打印出下面的log:


... msg="Loading configuration file" filename=prometheus.yml ...

下面我们来看看这两种方式内部实现原理。


第一种方法: 通过 kill 命令的 HUP (hang up) 参数实现
首先Prometheus在 cmd/promethteus/main.go 中实现了对进程系统调用监听,如果收到syscall.SIGHUP信号,将执行reloadConfig函数。


代码类似如下:


{
// Reload handler.

// Make sure that sighup handler is registered with a redirect to the channel before the potentially
// long and synchronous tsdb init.
hup := make(chan os.Signal, 1)
signal.Notify(hup, syscall.SIGHUP)
cancel := make(chan struct{})
g.Add(
func() error {
<-reloadReady.C

for {
select {
case <-hup:
if err := reloadConfig(cfg.configFile, logger, noStepSubqueryInterval, reloaders...); err != nil {
level.Error(logger).Log("msg", "Error reloading config", "err", err)
}
case rc := <-webHandler.Reload():
if err := reloadConfig(cfg.configFile, logger, noStepSubqueryInterval, reloaders...); err != nil {
level.Error(logger).Log("msg", "Error reloading config", "err", err)
rc <- err
} else {
rc <- nil
}
case <-cancel:
return nil
}
}

},
func(err error) {
// Wait for any in-progress reloads to complete to avoid
// reloading things after they have been shutdown.
cancel <- struct{}{}
},
)
}

第二种:通过 web 模块的 /-/reload请求实现:


首先 Prometheus 在 web(web/web.go) 模块中注册了一个 POST 的 http 请求 /-/reload, 它的 handler 是 web.reload 函数,该函数主要向 web.reloadCh chan 里面发送一个 error。


其次在Prometheus 的cmd/promethteus/main.go中有个单独的 goroutine 来监听web.reloadCh,当接受到新值的时候会执行 reloadConfig 函数。


func() error {
<-reloadReady.C

for {
select {
case <-hup:
if err := reloadConfig(cfg.configFile, logger, noStepSubqueryInterval, reloaders...); err != nil {
level.Error(logger).Log("msg", "Error reloading config", "err", err)
}
case rc := <-webHandler.Reload():
if err := reloadConfig(cfg.configFile, logger, noStepSubqueryInterval, reloaders...); err != nil {
level.Error(logger).Log("msg", "Error reloading config", "err", err)
rc <- err
} else {
rc <- nil
}
case <-cancel:
return nil
}
}

},

Prometheus内部提供了成熟的hot reload方案,这大大方便配置文件的修改和重新加载,在Prometheus生态中,很多Exporter也采用类似约定的实现方式。

收起阅读 »

企业不同时期的运维规划

企业创业期企业创业初期,人员少,业务流量不大,服务器数量相对较少,系统复杂度不高。对于日常的业务管理操作,因人员少,吼一声,大家就登录服务器进行手工操作,属于各自为战,每个人都有自己的操作方式,权限管理混乱、编写代码的风格各异,缺少必要的操作标准、流程机制,比...
继续阅读 »

企业创业期

企业创业初期,人员少,业务流量不大,服务器数量相对较少,系统复杂度不高。对于日常的业务管理操作,因人员少,吼一声,大家就登录服务器进行手工操作,属于各自为战,每个人都有自己的操作方式,权限管理混乱、编写代码的风格各异,缺少必要的操作标准、流程机制,比如业务目录环境都是各式各样的。在这个阶段建议建立如下规范:


  • 统一权限管理:应用程序、操作员、管理员权限分离。
  • 制定完善的操作流程:先开发环境验证、测试环境验证、预生产环境、生产环境的基础操作流程,最小操作权限、最小化的目录权限为准则。
  • 制定代码发布流程和机制:以开发环境、测试环境发布为先,在预生产环境、生产环境发布制定相应的审核。
  • 制定代码编写规范:制定排版、注释、标识命名、异常处理等相关规范,避免出现个性化的代码。
  • 使用云商自有监控做基础监控,主要是cpu、内存、网络等。
  • 强化系统、业务基线安全。


企业高速发展期

在企业发展期,拿到融资后,业务快速发展,随着服务器规模、系统复杂度的增加,全人工的操作方式已经不能满足业务的快速发展需要。因此,运维人员逐渐开始使用批量化的操作工具,针对不同操作类型出现了不同的脚本程序。


但各团队都有自己的工具,每次操作需求发生变化时都需要调整工具。这主要是因为对于环境、操作的规范不够,导致可程序化处理能力较弱。此时,虽然效率提升了一部分,但很快又遇到了瓶颈。在这个阶段建议建立如下规范:


  • 制定运维相关脚本的编写标准:如统一相关备份空间、相关备份执行计划,制定相关脚本的执行人员、执行权限、执行时间。
  • 统一同类工具的使用:如数据连接工具、备份工具、数据同步工具等。
  • 确认相关的操作人,减少或者避免开发和测试在服务器上的相关操作。
  • 部署监控平台进一步的监管数据库、进程、日志等。
  • 使用第三方应用性能管理对应用性能做应用分析和优化。


企业稳定发展时期

在企业稳定期,在这个阶段,对于运维效率和误操作率有了更高的要求,我们决定开始建设运维平台,通过平台承载标准、流程,进而解放人力和提高质量。
这个时候对服务的变更动作进行了抽象,形成了操作方法、服务目录环境、服务运行方式等统一的标准。通过平台来约束操作流程。

在平台中强制需要运维人员填写相应的检查项,然后才可以继续执行后续的部署动作。在这个阶段建议建立如下运维平台:


  • 统一运维操作和管理平台:操作管理、权限管理、资源。
  • 统一日志平台:统一日志收集标准、日志收集接口,查询方式,查询授权。
  • 统一监控平台:强化监控,从系统、数据库、缓存、中间件、接口、业务性能等。
  • 统一发布平台:细化发布项目、发布权限、发布审核、回滚、备份等。
  • 加强安全防护:上线前做安全加固、安全评估、渗透测试等。
  • 统一开发规范:统一接口、数据库、配置文件等规范。


企业集团化、规模化发展时期

更大规模的服务数量、更复杂的服务关联关系、各个运维平台的林立,原有的将批量操作转化成平台操作的方式已经不再适合,需要对服务变更进行更高一层的抽象。比如智能告警、故障自愈、运营辅助决策等。


这个阶段需要大量的运维数据支持,做相应的数据分析、测试,才能使用,不然因误报或错误的故障自愈决策造成大规模的故障。


分享阅读原文: http://m6z.cn/6sGPLO

收起阅读 »

交叉编译详解概念篇

1、交叉编译简介1.1 什么是交叉编译对于没有做过嵌入式编程的人, 可能不太理解交叉编译的概念, 那么什么是交叉编译?它有什么作用? 在解释什么是交叉编译之前,先要明白什么是本地编译。 本地编译: 本地编译可以理解为,在当前编译平台下,编译出来的程序只能放到当...
继续阅读 »

1、交叉编译简介

1.1 什么是交叉编译

对于没有做过嵌入式编程的人, 可能不太理解交叉编译的概念, 那么什么是交叉编译?它有什么作用?


在解释什么是交叉编译之前,先要明白什么是本地编译。


本地编译:


本地编译可以理解为,在当前编译平台下,编译出来的程序只能放到当前平台(CPU和系统)下运行。平时我们常见的软件开发,都是属于本地编译:


比如,我们在 x86 平台上,编写程序并编译成可执行程序。这种方式下,我们使用 x86 平台上的工具,开发针对 x86 平台本身的可执行程序,这个编译过程称为本地编译。


交叉编译:


交叉编译可以理解为,在当前编译平台下,编译出来的程序能运行在体系结构不同的另一种目标平台上,但是编译平台本身却不能运行该程序:


比如,我们在 x86 平台上,编写程序并编译成能运行在 ARM 平台的程序,编译得到的程序在 x86 平台上是不能运行的,必须放到 ARM 平台上才能运行。


1.2 为什么会有交叉编译

之所以要有交叉编译,主要原因是:


  • Speed: 目标平台的运行速度往往比当前编译主机慢得多,许多专用的嵌入式硬件被设计为低成本和低功耗,没有太高的性能;
  • Capability: 整个编译过程是非常消耗资源的,嵌入式系统往往没有足够的内存或磁盘空间;
  • Availability: 即使目标平台资源很充足,可以本地编译,但是第一个在目标平台上运行的本地编译器总需要通过交叉编译获得;
  • Flexibility: 一个完整的Linux编译环境需要很多支持包,交叉编译使我们不需要花时间将各种支持包移植到目标机器上。

1.3 为什么交叉编译比较困难

交叉编译的困难点在于两个方面:


不同的体系架构拥有不同的机器特性


  • Word size: 是64位还是32位系统
  • Endianness: 是大端还是小端系统
  • Alignment: 是否必修按照4字节对齐方式进行访问
  • Default signedness: 默认数据类型是有符号还是无符号
  • NOMMU: 是否支持MMU

交叉编译时的主机环境与目标环境不同


  • Configuration issues:具有单独配置步骤(标准./configure make make install)的软件包通常会测试字节序或页面大小等内容,以便在本地编译时可移植。交叉编译时,这些值在主机系统和目标系统之间会有所不同,因此在主机系统上运行测试会给出错误的答案。当目标没有该程序包或版本不兼容时,配置还可以检测主机上是否存在该程序包并包括对该程序包的支持;
  • HOSTCC vs TARGETCC:许多构建过程需要编译内容才能在主机系统上运行,例如上述配置测试或生成代码的程序(例如创建.h文件的C程序,然后在主构建过程中#include )。仅用目标编译器替换主机编译器就会破坏需要构建在构建本身中运行的事物的软件包。这样的软件包需要访问主机和目标编译器,并且需要教它们何时使用它们;
  • Toolchain Leaks:配置不正确的交叉编译工具链可能会将主机系统的某些位泄漏到已编译的程序中,从而导致通常易于检测但难以诊断和纠正的故障。工具链可能#include错误的头文件,或在链接时搜索错误的库路径。共享库通常依赖于其他共享库,这些共享库也可能潜入对主机系统的意外链接时引用;
  • Libraries:动态链接的程序必须在编译时访问适当的共享库。需要将与目标系统共享的库添加到交叉编译工具链中,以便程序可以针对它们进行链接;
  • Testing:在本机版本上,开发系统提供了便利的测试环境。交叉编译时,确认”hello world”构建成功可能需要配置(至少)引导加载程序,内核,根文件系统和共享库。

更详细的对比可以参看这篇文章,已经写的很详细了,在这就不细说了:Introduction to cross-compiling for Linux


2、交叉编译链

2.1 什么是交叉编译链

明白了什么是交叉编译,那我们来看看什么是交叉编译链。


首先编译过程是按照不同的子功能,依照先后顺序组成的一个复杂的流程,如下图:

那么编译过程包括了预处理、编译、汇编、链接等功能。既然有不同的子功能,那每个子功能都是一个单独的工具来实现,它们合在一起形成了一个完整的工具集。


同时编译过程又是一个有先后顺序的流程,它必然牵涉到工具的使用顺序,每个工具按照先后关系串联在一起,这就形成了一个链式结构。


因此,交叉编译链就是为了编译跨平台体系结构的程序代码而形成的由多个子工具构成的一套完整的工具集。同时,它隐藏了预处理、编译、汇编、链接等细节,当我们指定了源文件(.c)时,它会自动按照编译流程调用不同的子工具,自动生成最终的二进制程序映像(.bin)。



注意: 严格意义上来说,交叉编译器,只是指交叉编译的gcc,但是实际上为了方便,我们常说的交叉编译器就是交叉工具链。本文对这两个概念不加以区分,都是指编译链。



2.2 交叉编译链的命名规则

我们使用交叉编译链时,常常会看到这样的名字:


arm-none-linux-gnueabi-gcc
arm-cortex_a8-linux-gnueabi-gcc
mips-malta-linux-gnu-gcc

其中,对应的前缀为:


arm-none-linux-gnueabi-
arm-cortex_a8-linux-gnueabi-
mips-malta-linux-gnu-

这些交叉编译链的命名规则似乎是通用的,有一定的规则:


arch-core-kernel-system
  • arch: 用于哪个目标平台;
  • core: 使用的是哪个CPU Core,如Cortex A8,但是这一组命名好像比较灵活,在其它厂家提供的交叉编译链中,有以厂家名称命名的,也有以开发板命名的,或者直接是none或cross的;
  • kernel: 所运行的OS,见过的有Linux,uclinux,bare(无OS);
  • system: 交叉编译链所选择的库函数和目标映像的规范,如gnu,gnueabi等。其中gnu等价于glibc+oabi、gnueabi等价于glibc+eabi。

注意: 这个规则是一个猜测,并没有在哪份官方资料上看到过。而且有些编译链的命名确实没有按照这个规则,也不清楚这是不是历史原因造成的。如果有谁在资料上见到过此规则的详细描述,欢迎指出错误。



3、包含的工具

Binutils是GNU工具之一,它包括链接器、汇编器和其他用于目标文件和档案的工具,它是二进制代码的处理维护工具。


Binutils工具包含的子程序如下:


  • ld - GNU链接器;
  • as - GNU汇编器;
  • gold - 一个新的,更快的ELF链接器;
  • addr2line - 把地址转换成文件名和所在的行数;
  • ar - 用于创建,修改和提取档案的实用程序;
  • c ++ filt-过滤以解编码编码的C ++符号;
  • dlltool-创建用于构建和使用DLL的文件;
  • elfedit-允许更改ELF格式文件;
  • gprof-显示分析信息;
  • nlmconv-将目标代码转换为NLM;
  • nm-列出目标文件中的符号;
  • objcopy-复制并转换目标文件;
  • objdump-显示目标文件中的信息;
  • ranlib-生成指向档案内容的索引;
  • readelf-显示来自任何ELF格式对象文件的信息;
  • size -列出的对象或归档文件的部分的尺寸;
  • strings -列出文件中的可打印字符串;
  • strip - 丢弃的符号;
  • windmc -Windows兼容的消息编译器。
  • windres -Windows资源文件的编译器。

binutils介绍 binutils详解 详细页面。


3.2 GCC

GNU编译器套件,支持C, C++, Java, Ada, Fortran, Objective-C等众多语言。


3.3 Glibc

Linux上通常使用的C函数库为glibc。glibc是linux系统中最底层的api,几乎其它任何运行库都会依赖于glibc。glibc除了封装linux操作系统所提供的系统服务外,它本身也提供了许多其它一些必要功能服务的实现。


glibc 各个库作用介绍


因为嵌入式环境的资源及其紧张,所以现在除了glibc外,还有uClibc和eglibc可以选择,三者的关系可以参见这两篇文章:


uclibc eglibc glibc之间的区别和联系


Glibc vs uClibc Differences


3.4 GDB

GDB用于调试程序


4、如何得到交叉编译链

既然明白了交叉编译链的功能,那么在针对嵌入式系统开发时,我们需要的交叉编译链从哪儿得到?


主要有三个方式可以获取


4.1 下载已经做好的交叉编译链

使用其他人针对某些CPU平台已经编译好的交叉编译链。我们只需要找到合适的,下载下来使用即可。


常见的交叉编译链下载地址:


http://ftp.arm.linux.org.uk/pub/armlinux/toolchain/ 下载已经编译好的交叉编译链
http://www.denx.de/en/Software/WebHome 下载已经编译好的交叉编译链
https://launchpad.net/gcc-arm-embedded下载已经编译好的交叉编译链
一些制作交叉编译链的工具中,包含了已经制作好的交叉编译链,可以直接拿来使用。如crosstool-NG
如果购买了某个芯片或开发板,一般厂商会提供对应的整套开发软件,其中就包含了交叉编译链。
厂家提供的工具一般是经过了严格的测试,并打入了一些必要的补丁,所以这种方式往往是最可靠的工具来源。

4.2 使用工具定制交叉编译链

使用现存的制作工具,以简化制作交叉编译链这个事情的复杂度。我们只需要了解有哪些工具可以实现,并选个合适的工具,搞懂它的操作步骤即可。


  1. crosstool-NG
  2. Buildroot
  3. Embedded Linux Development Kit (ELDK)

工具还有很多,各有各的优势和劣势,大家可以慢慢研究,在这就不细说了。


4.3 从零开始构建交叉编译链

这个是最困难也最耗时间的,毕竟制作交叉编译链这样的事情,需要对嵌入式的编译原理了解的比较透彻,至少要知道出了问题要往哪个方面去翻阅资料。而且,也是最考耐心和细心的地方,配错一个选项或是一个步骤,都可能出现以前从来没见过的问题,而且这些问题往往还无法和这个选项或步骤直接联系起来。


当然如果搭建出来,肯定也是收获最大的,至少对于编译的流程和依赖都比较清楚了,细节上的东西可能还需要去翻看相应的协议或标准,但至少骨架会比较清楚。


详细的搭建过程可以参看后续的文章,这里面有详细的参数和步骤:
交叉编译详解 二 从零制作交叉编译链


为了方便大家搭建交叉编译链,我写了一个一键生成的脚本(包括源码下载和自动编译)。如果大家自己一直搭建不成功,不妨试试这个脚本,然后对比下自己的流程是否一致,参数是否有差异,也许能帮大家迈过这个障碍:
交叉编译详解 三 使用脚本自动生成交叉编译链


4.4 对比三种构建方式




























项目 使用已有交叉编译链 自己制作交叉编译链
安装 一般提供压缩包 需要自己打包
源码版本 一般使用较老的稳定版本,对于一些新的GCC特性不支持 可以使用自己需要的GCC特性的版本
补丁 一般都会打上修复补丁 普通开发者很难辨别需要打上哪些补丁,资深开发者可以针对自己的需求合入补丁
源码溯源 可能不清楚源码版本和补丁情况 一切都可以定制
升级 一般不会升级 可以随时升级
优化 一般已经针对特定CPU特性和性能进行优化 一般无法做到比厂家优化的更好,除非自己设计的CPU
技术支持 可以通过FAE进行支持,可能需要收费 只能通过社区支持,免费
可靠性验证 已经通过了完善的验证 自己验证,肯定没有专业人士验证的齐全

参考资料

1、Introduction to cross-compiling for Linux


2、binutils介绍


3、 glibc 各个库作用介绍


4、 uclibc eglibc glibc之间的区别和联系


5、 Glibc vs uClibc Differences


6、交叉编译链下载地址


分享原文: http://m6z.cn/6tdD7y

收起阅读 »

Linux文件的三个时间属性

时间属性介绍Linux下一个文件通过stat命令可以查看到这个文件时间方面的属性,具体信息如下: # stat tengine-2.0.0-23tf4566.tar.gz File: 'tengine-2.0.0-23tf4566.tar.gz' Si...
继续阅读 »

时间属性介绍

Linux下一个文件通过stat命令可以查看到这个文件时间方面的属性,具体信息如下:


# stat tengine-2.0.0-23tf4566.tar.gz
File: 'tengine-2.0.0-23tf4566.tar.gz'
Size: 35995224 Blocks: 70304 IO Block: 4096 regular file
Device: 802h/2050d Inode: 201842670 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 501/ UNKNOWN) Gid: ( 20/ games)
Access: 2020-07-30 14:07:46.617759798 +0000
Modify: 2020-07-30 12:57:35.000000000 +0000
Change: 2020-10-16 06:20:13.535869875 +0000
Birth: -

如上所示,可以看出来分别有Access Modify Change 三个关于时间的属性。


此三个属性初始时间记录都是文件被创建的时间:


  • Access 指最后一次读取的时间(访问)
  • Modify 指最后一次修改数据的时间(修改)
  • Change 指最后一次修改元数据的时间(改变)

Access的意思是访问:


在终端上用cat、more 、less、grep、sed、 cp 、file 一个文件时,此文件的Access的时间记录都会被更新(空文件例外),纯粹的access是不会影响modify和change,但会受到modify行为的影响。


ls -lu看到的文件时间是最近一次access的时间。对于目录而言,只是进入目录的话不会改变它的access时间,但只要用ls查看了此目录的内容(无论在何处),这个目录的access时间就会被更新。


Modify 意思是更改(内容)or 写入:


当更改了一个文件的内容的时候,此文件的modify的时间记录会被更新。用ls -l看到的文件时间是最近一次modify的时间。modify的行为是三个行为中最有影响力的行为,它发生以后,会使文件的access记录与change记录也同时得到更新, 对于目录亦是如此。


Change 改变(状态或属性):
对一个文件或者目录作mv、chown、chgrp操作后,它的Change时间记录被更新,change时间会受到modify行为的影响。ls -lc看到的文件时间是最近一次change的时间。


# stat test.txt 
File: ‘test.txt’
Size: 10 Blocks: 8 IO Block: 4096 regular file
Device: 802h/2050d Inode: 201843904 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2020-10-16 06:44:21.925299516 +0000
Modify: 2020-10-16 06:44:21.925299516 +0000
Change: 2020-10-16 06:44:21.925299516 +0000
Birth: -

# cat test.txt
lucky boy

# stat test.txt
File: ‘test.txt’
Size: 10 Blocks: 8 IO Block: 4096 regular file
Device: 802h/2050d Inode: 201843904 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2020-10-16 06:44:43.911988787 +0000
Modify: 2020-10-16 06:44:21.925299516 +0000
Change: 2020-10-16 06:44:21.925299516 +0000
Birth: -

如上用cat命令将文件test.txt的内容输出到终端( 执行 cat test.txt), 那么文件test.txt只有的Access被刷新。


# date >> test.txt 
# stat test.txt
File: ‘test.txt’
Size: 39 Blocks: 8 IO Block: 4096 regular file
Device: 802h/2050d Inode: 201843904 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2020-10-16 06:44:43.911988787 +0000
Modify: 2020-10-16 06:46:56.760155796 +0000
Change: 2020-10-16 06:46:56.760155796 +0000
Birth: -

如上把当前的时间追加到test.txt(执行 date >> test.txt) , 那么test.txt的ModifyChange都被刷新。


# chmod 777 test.txt 
# stat test.txt
File: ‘test.txt’
Size: 39 Blocks: 8 IO Block: 4096 regular file
Device: 802h/2050d Inode: 201843904 Links: 1
Access: (0777/-rwxrwxrwx) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2020-10-16 06:44:43.911988787 +0000
Modify: 2020-10-16 06:46:56.760155796 +0000
Change: 2020-10-16 06:48:45.676571600 +0000
Birth: -

如上把test.txt的权限改为777(执行 chmod 777 test.txt) , 那么只有test.txtChange被刷新。


假如我们用vi命令把文件test.txt打开, 然后保存退出,那么test.txtAccess、ModifyChange都会被刷新。


同时我们也可以使用命令touch更新test.txt的Access和Modify时间:


touch -d 1999-01-01 test.txt    // 将test.txt的Access和Modify时间改为1999-01-01
touch -a test.txt // 只将test.txt的Access时间改为当前系统时间
touch -m test.txt // 只将test.txt的Modify时间改为当前系统时间

当我们用ls -l test.txt看到的时间就是Modify时间。


按照时间排序文件

# ls -l
-rw-r--r-- 1 501 games 35995224 Jul 30 12:57 tengine-2.0.0-23tf4566.tar.gz
-rw-r--r-- 1 501 games 4321420 Jul 22 14:15 tengine-2.0.0-45axfa54.tar.gz
-rw-r--r-- 1 501 games 33238934 Jul 22 15:20 tengine-2.0.0-64af1234.tar.gz

如上有3个文件,如果按照时间排序呢?


按照修改时间排序:


ls -alt  等价于 ls --sort=time -la

按照创建时间排序:


ls -alc

按访问时间排序:


ls -alu

以上均可使用-r实现逆序排序


ls -alrt # 按修改时间排序
ls --sort=time -lra # 等价于> ls -alrt
ls -alrc # 按创建时间排序
ls -alru # 按访问时间排序

不管你是根据什么排序,加上-r 就会反序。

收起阅读 »

sed常用替换小技巧记录

1. 去掉行首空格 sed 's/^[ \t]*//g'2. 去掉行末空格 sed 's/[ \t]*$//g'3. 去掉所有空格 sed s/[[:space:]]//g4. 替换符号 sed "s/^\(.*\)$/'\1'/" sed "s/^\(.*...
继续阅读 »
1. 去掉行首空格
sed 's/^[ \t]*//g'
2. 去掉行末空格
sed 's/[ \t]*$//g'
3. 去掉所有空格
sed s/[[:space:]]//g
4. 替换符号
sed "s/^\(.*\)$/'\1'/" 
sed "s/^\(.*\)$/aa =>\1/"
收起阅读 »

一些常见错误技术问题汇总

Q: 启动apache报错 [warn] module php5_module is already loaded, skipping 一般出现这种问题有两种情况: 1.在apache安装目录conf下httpd.conf里可能重复了一行LoadModul...
继续阅读 »


Q: 启动apache报错 [warn] module php5_module is already loaded, skipping


一般出现这种问题有两种情况:
1.在apache安装目录conf下httpd.conf里可能重复了一行LoadModule php5_module modules/libphp5.so,删除重复的行就行。
 
2.或者在其他的conf文件中加载load了,如下yum安装的httpd,conf.d/php.conf里

LoadModule php5_module modules/libphp5.so


Q: centos 6.2 更新报错解决 yum you could try using skip broken to work around the problem


 
# yum update
Loaded plugins: aliases, changelog, downloadonly, kabi, presto, refresh-
: packagekit, security, tmprepo, verify, versionlock
Loading support for Red Hat kernel ABI
adobe-linux-x86_64 | 951 B 00:00
google-chrome | 951 B 00:00 ...
sl | 3.2 kB 00:00
sl-security | 1.9 kB 00:00
Setting up Update Process
Resolving Dependencies
--> Running transaction check
---> Package python-qpid.noarch 0:0.12-1.el6 will be updated
---> Package python-qpid.noarch 0:0.14-11.el6_3 will be an update
---> Package python-qpid-qmf.x86_64 0:0.12-6.el6 will be updated
---> Package python-qpid-qmf.x86_64 0:0.14-14.el6_3 will be an update
---> Package qpid-cpp-client.x86_64 0:0.12-6.el6 will be updated
--> Processing Dependency: libqpidclient.so.5()(64bit) for package: matahari-agent-lib-0.4.4-11.el6.x86_64
--> Processing Dependency: libqpidclient.so.5()(64bit) for package: matahari-network-0.4.4-11.el6.x86_64
--> Processing Dependency: libqpidclient.so.5()(64bit) for package: matahari-sysconfig-0.4.4-11.el6.x86_64
--> Processing Dependency: libqpidclient.so.5()(64bit) for package: matahari-service-0.4.4-11.el6.x86_64
--> Processing Dependency: libqpidclient.so.5()(64bit) for package: matahari-host-0.4.4-11.el6.x86_64
--> Processing Dependency: libqpidcommon.so.5()(64bit) for package: matahari-network-0.4.4-11.el6.x86_64
--> Processing Dependency: libqpidcommon.so.5()(64bit) for package: matahari-host-0.4.4-11.el6.x86_64
--> Processing Dependency: libqpidcommon.so.5()(64bit) for package: matahari-sysconfig-0.4.4-11.el6.x86_64
--> Processing Dependency: libqpidcommon.so.5()(64bit) for package: libvirt-qmf-0.3.0-4.el6.x86_64
--> Processing Dependency: libqpidcommon.so.5()(64bit) for package: matahari-agent-lib-0.4.4-11.el6.x86_64
--> Processing Dependency: libqpidcommon.so.5()(64bit) for package: matahari-service-0.4.4-11.el6.x86_64
---> Package qpid-cpp-client.x86_64 0:0.14-22.el6_3 will be an update
---> Package qpid-cpp-client-ssl.x86_64 0:0.12-6.el6 will be updated
---> Package qpid-cpp-client-ssl.x86_64 0:0.14-22.el6_3 will be an update
---> Package qpid-cpp-server.x86_64 0:0.12-6.el6 will be updated
---> Package qpid-cpp-server.x86_64 0:0.14-22.el6_3 will be an update
---> Package qpid-cpp-server-ssl.x86_64 0:0.12-6.el6 will be updated
---> Package qpid-cpp-server-ssl.x86_64 0:0.14-22.el6_3 will be an update
---> Package qpid-qmf.x86_64 0:0.12-6.el6 will be updated
---> Package qpid-qmf.x86_64 0:0.14-14.el6_3 will be an update
---> Package qpid-tools.noarch 0:0.12-2.el6 will be updated
---> Package qpid-tools.noarch 0:0.14-6.el6_3 will be an update
---> Package ruby-qpid-qmf.x86_64 0:0.12-6.el6 will be updated
---> Package ruby-qpid-qmf.x86_64 0:0.14-14.el6_3 will be an update
--> Finished Dependency Resolution
Error: Package: matahari-host-0.4.4-11.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
Requires: libqpidclient.so.5()(64bit)
Removing: qpid-cpp-client-0.12-6.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
libqpidclient.so.5()(64bit)
Updated By: qpid-cpp-client-0.14-22.el6_3.x86_64 (sl-security)
Not found
Error: Package: matahari-sysconfig-0.4.4-11.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
Requires: libqpidclient.so.5()(64bit)
Removing: qpid-cpp-client-0.12-6.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
libqpidclient.so.5()(64bit)
Updated By: qpid-cpp-client-0.14-22.el6_3.x86_64 (sl-security)
Not found
Error: Package: matahari-service-0.4.4-11.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
Requires: libqpidcommon.so.5()(64bit)
Removing: qpid-cpp-client-0.12-6.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
libqpidcommon.so.5()(64bit)
Updated By: qpid-cpp-client-0.14-22.el6_3.x86_64 (sl-security)
Not found
Error: Package: matahari-network-0.4.4-11.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
Requires: libqpidclient.so.5()(64bit)
Removing: qpid-cpp-client-0.12-6.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
libqpidclient.so.5()(64bit)
Updated By: qpid-cpp-client-0.14-22.el6_3.x86_64 (sl-security)
Not found
Error: Package: matahari-sysconfig-0.4.4-11.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
Requires: libqpidcommon.so.5()(64bit)
Removing: qpid-cpp-client-0.12-6.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
libqpidcommon.so.5()(64bit)
Updated By: qpid-cpp-client-0.14-22.el6_3.x86_64 (sl-security)
Not found
Error: Package: matahari-host-0.4.4-11.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
Requires: libqpidcommon.so.5()(64bit)
Removing: qpid-cpp-client-0.12-6.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
libqpidcommon.so.5()(64bit)
Updated By: qpid-cpp-client-0.14-22.el6_3.x86_64 (sl-security)
Not found
Error: Package: libvirt-qmf-0.3.0-4.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
Requires: libqpidcommon.so.5()(64bit)
Removing: qpid-cpp-client-0.12-6.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
libqpidcommon.so.5()(64bit)
Updated By: qpid-cpp-client-0.14-22.el6_3.x86_64 (sl-security)
Not found
Error: Package: matahari-agent-lib-0.4.4-11.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
Requires: libqpidcommon.so.5()(64bit)
Removing: qpid-cpp-client-0.12-6.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
libqpidcommon.so.5()(64bit)
Updated By: qpid-cpp-client-0.14-22.el6_3.x86_64 (sl-security)
Not found
Error: Package: matahari-network-0.4.4-11.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
Requires: libqpidcommon.so.5()(64bit)
Removing: qpid-cpp-client-0.12-6.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
libqpidcommon.so.5()(64bit)
Updated By: qpid-cpp-client-0.14-22.el6_3.x86_64 (sl-security)
Not found
Error: Package: matahari-agent-lib-0.4.4-11.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
Requires: libqpidclient.so.5()(64bit)
Removing: qpid-cpp-client-0.12-6.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
libqpidclient.so.5()(64bit)
Updated By: qpid-cpp-client-0.14-22.el6_3.x86_64 (sl-security)
Not found
Error: Package: matahari-service-0.4.4-11.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
Requires: libqpidclient.so.5()(64bit)
Removing: qpid-cpp-client-0.12-6.el6.x86_64 (@anaconda-ScientificLinux-201202061444.x86_64)
libqpidclient.so.5()(64bit)
Updated By: qpid-cpp-client-0.14-22.el6_3.x86_64 (sl-security)
Not found
You could try using --skip-broken to work around the problem
** Found 1 pre-existing rpmdb problem(s), 'yum check' output follows:
libvpx-1.0.0-1.el6.x86_64 is a duplicate with libvpx-0.9.0-8.el6_0.x86_64
上述更新错误,解决方法如下:
yum remove matahari*执行完后,然后执行yun update 更新,这样应该就可以了。


Q: Cannot load /…/libphp5.so into server: /…/libphp5.so: undefined symbol: _efree


此错误是由于重装php时,没有关闭apache。解决方法:调转到php安装目录,执行“make clean”,然后从新安装php,记得安装之前关闭apache。


Q: apache启动报错(98)Address already in use: make_sock: could not bind to address :80


端口占用情况:
#netstat -lnp|grep 80
#ps 端口号为80的进程
#kill -9 端口号为80的进程(可能进程不止一个)


Q: 从源码安装apache2,遇到错误:cannot install `libaprutil-1.la'


这是由于configure过一次,没有清理干净,需要清理。可以删除掉源码目录,重新解压源码,重新安装,或者make clean. 收起阅读 »

AIOps根因分析最佳实践

随着基础架构和软件环境变得越来越复杂,检测性能或可用性问题的根因变得越来越具有挑战性。幸运的是,迎接挑战的是一类新的工具和一种新的策略:AIOps。什么是根因分析?在IT中,根因分析是确定硬件或软件问题的根本问题原因是什么的过程。根因分析很重要,因为在许多情况...
继续阅读 »

随着基础架构和软件环境变得越来越复杂,检测性能或可用性问题的根因变得越来越具有挑战性。幸运的是,迎接挑战的是一类新的工具和一种新的策略:AIOps。

什么是根因分析?
在IT中,根因分析是确定硬件或软件问题的根本问题原因是什么的过程。

根因分析很重要,因为在许多情况下,有多个可能的问题原因,而且从问题本身来看,原因并不明显。例如,如果应用程序开始响应缓慢,则仅凭这些信息就很难知道问题的原因是否是应用程序本身编写的糟糕的代码,还是托管应用程序的操作系统存在的问题,还是文件系统存在问题。应用程序正在使用,应用程序所依赖的网络或存储基础结构出现问题或其他原因。也可能有多个潜在问题在起作用。

为什么当前根因分析尤其重要
从前,根因分析相对简单,因为IT团队需要管理的硬件和软件层较少。物理基础架构和硬件环境之间也几乎没有抽象。因此,如果监控软件检测到磁盘性能问题,则可以相对确定磁盘本身或用于格式化磁盘的文件系统是根本问题。

但是,今天,我们依赖高度动态的多层软件定义环境。映射这些环境中所有组件之间的关系非常困难,尤其是因为配置不断变化。很难解释在环境的一层中表现出来的问题与其他层之间的关系。

如今,存储性能问题的根因可能不一定是物理磁盘或本地文件系统,还可能是使存储可供远程系统使用的网络或分布式文件系统。也可能是提供存储的虚拟化网络。

充分利用AIOps进行根因分析
部分原因是由于现代环境中根因分析的困难, AIOps变得如此重要。通过使用机器学习自动映射和解释复杂的环境和因果关系,AIOps可以帮助IT团队比仅依靠手动分析更快地找到性能或可用性问题的根源。简单地使用AIOps工具将大大提高您的根本原因分析能力。

就是说,您可以采取一些步骤来确保充分利用AIOps辅助的根本原因分析。它们包括以下内容。

1. 记住,配置快速变更,根因也会随之变更

在瞬息万变的现代环境中进行根因分析的棘手事情之一是,一次构成根本问题的原因可能在下一时刻改变。应用程序性能缓慢的根本原因可能是网络拥塞,但随着网络流量模式和存储系统负载的变化,下一阶段将变为IO瓶颈。

AIOps工具可以帮助解决这些变化,但是对于人类工程师而言,重要的是要记住根因是可以改变的。不要认为核心问题是一成不变的。

2. 考虑自动响应

AIOps的另一个关键功能是它使软件工具可以采取自动措施来解决问题。尽管并不是在每种情况下都自动响应是正确的解决方案(例如,您可能希望让人工工程师在进行重大变更之前先进行审查),但对于更简单的问题的自动响应可以有效地帮助确保您不仅识别根因可以快速解决,也可以在最终给用户造成严重问题之前解决它们。

3. 不要假设只有一个根因

如上所述,软件或硬件问题的原因可能是多个问题。停止响应的应用程序可能会这样做,因为代码编写得不好,无法使应用程序从意外的网络错误中恢复;在这种情况下,应用程序代码和网络问题都是此问题的根因。

这里的关键要点是,一方面,在执行根因分析时,您应努力将辅助问题与根因区分开,但您不应排除可能存在两个或多个核心潜在问题的可能性。

4. 力求与环境无关的根本原因分析

理想情况下,根因分析工作流程应对任何类型的基础架构或环境均有效。如果您依赖仅支持特定类型的环境或基础架构的监控或分析工具(例如来自特定云供应商的工具或仅针对一种操作系统设计的工具),则不会发生这种情况。

此处的教训是,您应该寻找AIOps工具,这些工具可以协助对任何类型的基础结构进行根本原因分析。

英文原文:http://suo.im/64aCgc

收起阅读 »