热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

从AIX移植到Solaris案例分析

http:www.ibm.comdeveloperworkscnlinuxportingsolarisghttp:www.ibm.comdeveloperworkscnlin
http://www.ibm.com/developerworks/cn/linux/porting/solaris/g
http://www.ibm.com/developerworks/cn/linux/l-solar/
http://wenku.it168.com/d_000027189.shtml

http://www.ibm.com/developerworks/cn/linux/l-porting/


介绍

这份文档记录了一个真实系统项目移植的过程,包括项目的前期分析和具体项目中遇到的技术问题。希望通过这份文档分享移植到Solaris的经验。

 

项目背景

该项目移植的系统是某机构的关键核心数据中转系统。该系统是一个运行在IBM AIX 5L上的一个C/S架构的应用系统,主要使用C语言实现。系统比较庞大,C源程序代码近30多万行。其应用架构使用了BEATuxedo中间件,所有程序服务部署为Tuxedo Server。其后台数据库使用IBM DB2。该系统作为核心系统,用户对它的健壮性,可靠性非常高,现在用户决定将整体平台移植到Solaris上,希望能够通过异构的系统来达到更好的可靠性。整个项目的开发和系统集成测试委托独立软件开发商(ISV)Sun公司作为原厂商对这个项目提供相应的技术支持。

 

移植流程

整个移植项目的步骤分为:项目技术分析,项目规划,系统移植,系统测试,系统调优,性能测试和调优。整个过程如下图所示:

 

首先我们对项目进行技术分析,判断项目理论上的可行性。这是非常重要的一个步骤,因为从一个平台上迁移到另一个平台还是存在一定的风险。为了尽可能的保护后期的投入,必须根据用户的需求,从技术上分析项目的可行方案。如果技术分析通过,则需要现代项目管理方式,制定出一份项目计划,从中确定项目需求,实施计划和所需资源。接着是系统移植,得到一份可以运行的系统。然后是安排系统测试,包括系统完整性测试 (System Integration Test – SIT)和用户测试 (User Acceptance Test – UAT),确保移植后的系统能够正确工作。最后就是针对系统性能的测试和调优,让系统达到可交付的性能。

 

项目技术分析

在这个阶段中主要是对各种技术难点,比如第三方软件的依赖程度,对操作系统的依赖程度进行判断及预测。并且通过这种技术分析,确定在移植目标系统上系统整体方案。主要考虑的是以下技术点:32位还是64位,CPU类型选择,Endian,第三方依赖库,操作系统的选择,编译器的选择还有代码分析。

32/64

该系统在AIX上是64 (LP64数据模型)位运算,对SolarisSun公司64位服务器来说亦不是问题。

CPU

根据原先用户的机型,我们选择基于UltraSPARC IV+机器。UltraSPARC IV+Sun面向数值计算的一款64位双核CPU,在保持原有的功耗和价格,它的性能却是UltraSPARC IV2.5倍。

而且UltraSPARC IV+做为RISC芯片和IBMPower芯片一样,都兼容Big Endian。这点方便了我们移植工作。

Endian

Endian是指CPU处理数据的字节序,其中有Big EndianLittle Endian两种不同的处理方式。系统移植的时候,如果数据处理字节序不一样的话,就要注意源代码是否依赖某一种数据处理方式。如前所述,由于我们采用了UltraSPARC IV+,和原来系统一样都是Big Endian

 

* IBM Power 4是可以接受Big EndianLittle Endian模式,但是上层的操作系统AIX 5L只支持Big Endian

 

第三方依赖库

在技术分析中最为重要的就是根据系统所依赖的第三方软件在Solaris上是否有相应的版本和认证。经过查证,该系统除了前面所说的IBM DB2BEA Tuxedo,没有依赖其它第三方库,所有其它功能比如日志,外界通信等都是直接自己实现。原先期望是采用Solaris最新版本Solaris 10,后来发现BEA Tuxedo虽没有问题,但是系统所使用的IBM DB2版本是8.1,其正式支持的Solaris版本最高是Solaris 9。由于这个原因,确定移植目标系统使用Solaris 9

操作系统

如前所述,最后选择Solaris 9 SPARC版本。Solaris 9Sun公司2002年发布的操作系统的版本,它支持众多UNIX系统标准:IEEE Std 1003.1 (POSIX.1)IEEE Std 1003.2 (POSIX.2)Single UNIX Specification, Version 3等。这些对标准的支持也是用户选择Solaris的一个重要的原因。

编译器

编译器的选择也是非常重要的一个环节。在Solaris 9 SPARC版本上可以选择的C编译器有GCCSun StudioGCC作为GNU的开发工具,适用的平台范围广,非常适合跨平台应用程序的开发。Sun Studio作为Sun出品的开发工具,毋庸置疑,能够编译出发挥UltraSPARC机器最佳性能的可执行码。同时我们不仅要考虑目标移植系统的可选编译器,还要考虑原系统平台使用的编译器。

 

原先在AIX平台上使用的是IBM Visual Age开发工具,并且软件开发商曾为了确保代码的可移植性,使用GCC编译过一个分支版本。现在看来,这个尝试是非常明智的,减少了移植的风险。

 

但是对于CC++程序来说,绝对不能忽略某些第三方开发库对于编译器都有要求。尤其一些商业的开发库,不仅会对不同的操作系统每个版本进行认证,而且只针对指定编译器提供官方支持。比如使用BEA TuxedoIBM DB2Solaris上支持的编译器都是Forte Developer (Sun Studio先前版本Sun Studio。根据查找BEA TuxedoIBM DB2支持的文档,两者所支持Sun Studio编译器版本列表的交集是Forte Developer 6.2Forte Developer 6.2Sun公司2001年推出的一套开发工具,现在除了一个HPC特别版,Forte Developer 6.2已经停止销售了。

 

不过目前Sun公司最新的开发工具Sun Studio版本是11,它符合ISO C99C98规范,不仅提供更好的优化和多核CPU(UltraSPARC IV+, UltraSPARC T1, AMD Opteron)的支持,而且也提供对旧版本的兼容。Sun为了保护用户,软件开放商的投入,承诺高版本的Sun Studio可以使用低版本的Sun Studio或者Forte Developer编译出来的链接库或者对象文件。也就是说,Forte Developer 6.2可以使用的开发库,Sun Studio 11也可以使用。所以最后我们确定选择使用Sun Studio 11

 

代码分析

通过代码分析,判断代码可能存在的兼容性问题会对后面的具体移植,系统编译帮助非常大。目前系统代码主要是shell脚本,DB2脚本和C源程序。

 

Shell脚本移植性主要是依赖具体的Shell解释器和解释器的版本。这次系统中Shell 脚本使用的是Bourne Shell。正好可以使用Scriptran来检查,结果工具没有发现问题,在后续的移植中也得到验证。

 

* Sun公司提供一个Scriptran工具,它是针对Bourne Shell脚本的检查工具,能够检查脚本中哪些命令,参数或者系统依赖路径Solaris不支持。

 

因为使用同一个版本的DB2和指定支持的系统,所以判断DB2脚本兼容性应该能够得到保证。

 

C源程序是否能够兼容目标系统SolarisSun Studio是一个潜在风险。因为C/C++程序的跨平台性最主要的障碍是编译器和操作系统还有某些功能实现技术差异。即使存在相应的编译器标准,UNIX标准,但是很难保证系统没有使用编译器或者AIX特别的扩展功能。

虽然用户曾经使用GCC编译过某个分支版本,这只能说明该系统C代码的跨平台性不错,没有使用编译器特有的属性或扩展。

 

针对这个问题,我们可以通过AIX-Solaris Migration Kit工具做一个代码分析。

 

* Sun公司针对系统移植提供一个代码分析工具AIX-Solaris Migration Kit,它能够自动解析C/C++, COBOL代码,检查出代码移植中已知可预见的问题:比如操作系统的扩展,某些函数的不兼容。该工具分析后会以HTML报告的形式列出所有未知的函数及有问题的代码,并给出解决办法和相应的时间预测。目前该工具未正式发布,我们使的是Beta版本。

 

下面是这次移植中,AIX-Solaris Migration Kit针对代码分析后产生报告的部分剪屏。这个是项目概要:

下面这张图列出了移植中待确认的函数,最后给出对移植预测的判断(“Your Average Level of Porting Difficulty Is”):是未知。虽然这并不代表移植中没有问题,但至少说明目前未发现已知问题函数或者问题代码。所以说这个报告结果还是乐观的,增加了用户和软件开发商对系统移植的信心。

 

项目规划

根据现有的资源和数据,对项目制定出一个计划,在任何一个项目中都是不可缺少的。整个项目软件开发商规划是60个人天,包括开发环境架设,实际编译工作和系统测试。最后的实际项目进展也和预期一样,整个项目规划证明还是非常有效合理。

 

系统编译

系统编译不仅包含对系统代码的编译工作,还有包括开发环境架设,Make工具,数据库和开发所用的版本控制器准备。有时候移植的时候还可能牵涉到测试工具的移植,这时候有可能也要考虑进去。当然最主要的工作还是利用Sun Studio开发工具编译源代码,生成最终的执行代码。在这个阶段,首先要修改Makefile,指定编译器和选项。

 


编译选项

下面的列表描述了一些就Sun StudioSPARC版本)和Visual Age在参数上的区别。

 

代码生成参数选项

 

功能

Sun Studio 编译器

Visual Age 编译器

生成与位置无关的代码

-KPIC / -Kpic

默认开启

使用多线程库

-mt

xlC_r调用

指定代码地址空间

-xcode=

无对应属性

将数据段合并到文本段中

-xMerge

无对应属性

 

 

调试参数选项

 

功能

Sun Studio编译器

Visual Age编译器

显示编译器所使用的选项,不做编译

-### / -xdryrun

-#

将当前编译过程中包含的每个文件的路径名打印到标准错误输出

-H

-qshowinc

保留在编译期间创建的临时文件而非自动删除它们

-keeptmp

无对应属性

允许在没有对象文件(.o)的情况下使用dbx进行调试

-xs

无对应属性

为源代码浏览器生成额外的符号表信息

-xsb

无对应属性

 


浮点操作选项

 

功能

Sun Studio编译器

Visual Age编译器

控制SPARC 非标准浮点模式

-fns[={yes|no}]

-qfloat=

设置在程序初始化运行时建立的IEEE 754 舍入模式

-fround=

-qfloat=

允许优化器产生关于浮点运算的简化假定

-fsimple[=]

-qfloat=

设置 IEEE 捕获模式启动时有效,但不安装 SIGFPE 处理程序

-ftrap=t[,t...]

-qfloat=

强制 IEEE 754 样式返回异常情况下的数学例程值

-xlibmieee

-qfloat=

 

链接库选项

 

功能

Sun Studio编译器

Visual Age编译器

指定动态库链接

-Bdynamic

-bdynamic/-bshared

制定静态库链接

-Bstatic

-bstatic

指定链接编辑器中的动态链接

-d{y|n}

无对应属性

忽略任何 LD_LIBRARY_PATH或 LD_LIBRARY_PATH_64

设置

-i

无对应属性

使编译器在对性能有益的地方替换内在函数或内联系统函数

-xbuiltin[=]

无对应属性

内联部分库例程以加快执行速度

-xlibmil/-libmil

无对应属性

以使用优化的数学例程库

-xlibmopt

无对应属性

默认情况下不链接任何库

-xnolib

无对应属性

取消使用–xlibmil

-xnolibmil / -nolibmil

无对应属性

取消使用–xlibmopt

-xnolibmopt

无对应属性

 

 

性能优化选项

 

功能

Sun Studio编译器

Visual Age编译器

定义优化器使用的缓存属性

-xcache=

-qcache

指定供优化器使用的目标处理器

-xchip=

无对应属性

允许链接程序对函数和变量进行最佳重新排序

-xF=

无对应属性

只内联可选列表中指定的函数

-xinline[=] / -inline[=]

-qinline / -Q

指定所有源文件执行内联处理及以提高缓存的性能为目的对执行过程间别名分析同时优化内存分配和布局

-xipo[=]

-qipa

为源代码浏览器创建数据库

-xsbfast

无对应属性

 

除了Makefile的修改,我们在实际编译期也遇到一些问题:

 

编译期问题

类型定义

IBM Visual Age上,会对一些函数调用中的参数变量做自动类型转换,比如从charint。在Sun Studio编译器中,对这种转换检查较为严格。我们可以通过代码调整,改变参数类型,使代码更加符合语意。

 


全局变量的声明和定义

IBM Visual Age上存在多个C源文件中多次重复声明并定义同一个全局变量:

 

user_data_t * const gpData = NULL;

 

虽然IBM Visual Age可以编译通过,但显然不符合C标准及语意。修改方法也很简单,保证留有一个变量定义,其它则改为声明。

 

__FUNCTION____func__

Sun Studio并未有内嵌__FUNCTION__宏,不过提供__func__预定义标识符。可以通过自定义来避免代码修改。

 

#define __FUNCTION__ __func__

 

TCP_RFC1323

IBM AIX支持通过setsocktopt(3SOCKET)设置对RFC1323支持选项,TCP_RFC1323是一个网络优化的选项,主要是来开启TCP Windows Scale和相关的timestamp,从而达到一个比较适合当前高速网络窗口(Windows)大小。

Solaris下,没有这样针对Socket的控制选项,不过Solaristcp_wscale_alwaystcp_tstamp_if_wscale两个系统选项专门针对RFC1323协议。默认在Solaris 9下是开启,可以通过以下命令验证,1位开启,0为关闭:

 

-bash-3.00# ndd /dev/tcp tcp_wscale_always

1

-bash-3.00# ndd /dev/tcp tcp_tstamp_if_wscale

1

 

pthread_cleanup_pushpthread_cleanup_pop

通常这两个函数是以宏定义的形式出现,在编程中要确保这两个函数要在同一个词法作用域内(Lexical Scope)“成对”出现,比如同一个函数体中。这是因为通常它们的宏定义中含有“{”和“}”。以下就是在Solaris中的定义:

 

#define pthread_cleanup_push(routine, args) { /

        _cleanup_t _cleanup_info; /

        __pthread_cleanup_push((_Voidfp)(routine), (void *)(args), /

                                (caddr_t)_getfp(), &_cleanup_info);

 

#define pthread_cleanup_pop(ex) /

        __pthread_cleanup_pop(ex, &_cleanup_info); / }

 

但是在AIX环境中它可以不受这个约束。由于原系统代码并未遵从这种“成对”编码方式,在Solaris上编译,编译器会报错,出错信息一般都是针对提示作用域“{”或“}”的语法错误。解决办法就是根据场景的语意,将两个函数调用调整至同一个函数体内或者同一个词法作用域内。

 

系统测试

在系统测试阶段(SIT&UAT),我们使用的可执行文件仍旧是含有调试信息。这样做的目的是为了,如果程序出现崩溃或者其它异常行为,我们可以通过这些调试信息和Sun Studio的调试器dbx快速定位到出错代码。

下面介绍一个典型的用dbx调试器定位错误代码的场景:

 

-bash-3.00# /opt/SUNWspro/bin/dbx   yourApplication   core

For information about new features see `help changes'

To remove this message, put `dbxenv suppress_startup_message 7.5' in your .dbxrc

Reading tServer

core file header read successfully

Reading ld.so.1

Reading libpthread.so.1

Reading librt.so.1

Reading libsocket.so.1

Reading libnsl.so.1

Reading libc.so.1

Reading libthread.so.1

Reading libCrun.so.1

Reading libm.so.1

Reading libkstat.so.1

t@1 (l@1) program terminated by signal SEGV (no mapping at the fault address)

0xffffffff7ce3ce90: strcmp+0x0014:      ldub     [%i1], %i5

** 会自动显示造成系统崩溃的代码行

Current function is txnAtomMatchRqst

  177                       && strcmp(pMsg->inHeader.msgVer, "01" == 0)) {

(dbx) threads                                      ** 显示所有线程信息

o>    t@1  a  l@1   ?()   signal SIGSEGV in  strcmp()

      t@2  b  l@2   tTimerThread()   LWP suspended in  __pollsys()

(dbx) thread -info t@1                              ** 显示可疑线程的信息

 

        Thread t@1 (0xffffffff7a500000) at priority 0

        state: active on    l@1

        base function: 0x0: 0x0000000000000000() stack: 0xffffffff80000000[8388608]

        flags: (none)

        masked signals: (none)

        Currently active in strcmp

(dbx) where                                       ** 显示当前堆栈

current thread: t@1

  [1] strcmp(0x100263d63, 0x0, 0xac, 0x0, 0x30, 0x31), at 0xffffffff7ce3ce90

=>[2] tAtomMatchRqst(), line 177 in "tAtomMatchRqst.c"

  [3] tFlow(), line 96 in "tFlow.c"

  [4] tServer(rqst = 0x1001e6c58), line 73 in "tServer.c"

  [5] _tsvcdsp(0x1700, 0x0, 0x10004ca60, 0x1001e55c0, 0x0, 0x1001d9440), at 0xffffffff7e15d138

  [6] _trunserver(0x1001e3844, 0x1001da958, 0x0, 0xffffffff7e3525c8, 0x1400, 0x1001ee400), at 0xffffffff7e180ea0

  [7] _tstartserver(0x0, 0xffffffff7ffff568, 0x1001bcc38, 0x1001d9440, 0x0, 0x0), at 0xffffffff7e15be28

  [8] main(0xf, 0xffffffff7ffff568, 0xffffffff7ffff5e8, 0x0, 0x0, 0x100000000), at 0x1000099ec

(dbx) quit

-bash-3.00#

 

在这次移植中,每次程序崩溃,dbx总是能够100%准确定位错误代码,所以在这次移植中,Sun Studio开发工具对我们帮助非常大。

 

在测试中发现了两个典型运行期的问题:NULL指针处理和数据非对齐访问。

 

NULL指针处理

NULL指针是指那些指针内容为0的指针,如果直接访问这种NULL指针,其实就是访问地址为0的虚拟内存项。通常在用户模式 (User Level) 中访问NULL指针是不允许的,会和其它非法地址操作一样产生SIGSEGV信号,系统将中断程序执行,产生相应的core dump文件。Solaris系统上就是遵从这个规则,但是在AIX中,为了迎合程序员某些有问题的代码,却允许这种操作,将这种NULL指针作为空字符串处理。比如以下例子是可以直接在AIX运行的,但是在Solaris上程序会崩溃。

 

If (strcmp(pMsg->inHeader.msgVer, NULL)) {

}

 

虽然从语意上将NULL指针作为空字符串处理并不十分准确,但是AIX这种处理方式有时候会“纵容”程序员的错误代码,比如前面那个例子,AIX上的实际用户代码应为如下:

 

If (strcmp(pMsg->inHeader.msgVer, "01" == 0)) {

}

 

大家是不是觉得很奇怪,为什么要在代码中对静态字符串("01")进行判断呢?其实根据需求,正确代码行为应如下:

 

If (strcmp(pMsg->inHeader.msgVer, "01") == 0) {

}

 

可以看到这是编码中一个括号位置的错误。由于AIX这种机制,反而导致一些错误代码能够运行。在Solaris上这种错误代码则需要通过修改,避免这种情况。如果非要让代码访问0地址空间的内容,或者不愿意修改代码,也可以通过如下方式预先加载一个0@0.so库,它可以让你的程序继续执行下去。

 

-bash-3.00# LD_PRELOAD_32= /usr/lib/32/0/@0.so.1

-bash-3.00# export LD_PRELOAD_32            **针对32位程序

-bash-3.00# LD_PRELOAD_64= /usr/lib/64/0/@0.so.1

-bash-3.00# export LD_PRELOAD_64            **针对64位程序  

 

 

数据非对齐访问

测试中,我们遇到一个SIGBUS信号产生的崩溃。这是因为UltraSPARC在设计上为了性能上的考虑,要求数据地址访问,操作都要对齐。如果发现没有对齐的访问,就会向当前进程发出SIGBUS信号,使程序崩溃。而在IBM Power芯片上没有这种要求,但这是以性能为代价的。例如下面例子:

 

short array[4];

int * p = (int *) &array[0];

*p = 1;

int * p = (int *) &array[1];

*p = 2;        **是一个非对齐访问,有可能导致程序崩溃

 

这段程序如果编译成64位程序,运行的时候就会产生Core Dump

 

/opt/SUNWspro/bin/cc –xtarget=generic64 t.c  **-xtarget=generic64编译成64位程序

 

 

因为所有的基本类型数值都会根据它的类型字节长度在内存中进行对齐,比如int数据类型长度是4个字节,那么该数据的地址必定是4的倍数。所以你用int型指针去操作(deference)数据的时候,就要求被操作的数据地址必须是4的倍数,如果未对齐,不是4的倍数的话,恰恰是UltraSPARC不允许的操作,就会产生SIGBUS信号。

 

上面程序定义的short数组在内存中可能分配的情况如下图所示:

 

  

 

 

以图中的内存分配为例,当我们用int型指针p指向array[0]的时候,被修改的数据的地址是4的倍数,运行没有问题,但是如果通过int型指针强制操作array[1]的话,array[1]的地址末尾值是0xfe02,则会是一个非对齐访问,系统会产生SIGBUS,程序被停止。

 

Sun Studio提供“-xmemalign”选项控制是否对编译期间可判断的非对齐访问生成额外的Load/Store指令,避免程序崩溃。

 

如果该段程序编译成32位的话,则不会出现这种问题,因为Sun Studio针对32位编译,默认加上参数“-xmemalign=8i”。“-xmemalign=8i”假定最多 8 字节对齐,并允许未对齐的内存访问行为。

 

/opt/SUNWspro/bin/cc t.c    **默认编译成32位程序

 

这次在项目中遇到的这个SIGBUS信号正是由于这种操作导致的:程序申请了一块大内存,并在这个大内存划分出多个的动态列表,用于存放自定义数据结构。代码先通过sizeof操作符获得每个自定义结构大小,然后直接划分相应的数组列表所需空间。整个数组列表空间操作及数据填写都是用long指针来传递并操作。其中有一个数据结构的定义如下:

 

typedef struct sys_domain_def {

char    domainId[14];    

char    openSign;    

    char    fwdStatus;    

    char    rcvStatus;    

} sys_domain_t;          //**sizeof(sys_domain_t) = 17

 

该数据结构全都是char型变量,造成该结构大小是17个字节,导致整个数组列表除了第一个成员以外,其它成员地址都是未对齐。因为这是运行态的,“-xmemalign”选项无法识别。这时需要修改代码,最佳方式就是加入一些冗余空间,让数据结构的大小成为8的倍数(64位程序),从而数组列表中每一个成员都可以正确对齐。修改后的代码如下:

 

typedef struct sys_domain_def {

char    domainId[14];    

char    openSign;    

    char    fwdStatus;    

char    rcvStatus;

int     padding;

} sys_domain_t;                    //** sizeof(sys_domain_t) = 24

 

 


为了将数据结构大小调整为8的倍数,我们在结构中加入一个int变量(4个字节制造冗余空间。这时数据结构大小并不是21字节,而是变为24个字节。这是因为编译器由于性能的考虑,int这种基本变量的地址默认都是4的倍数,所以不会将int变量直接放置在前面一个char变量之后,会自动空出三个字节后。其修改后的数据结构在内存中的排列形式大致如下:

 

 

 

 


性能测试和调优

最后是性能测试,在不修改代码,不改变系统行为的情况下,对系统和相应的模块做一些性能调整。这份文档主要针对移植,对调优不做详细描述,后续会有相应的总结。

 

总结

虽然整个系统比较庞大,但由于在项目前期,做了详细的调研,整个移植工作还是非常顺利。Solaris, Sun Studio开发工具和Sun公司针对系统移植提供的工具在这个项目中起到非常关键的作用,给软件开发商和客户都留下深刻的印象。

 

参考

§         PORTING TO THE SOLARIS OS: A GUIDE FOR LINUX DEVELOPERS

 

http://www.sun.com/software/solaris/webadvantage/porting_guide.pdf

 

§         Linux 到Solaris 10操作系统迁移指南

 

http://developers.sun.com.cn/home/export/sites/default/home/solaris/Linux_Solaris_Migration_Guide.pdf

 

§         Sun Studio 11: C 用户指南

 

http://docs.sun.com/app/docs/doc/819-4765?l=zh


推荐阅读
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 基于PgpoolII的PostgreSQL集群安装与配置教程
    本文介绍了基于PgpoolII的PostgreSQL集群的安装与配置教程。Pgpool-II是一个位于PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件,提供了连接池、复制、负载均衡、缓存、看门狗、限制链接等功能,可以用于搭建高可用的PostgreSQL集群。文章详细介绍了通过yum安装Pgpool-II的步骤,并提供了相关的官方参考地址。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 如何去除Win7快捷方式的箭头
    本文介绍了如何去除Win7快捷方式的箭头的方法,通过生成一个透明的ico图标并将其命名为Empty.ico,将图标复制到windows目录下,并导入注册表,即可去除箭头。这样做可以改善默认快捷方式的外观,提升桌面整洁度。 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • Firefox火狐浏览器关闭到http://detectportal.firefox.com的流量问题解决办法
    本文介绍了使用Firefox火狐浏览器时出现关闭到http://detectportal.firefox.com的流量问题,并提供了解决办法。问题的本质是因为火狐默认开启了Captive portal技术,当连接需要认证的WiFi时,火狐会跳出认证界面。通过修改about:config中的network.captive-portal-service.en的值为false,可以解决该问题。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • Linux如何安装Mongodb的详细步骤和注意事项
    本文介绍了Linux如何安装Mongodb的详细步骤和注意事项,同时介绍了Mongodb的特点和优势。Mongodb是一个开源的数据库,适用于各种规模的企业和各类应用程序。它具有灵活的数据模式和高性能的数据读写操作,能够提高企业的敏捷性和可扩展性。文章还提供了Mongodb的下载安装包地址。 ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
author-avatar
L灬MOXIE
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有