apache修改最大连接并用ab网站压力测试
apache 2.2,使用默认配置,默认最大连接数是150
1.首先在httpd.conf中加载httpd-mpm.conf配置(去掉前面的注释):
# Server-pool management (MPM
specific)
Include conf/extra/httpd-mpm.conf
2.可见的MPM配置在/usr/local/apache/conf/extra/httpd-mpm.conf,但里面根据httpd的工作模式分了很多块,哪一部才是当前httpd的工作模式呢?可通过执行
apachectl -l 来查看:
[root@zh888 extra]# /usr/local/apache/bin/apachectl
-l//因为采用静态编译
Compiled in
modules:
core.c
mod_authn_file.c
mod_authn_default.c
mod_authz_host.c
mod_authz_groupfile.c
mod_authz_user.c
mod_authz_default.c
mod_auth_basic.c
mod_cache.c
mod_disk_cache.c
mod_mem_cache.c
mod_include.c
mod_filter.c
mod_deflate.c
mod_log_config.c
mod_env.c
mod_expires.c
mod_headers.c
mod_setenvif.c
mod_version.c
mod_proxy.c
mod_proxy_connect.c
mod_proxy_ftp.c
mod_proxy_http.c
mod_proxy_scgi.c
mod_proxy_ajp.c
mod_proxy_balancer.c
prefork.c//才用prefork所以在httpd-mpm.conf中找到mpm_prefork_module
http_core.c
mod_mime.c
mod_status.c
mod_autoindex.c
mod_asis.c
mod_cgi.c
mod_negotiation.c
mod_dir.c
mod_actions.c
mod_userdir.c
mod_alias.c
mod_rewrite.c
mod_so.c
所以修改连接数就在/usr/local/apache/conf/extra/httpd-mpm.conf这个文件了,打开它就找到prefork模式的默认配置是:
StartServers
5
MinSpareServers 5
MaxSpareServers 10
MaxClients
150
MaxRequestsPerChild 0
prefork
控制进程在最初建立“StartServers”个子进程后,为了满足MinSpareServers设置的需要创建一个进程,等待一秒钟,继续创建两个,再等待一秒钟,继续创建四个……如此按指数级增加创建的进程数,最多达到每秒32个,直到满足MinSpareServers设置的值为止。
这种模式可以不必在请求到来时再产生新的进程,从而减小了系统开销以增加性能。MaxSpareServers设置了最大的空闲进程数,如果空闲进程数大于这个值,Apache会自动kill掉一些多余进程。这个值不要设得过大,但如果设的值比MinSpareServers小,Apache会自动把其调整为
MinSpareServers+1。如果站点负载较大,可考虑同时加大MinSpareServers和MaxSpareServers。
MaxRequestsPerChild设置的是每个子进程可处理的请求数。每个子进程在处理了“MaxRequestsPerChild”个请求后将自动销毁。0意味着无限,即子进程永不销毁。
虽然缺省设为0可以使每个子进程处理更多的请求,但如果设成非零值也有两点重要的好处:
1、可防止意外的内存泄漏。
2、在服务器负载下降的时侯会自动减少子进程数。因此,可根据服务器的负载来调整这个值。MaxClients是这些指令中最为重要的一个,设定的是
Apache可以同时处理的请求,是对Apache性能影响最大的参数。其缺省值150是远远不够的,如果请求总数已达到这个值(可通过ps -ef|grep
httpd|wc
-l来确认),那么后面的请求就要排队,直到某个已处理请求完毕。这就是系统资源还剩下很多而HTTP访问却很慢的主要原因。虽然理论上这个值越大,可以处理的请求就越多,但Apache默认的限制不能大于256。ServerLimit指令无须重编译Apache就可以加大MaxClients。
注意,虽然通过设置ServerLimit,我们可以把MaxClients加得很大,但是往往会适得其反,系统耗光所有内存。以我手头的一台服务器为例:内存2G,每个apache进程消耗大约0.5%(可通过ps
aux来确认)的内存,也就是10M,这样,理论上这台服务器最多跑200个apache进程就会耗光系统所有内存,所以,设置MaxClients要慎重。
3.要加到多少?
连接数理论上当然是支持越大越好,但要在服务器的能力范围内,这跟服务器的CPU、内存、带宽等都有关系。
查看当前的连接数可以用:
ps aux | grep httpd | wc -l
计算httpd占用内存的平均数:
ps
aux|grep -v grep|awk '/httpd/{sum+=$6;n++};'
由于基本都是静态页面,CPU消耗很低,每进程占用内存也不算多,大约200K。
假如服务器内存有2G,除去常规启动的服务大约需要500M(保守估计),还剩1.5G可用,那么理论上可以支持1.5*1024*1024*1024/
= 8053.
约8K个进程,支持2W人同时访问应该是没有问题的(能保证其中8K的人访问很快,其他的可能需要等待1、2秒才能连上,而一旦连上就会很流畅)
控制最大连接数的MaxClients ,因此可以尝试配置为:
StartServers 5
MinSpareServers
5
MaxSpareServers 10
ServerLimit 5500
MaxClients
5000
MaxRequestsPerChild 100
注意,MaxClients默认最大为250,若要超过这个值就要显式设置ServerLimit,且ServerLimit要放在MaxClients之前,值要不小于MaxClients,不然重启httpd时会有提示。
重启httpd后,通过反复执行pgrep httpd|wc -l
来观察连接数,可以看到连接数在达到MaxClients的设值后不再增加,但此时访问网站也很流畅,那就不用贪心再设置更高的值了,不然以后如果网站访问突增不小心就会耗光服务器内存,可根据以后访问压力趋势及内存的占用变化再逐渐调整,直到找到一个最优的设置值。
(MaxRequestsPerChild不能设置为0,可能会因内存泄露导致服务器崩溃)
更佳最大值计算的公式:
apache_max_process_with_good_perfermance < (total_hardware_memory /
apache_memory_per_process ) * 2
apache_max_process =
apache_max_process_with_good_perfermance * 1.5
4.用/usr/local/apache/bin/ab来测试压力不过还有一个工具叫webbench也可以测试。
[root@zh888 bin]# /usr/local/apache/bin/ab -n 100 -c
100http://192.168.100.1:8000/index.php//参数很多一般我们用 -c 和 -n
参数就可以了这个表示同时处理100个请求并运行100次index.php文件.
This is ApacheBench Version 2.3
Copyright 1996 Adam Twiss Zeus Technology
Ltd
Licensed to The Apache Software Foundation
Benchmarking 192.168.100.1 (be patient).....done
Server Software: Apache/2.2.19//平台apache 版本2.0.54
Server Hostname: 192.168.100.1//服务器主机名
Server Port: 8000//端口
Document Path: /index.php//测试的页面文档
Document Length: bytes//文档大小
Concurrency Level: 100//并发数
Time taken for tests: 4.482 seconds//整个测试持续的时间
Complete requests: 100//完成的请求数量
Failed requests: 0//失败的请求数量
Write errors: 0
Total transferred: bytes//整个场景中的网络传输量
HTML transferred: bytes
Requests per second: 22.31 [#/sec]
(mean)//大家最关心的指标之一,相当于 LR 中的 每秒事务数 ,后面括号中的 mean 表示这是一个平均值
Time per request: 4481.929 [ms] (mean)//大家最关心的指标之二,相当于 LR 中的 平均事务响应时间 ,后面括号中的
mean 表示这是一个平均值
Time per request: 44.819 [ms] (mean across all concurrent
requests)//每个请求实际运行时间的平均值
Transfer rate: 793.68 [Kbytes/sec]
received//平均每秒网络上的流量,可以帮助排除是否存在网络流量过大导致响应时间延长的问题
Connection Times (ms)//网络上消耗的时间的分解。
min mean[+/-sd] median max
Connect: 0 73 24.5 79 96
Processing: 252
2542 1291.7 2590 4386
Waiting: 252 2541 1292.5 2590 4384
Total: 253 2615
1311.0 2671 4482
Percentage of the requests served within a certain time
(ms)//整个场景中所有请求的响应情况。在场景中每个请求都有一个响应时间,其中50%的用户响应时间小于1093 毫秒,60% 的用户响应时间小于1247
毫秒,最大的响应时间小于7785
毫秒
由于对于并发请求,cpu实际上并不是同时处理的,而是按照每个请求获得的时间片逐个轮转处理的,所以基本上第一个Time per
request时间约等于第二个Time per request时间乘以并发请求数
50% 2671
66% 3351
75% 3923
80% 4095
90% 4358
95%
4441
98% 4472
99% 4482
100% 4482 (longest request)
4.是在使用Apache2.2的ab进行测试时遇到的问题:
使用ab测试的时候当-c并发数超过1024就会出错:
windows下提示:apr_pollset_create
failed: Invalid argument (22)
linux下提示:socket: Too
many open files (24)
解决办法:
linux下:ulimit -n
(设置系统允许同时打开的文件数,系统默认是1024),可以用ulimit -a查看open files项,# lsof |wc -l
可以查看系统所有进程的文件打开数。
ulimit:显示(或设置)用户可以使用的资源限制
ulimit -a 显示用户可以使用的资源限制
ulimit unlimited
不限制用户可以使用的资源,但本设置对可打开的最大文件数(max open files)
和可同时运行的最大进程数(max user
processes)无效
ulimit -n 设置用户可以同时打开的最大文件数(max open files)
例如:ulimit -n 8192
如果本参数设置过小,对于并发访问量大的网站,可能会出现too many open files的错误
ulimit -u
设置用户可以同时运行的最大进程数(max user processes)
例如:ulimit -u 1024
5最后补充一下apache的知识:
简介
Apache
HTTP服务器被设计为一个强大的、灵活的能够在多种平台以及不同环境下工作的服务器。不同的平台和不同的环境经常产生不同的需求,或是为了达到同样的最佳效果而采用不同的方法。Apache凭借它的模块化设计很好的适应了大量不同的环境。这一设计使得网站管理员能够在编译时和运行时凭借载入不同的模块来决定服务器的不同附加功能。
Apache2.0将这种模块化的设计延伸到了web服务器的基础功能上。这个版本带有多路处理模块(MPM)的选择以处理网络端口绑定、接受请求并指派钟进程来处理这些请求。
将模块化设计延伸到这一层次主要有以下两大好处:
*
Apache可以更简洁、更有效地支持各种操作系统。尤其是在mpm_winnt中使用本地网络特性代替Apache1.3中使用的POSIX模拟层后,Windows版本的Apache现在具有更好的性能。这个优势借助特定的MPM同样延伸到了其他各种操作系统。
*
服务器可以为某些特定的站点进行定制。比如,需要更好伸缩性的站点可以选择象worker或event这样线程化的MPM,而需要更好的稳定性和兼容性以适应一些旧的软件的站点可以用prefork
。
从用户角度来看,MPM更像其他的Apache模块。主要的不同在于:不论何时,必须有且仅有一个MPM被载入到服务器中。现有的MPM列表可以在模块索引中找到。
选择一个MPM
MPM必须在编译配置时进行选择,并静态编译到服务器中。如果编译器能够确定线程功能被启用,它将会负责优化大量功能。因为一些MPM在Unix上使用了线程,而另外一些没有使用,所以如果在编译配置时选择MPM并静态编译进Apache,Apache将会有更好的表现。
你可以在使用configure脚本时用 --with-mpm=NAME 选项指定MPM,NAME就是你想使用的MPM的名称。
一旦服务器编译完成,就可以用 ./httpd -l
命令来查看使用了哪个MPM。这个命令将列出所有已经被编译到服务器中的模块,包括MPM。
我们主要阐述prefork和worker这两种和性能关系最大的产品级MPM。
Apache MPM prefork
一个非线程型的、预派生的MPM
概述
这个多路处理模块(MPM)实现了一个非线程型的、预派生的web服务器,它的工作方式类似于Apache
1.3。它适合于没有线程安全库,需要避免线程兼容性问题的系统。它是要求将每个请求相互独立的情况下最好的MPM,这样若一个请求出现问题就不会影响到其他请求。
这个MPM具有很强的自我调节能力,只需要很少的配置指令调整。最重要的是将MaxClients设置为一个足够大的数值以处理潜在的请求高峰,同时又不能太大,以致需要使用的内存超出物理内存的大小。
工作方式
一个单独的控制进程(父进程)负责产生子进程,这些子进程用于监听请求并作出应答。Apache总是试图保持一些备用的(spare)或者是空闲的子进程用于迎接即将到来的请求。这样客户端就不需要在得到服务前等候子进程的产生。
StartServers MinSpareServers MaxSpareServers
MaxClients指令用于调节父进程如何产生子进程。通常情况下Apache具有很强的自我调节能力,所以一般的网站不需要调整这些指令的默认值。可能需要处理最大超过256个并发请求的服务器可能需要增加MaxClients的值。内存比较小的机器则需要减少MaxClients的值以保证服务器不会崩溃。更多关于调整进程产生的问题请参见性能方面的提示。
在Unix系统中,父进程通常以root身份运行以便邦定80端口,而Apache产生的子进程通常以一个低特权的用户运行。User和Group指令用于设置子进程的低特权用户。运行子进程的用户必须要对它所服务的内容有读取的权限,但是对服务内容之外的其他资源必须拥有尽可能少的权限。
MaxRequestsPerChild指令控制服务器杀死旧进程产生新进程的频率。
Apache MPM worker
支持混合的多线程多进程的多路处理模块
概述
此多路处理模块(MPM)使网络服务器支持混合的多线程多进程。由于使用线程来处理请求,所以可以处理海量请求,而系统资源的开销小于基于进程的MPM。但是,它也使用了多进程,每个进程又有多个线程,以获得基于进程的MPM的稳定性。
控制这个MPM的最重要的指令是,控制每个子进程允许建立的线程数的ThreadsPerChild指令,和控制允许建立的总线程数的MaxClients指令。
工作方式
每个进程可以拥有的线程数量是固定的。服务器会根据负载情况增加或减少进程数量。一个单独的控制进程(父进程)负责子进程的建立。每个子进程可以建立ThreadsPerChild数量的服务线程和一个监听线程,该监听线程监听接入请求并将其传递给服务线程处理和应答。
Apache总是试图维持一个备用(spare)或是空闲的服务线程池。这样,客户端无须等待新线程或新进程的建立即可得到处理。初始化时建立的进程数量由StartServers指令决定。随后父进程检测所有子进程中空闲线程的总数,并新建或结束子进程使空闲线程的总数维持在MinSpareThreads和MaxSpareThreads所指定的范围内。由于这个过程是自动调整的,几乎没有必要修改这些指令的缺省值。可以并行处理的客户端的最大数量取决于MaxClients指令。活动子进程的最大数量取决于MaxClients除以ThreadsPerChild的值。
有两个指令设置了活动子进程数量和每个子进程中线程数量的硬限制。要想改变这个硬限制必须完全停止服务器然后再启动服务器(直接重启是不行的),ServerLimit是活动子进程数量的硬限制,它必须大于或等于MaxClients除以ThreadsPerChild的值。ThreadLimit是所有服务线程总数的硬限制,它必须大于或等于ThreadsPerChild指令。这两个指令必须出现在其他workerMPM指令的前面。
在设置的活动子进程数量之外,还可能有额外的子进程处于"正在中止"的状态但是其中至少有一个服务线程仍然在处理客户端请求,直到到达MaxClients以致结束进程,虽然实际数量会很小。这个行为能够通过以下禁止特别的子进程中止的方法来避免:
* 将MaxRequestsPerChild设为"0"
* 将MaxSpareThreads和MaxClients设为相同的值
一个典型的针对workerMPM的配置如下:
ServerLimit 16
StartServers 2
MaxClients
150
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild
25
在Unix中,为了能够绑定80端口,父进程一般都是以root身份启动,随后,Apache以较低权限的用户建立子进程和线程。User和Group指令用于设置Apache子进程的权限。虽然子进程必须对其提供的内容拥有读权限,但应该尽可能给予它较少的特权。另外,除非使用了suexec
,否则,这些指令设置的权限将被CGI脚本所继承。
MaxRequestsPerChild指令用于控制服务器建立新进程和结束旧进程的频率。
常用指令:
StartServers
指令
StartServers指令设置了服务器启动时建立的子进程数量。因为子进程数量动态的取决于负载的轻重,所有一般没有必要调整这个参数。
MinSpareServers
指令
MinSpareServers指令设置空闲子进程的最小数量。所谓空闲子进程是指没有正在处理请求的子进程。如果当前空闲子进程数少于MinSpareServers
,那么Apache将以最大每秒一个的速度产生新的子进程。
只有在非常繁忙机器上才需要调整这个参数。将此参数设的太大通常是一个坏主意。
MaxSpareServers
指令
MaxSpareServers指令设置空闲子进程的最大数量。所谓空闲子进程是指没有正在处理请求的子进程。如果当前有超过MaxSpareServers数量的空闲子进程,那么父进程将杀死多余的子进程。
只有在非常繁忙机器上才需要调整这个参数。将此参数设的太大通常是一个坏主意。如果你将该指令的值设置为比MinSpareServers小,Apache将会自动将其修改成"MinSpareServers+1"。
MaxClients
指令
MaxClients指令设置了允许同时伺服的最大接入请求数量。任何超过MaxClients限制的请求都将进入等候队列,直到达到ListenBacklog指令限制的最大值为止。一旦一个链接被释放,队列中的请求将得到服务。
对于非线程型的MPM(也就是prefork),MaxClients表示可以用于伺服客户端请求的最大子进程数量,默认值是256。要增大这个值,你必须同时增大ServerLimit
。
对于线程型或者混合型的MPM(也就是beos或worker),MaxClients表示可以用于伺服客户端请求的最大线程数量。线程型的beos的默认值是50。对于混合型的MPM默认值是16(ServerLimit)乘以25(ThreadsPerChild)的结果。因此要将MaxClients增加到超过16个进程才能提供的时候,你必须同时增加ServerLimit的值。
MaxRequestsPerChild
指令
MaxRequestsPerChild指令设置每个子进程在其生存期内允许伺服的最大请求数量。到达MaxRequestsPerChild的限制后,子进程将会结束。如果MaxRequestsPerChild为"0",子进程将永远不会结束。
不同的默认值
在mpm_netware和mpm_winnt上的默认值是"0"。
将MaxRequestsPerChild设置成非零值有两个好处:
*
可以防止(偶然的)内存泄漏无限进行,从而耗尽内存。
*
给进程一个有限兽命,从而有助于当服务器负载减轻的时候减少活动进程的数量。
注意:
对于KeepAlive链接,只有第一个请求会被计数。事实上,它改变了每个子进程限制最大链接数量的行为。
ThreadsPerChild
指令
这个指令设置了每个子进程建立的线程数。子进程在启动时建立这些线程后就不再建立新的线程了。如果使用一个类似于mpm_winnt只有一个子进程的MPM,这个数值要足够大,以便可以处理可能的请求高峰。如果使用一个类似于worker有多个子进程的MPM,每个子进程所拥有的所有线程的总数要足够大,以便可以处理可能的请求高峰。
对于mpm_winnt,ThreadsPerChild的默认值是64;对于其他MPM是25。
ThreadLimit
指令
这个指令设置了每个子进程可配置的线程数ThreadsPerChild上限。任何在重启期间对这个指令的改变都将被忽略,但对ThreadsPerChild的修改却会生效。
使用这个指令时要特别当心。如果将ThreadLimit设置成一个高出ThreadsPerChild实际需要很多的值,将会有过多的共享内存被分配。如果将ThreadLimit和ThreadsPerChild设置成超过系统的处理能力,Apache可能无法启动,或者系统将变得不稳定。该指令的值应当和ThreadsPerChild可能达到的最大值保持一致。
对于mpm_winnt,ThreadLimit的默认值是1920;对于其他MPM这个值是64。
注意:
Apache在编译时内部有一个硬性的限制"ThreadLimit
"(对于mpm_winnt是"ThreadLimit "),你不能超越这个限制。
ServerLimit
指令
对于preforkMPM,这个指令设置了MaxClients最大允许配置的数值。对于workerMPM,这个指令和ThreadLimit结合使用设置了MaxClients最大允许配置的数值。任何在重启期间对这个指令的改变都将被忽略,但对MaxClients的修改却会生效。
使用这个指令时要特别当心。如果将ServerLimit设置成一个高出实际需要许多的值,将会有过多的共享内存被分配。如果将ServerLimit和MaxClients设置成超过系统的处理能力,Apache可能无法启动,或者系统将变得不稳定。
对于preforkMPM,只有在你需要将MaxClients设置成高于默认值256的时候才需要使用这个指令。要将此指令的值保持和MaxClients一样。
对于workerMPM,只有在你需要将MaxClients和ThreadsPerChild设置成需要超过默认值16个子进程的时候才需要使用这个指令。不要将该指令的值设置的比MaxClients
和ThreadsPerChild需要的子进程数量高。
注意:
Apache在编译时内部有一个硬限制"ServerLimit
"(对于preforkMPM为"ServerLimit ")。你不能超越这个限制。
配置apache使用workerMPM:
cd httpd-2.0.55
make clean
vi server/mpm/worker/worker.c
修改define
DEFAULT_THREAD_LIMIT 64 为100
即=你要设置的ThreadsPerChild的值(修改默认ThreadsPerChild
)
修改define
DEFAULT_SERVER_LIMIT 16 为 25
即=你要设置的ServerLimit值(修改默认ServerLimit值)
:wq
./configure
--prefix=/usr/local/apache --with-mpm=worker
make
make install
cd
/usr/local/apache/conf
vi httpd.conf
修改
StartServers
2
MaxClients 150
MinSpareThreads 25
MaxSpareThreads
75
ThreadsPerChild 25
MaxRequestsPerChild 0
内容为
StartServers
3
MaxClients 2000
ServerLimit 25
MinSpareThreads 50
MaxSpareThreads
200
ThreadLimit 200
ThreadsPerChild 100
MaxRequestsPerChild 0
修改
serveradmin servername等信息为正确配置
:wq
/usr/local/apache/bin/apachectl
start
vi /etc/rc.loacl
添加 /usr/local/apache/bin/apachectl
start
PS:
用netstat -an|grep ESTABLISHED|grep 202.100.85.249:80 |wc -l
看连接数,使用worker模式后,httpd进程数变少不能反映tcp连接数
虚拟机上的linux访问本机Windows共享文件设置方法
1.安装VMtools for linux:
选择vmware
workstation程序菜单中VM > install VMware tools...
2. 进入linux
挂载vmtools 安装文件:
mount /dev/cdrom
/mnt/cdrom(vmtools的安装文件放在vmware虚拟的cdrom中,首先要mount上这个光驱才能找到安装文件)
进入/mnt/cdrom 目录,把安装文件解压到/tmp :
cd /mnt/cdrom
tar -zxvf
VMwareTools-5.0.0-12124.i386.tar.gz -C /tmp(把安装文件解压到/tmp)
执行vwware的安装脚本:
cd
/tmp/vmware-tools-distrib
./vmware-install.pl
在这里,安装程序会询问安装文件存放位置和设置分辨率等一系列问题,在大多数情况下,安装默认配置vmware
tools就可以正常工作,因此,这里对每一个问题按回车键选择默认配置。
安装完以后,vmware会添加一个vmhgfs的模块到内核中,可以使用lsmod查看.
3.设置共享文件夹:
选择vmware
workstation程序菜单中VM>Settings>Options>Shared Folders
>Properties
点击对话框右下的“add”按钮,点击“下一步”
在文本框“name”中输入共享目录的名字(这里填写的目录名以后VM的linux系统中将显示出同样的目录名),比如:win_linux_share
下一个对话框是选择共享的方式:Enable
this share是指这个共享长期有效,目录可读写;Read-only方式是指这个共享长期有效,目录只读;Disable after this
session方式是指下次ghost computer被关闭或挂起后,共享将会失效。一般情况下选择Enable this share然后点击“完成”
shared folder设置完毕
4.在VM的linux查看shared
folder目录的使用
cd /mnt/hgfs
/mnt/hgfs/目录下就同步了windows中的win_linux_share文件夹
[root@localhost network-scripts]# cd
/mnt/hgfs
[root@localhost hgfs]# ls
win_linux_share
[root@localhost
hgfs]# cd win_linux_share/
[root@localhost win_linux_share]#
ls
sunzhaoyao.txt
环境:
OS:Red Hat Linux As 5
1.服务器上创建共享目录
mkdir
doc_share
2.编辑exports文件
vim /etc/exports
写入
/doc_share
192.168.2.131/255.255.255.0(rw,sync)
格式是:
要共享的目录
共享的IP及掩码或者域名(权限,同步更新)
3.启动服务
/etc/init.d/portmap restart
/etc/init.d/nfs restart
chkconfig nfs
on
chkconfig portmap on
然后关闭防火墙以及更改Selinux关于NIS的选项
/etc/init.d/iptables stop (防护墙服务关闭)
chkconfig iptables off
system-config-selinux (设置selinux)
查看共享的东西
[root@rac1
/]# exportfs -rv
exporting
192.168.2.131/255.255.255.0:/doc_share
试着在本机看能否加载
mount
192.168.2.131:/doc_share /mnt
[root@rac1 doc_share]# echo
aa>aa.txt
[root@rac1 doc_share]# ls
aa.txt
[root@rac1 /]# cd
/mnt
[root@rac1 mnt]# ls
aa.txt
4.客户端
手工mount:
mount -o nolock 192.168.2.131:/doc_share
/mnt
这个时候可以看到在节点1上内容了.
[root@rac2
mnt]# cd /mnt
[root@rac2 mnt]# ls
aa.txt
自动mount:
编辑fstab文件,实现开机自动挂载
mount -t nfs IP:/目录 挂载到的目录
(此为临时挂载)
如:mount -t nfs
192.168.0.9:/doce /doc
vim /etc/fstab 添加如下内容
192.168.2.131:/doc_share /mnt nfs
defaults 0 0
相关的一些命令:
showmout命令对于NFS的操作和查错有很大的帮助.
showmout
-a:这个参数是一般在NFS SERVER上使用,是用来显示已经mount上本机nfs目录的cline机器.
-e:显示指定的NFS
SERVER上export出来的目录.
例如:
showmount -e 192.168.0.30
Export list for localhost:
/tmp *
/home/linux *.linux.org
/home/public (everyone)
/home/test 192.168.0.100
exportfs命令:
如果我们在启动了NFS之后又修改了/etc/exports,是不是还要重新启动nfs呢?这个时候我们就可以用exportfs命令来使改动立刻生效,该命令格式如下:
exportfs
[-aruv]
-a :全部mount或者unmount /etc/exports中的内容
-r :重新mount
/etc/exports中分享出来的目录
-u :umount 目录
-v :在 export
的时候,将详细的信息输出到屏幕上.
具体例子:
[root @test root]# exportfs
-rv <==全部重新 export 一次!
exporting
192.168.0.100:/home/test
exporting 192.168.0.*:/home/public
exporting
*.the9.com:/home/linux
exporting *:/home/public
exporting *:/tmp
reexporting 192.168.0.100:/home/test to kernel
exportfs -au
<==全部都卸载了
-------------------------------------------------------------------------------
今天在机器上配置NFS文件系统,在/etc/exports中加入以下信息:
/testfs 10.0.0.0/8(rw)
重启NFS服务以后,在客户机通过mount -o rw -t nfs 10.214.54.29:/testfs /rd1命令将网络文件mount到本地。执行完成之后,目录是可以访问了,但无法写入。感觉有点奇怪,明明在命令中指定可以写入了。于是到网上搜索资料,发现exports目录权限中,有这么一个参数no_root_squash。其作用是:登入 NFS 主机使用分享目录的使用者,如果是 root 的话,那么对于这个分享的目录来说,他就具有 root 的权限!。默认情况使用的是相反参数 root_squash:在登入 NFS 主机使用分享之目录的使用者如果是 root 时,那么这个使用者的权限将被压缩成为匿名使用者,通常他的 UID 与 GID 都会变成 nobody 那个身份。
因为我的客户端是使用root登录的,自然权限被压缩为nobody了,难怪无法写入。将配置信息改为:
/testfs 10.0.0.0/8(rw,no_root_squash)
据说有点不安全,但问题是解决了。
另外,在测试NFS文件系统时,会经常mount和umount文件,但有时会出现device is busy的错误提示。你肯定感到很奇怪,我明明没有使用啊,看看你当前所在的目录,是不是在mount的文件目录中?回退到上层目录重新umount,是不是OK了?
ichartjs是一款基于HTML5的图形库。使用纯javascript语言,利用HTML5的canvas标签绘制各式图形。ichartjs可以为web应用提供简单、直观、可交互的体验级图表组件。是web图表方面的解决方案。最近正好在学HTML5,顺便就用ichartjs来练习。ichartjs目前支持饼图、折线图、区域图、柱形图、条形图。ichartjs是基于Apache License 2.0 协议的开源项目。今天介绍的是如何在android手机上动态实现3D柱形图。若想详细了解ichartjs,可以访问ichartjs官网:http://www.ichartjs.cn/index.html
实现主要原理是所需实现的数据打包成json格式,因为ichartjs规定的数据源统一采用json对象方式。数据源分为单一数据源与集合多值数据源,单一数据源的值为单一的数值,而集合多值数据源为数值集合。3D柱形图使用的单一的数据源。废话不多说了,直接上代码。
首先编写的是封装数据的实体类Contact:
- package com.chinasofti.html;
-
- public class Contact {
- private String name;
- private double value;
- private String color;
-
-
-
-
-
-
-
- public Contact(String name, double value, String color) {
- this.name = name;
- this.value = value;
- this.color = color;
- }
-
-
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public double getValue() {
- return value;
- }
- public void setValue(double value) {
- this.value = value;
- }
- public String getColor() {
- return color;
- }
- public void setColor(String color) {
- this.color = color;
- }
-
- }
package com.chinasofti.html;
public class Contact {
private String name; // 浏览器的名称
private double value; // 浏览器对应的所占市场份额值
private String color; // 在柱形图中所显示的颜色
/**
* 构造函数
* @param name 浏览器的名称
* @param value 浏览器对应的所占市场份额值
* @param color 在柱形图中所显示的颜色
*/
public Contact(String name, double value, String color) {
this.name = name;
this.value = value;
this.color = color;
}
// 下面是三个实例变量的getters and setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getValue() {
return value;
}
public void setValue(double value) {
this.value = value;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
接着创建一个list将所需要的contact对象添加到list中:
- import java.util.ArrayList;
- import java.util.List;
-
- import com.chinasofti.html.Contact;
-
- public class ContactService {
-
- public List<Contact> getContacts() {
- List<Contact> contacts = new ArrayList<Contact>();
- contacts.add(new Contact("IE", 32.85, "#a5c2d5"));
- contacts.add(new Contact("Chrome", 33.59, "#cbab4f"));
- contacts.add(new Contact("Firefox", 22.85, "#76a871"));
- contacts.add(new Contact("Safari", 7.39, "#9f7961"));
- contacts.add(new Contact("Opera", 1.63, "#a56f8f"));
- contacts.add(new Contact("Other", 1.69, "#6f83a5"));
- return contacts;
- }
- }
import java.util.ArrayList;
import java.util.List;
import com.chinasofti.html.Contact;
public class ContactService {
public List<Contact> getContacts() {
List<Contact> contacts = new ArrayList<Contact>();
contacts.add(new Contact("IE", 32.85, "#a5c2d5"));
contacts.add(new Contact("Chrome", 33.59, "#cbab4f"));
contacts.add(new Contact("Firefox", 22.85, "#76a871"));
contacts.add(new Contact("Safari", 7.39, "#9f7961"));
contacts.add(new Contact("Opera", 1.63, "#a56f8f"));
contacts.add(new Contact("Other", 1.69, "#6f83a5"));
return contacts;
}
}
然后编写android主界面代码,实现list转换成json格式字符串,并实现和html文件的交互:
- import java.util.List;
-
- import org.json.JSONArray;
- import org.json.JSONException;
- import org.json.JSONObject;
-
- import android.app.Activity;
- import android.os.Bundle;
- import android.util.Log;
- import android.webkit.WebView;
-
- public class MainActivity extends Activity {
- private static final String TAG = "MainActivity";
- private ContactService contactService;
- private WebView webView;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
- contactService = new ContactService();
- webView = (WebView) this.findViewById(R.id.webView);
- webView.getSettings().setJavaScriptEnabled(true);
- webView.getSettings().setBuiltInZoomControls(true);
-
- webView.addJavascriptInterface(this,TAG);
- webView.loadUrl("file:///android_asset/3dchart.html");
- }
-
-
-
-
-
- public String getContacts() {
- List<Contact> contacts = contactService.getContacts();
- String json = null;
- try {
- JSONArray array = new JSONArray();
- for (Contact contact : contacts) {
-
- JSONObject item = new JSONObject();
- item.put("name", contact.getName());
- item.put("value", contact.getValue());
- item.put("color", contact.getColor());
- array.put(item);
- }
- json = array.toString();
- Log.i(TAG, json);
-
- } catch (JSONException e) {
- e.printStackTrace();
- }
- return json;
- }
- }
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.webkit.WebView;
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
private ContactService contactService; // 构建list的类
private WebView webView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
contactService = new ContactService();
webView = (WebView) this.findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true); // 允许使用javascript脚本语言
webView.getSettings().setBuiltInZoomControls(true); // 设置可以缩放
// 设置javaScript可用于操作MainActivity类
webView.addJavascriptInterface(this,TAG);
webView.loadUrl("file:///android_asset/3dchart.html");
}
/**
* 实现将list转换成json格式字符串
* @return json格式的字符串
*/
public String getContacts() {
List<Contact> contacts = contactService.getContacts();
String json = null;
try {
JSONArray array = new JSONArray();
for (Contact contact : contacts) {
JSONObject item = new JSONObject();
item.put("name", contact.getName());
item.put("value", contact.getValue());
item.put("color", contact.getColor());
array.put(item);
}
json = array.toString();
Log.i(TAG, json);
// webView.loadUrl("javascript:show('" + json + "')");
} catch (JSONException e) {
e.printStackTrace();
}
return json;
}
}
最后是编辑html文件。要实现ichartjs表图,首先要保证在assets目录下已导入了ichart - 1.0.js。然后对html文件进行编辑:
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8" />
- <title>Hello World</title>
- <meta name="Description" content="" />
- <meta name="Keywords" content="" />
- <script type="text/javascript" src="ichart-1.0.js"></script>
- <script type="text/javascript">
- var data = new Array();
- var contact = window.MainActivity.getContacts(); //得到MainActivity中转换出的json字符串
- eval('data='+contact); //得到json数据
-
- $(function(){
- new iChart.Column3D({
- render : 'canvasDiv', //渲染的Dom目标,canvasDiv为Dom的ID
- data: data, //绑定数据
- title : 'Top 5 Browsers in August 2012', //设置标题
- showpercent:true, //显示百分比
- decimalsnum:2,
- width : 800, //设置宽度,默认单位为px
- height : 400, //设置高度,默认单位为px
- align:'left',
- offsetx:50,
- legend : {
- enable : true
- },
- coordinate:{ //配置自定义坐标轴
- scale:[{ //配置自定义值轴
- width:600,
- position:'left', //配置左值轴
- start_scale:0, //设置开始刻度为0
- end_scale:40, //设置结束刻度为40
- scale_space:8, //设置刻度间距为8
- listeners:{ //配置事件
- parseText:function(t,x,y){ //设置解析值轴文本
- return {text:t+"%"}
- }
- }
- }]
- }
- }).draw(); //调用绘图方法开始绘图
- });
- </script>
- </head>
- <body>
- <div id='canvasDiv'></div>
- </body>
- </html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World</title>
<meta name="Description" content="" />
<meta name="Keywords" content="" />
<script type="text/javascript" src="ichart-1.0.js"></script>
<script type="text/javascript">
var data = new Array();
var contact = window.MainActivity.getContacts(); //得到MainActivity中转换出的json字符串
eval('data='+contact); //得到json数据
$(function(){
new iChart.Column3D({
render : 'canvasDiv', //渲染的Dom目标,canvasDiv为Dom的ID
data: data, //绑定数据
title : 'Top 5 Browsers in August 2012', //设置标题
showpercent:true, //显示百分比
decimalsnum:2,
width : 800, //设置宽度,默认单位为px
height : 400, //设置高度,默认单位为px
align:'left',
offsetx:50,
legend : {
enable : true
},
coordinate:{ //配置自定义坐标轴
scale:[{ //配置自定义值轴
width:600,
position:'left', //配置左值轴
start_scale:0, //设置开始刻度为0
end_scale:40, //设置结束刻度为40
scale_space:8, //设置刻度间距为8
listeners:{ //配置事件
parseText:function(t,x,y){ //设置解析值轴文本
return {text:t+"%"}
}
}
}]
}
}).draw(); //调用绘图方法开始绘图
});
</script>
</head>
<body>
<div id='canvasDiv'></div>
</body>
</html>
最后得到效果为:
函数trunc是一个Oracle内置的函数,可以对date类型数据进行“度身裁剪”,来适应不同类型的数据需求。
在前篇《Oracle日期类型操作几个问题》中,我们已经了解到date类型的基本知识。date类型是一种包括年、月、日、时、分和秒的数据类型,可以表示相对精确的时间信息。内部存储上,date类型是类似于数字类型的,可以通过加减操作实现对日期的推进和后退。
但是,日期格式的精确常常给我们带来一些困扰,特别是其中的时分秒信息。很多时候,我们对这部分信息是不需要的。比如指定日期查询、只显示天信息等等。借助To_char虽然可以实现一部分这种需要,但是这样做格式上比较复杂,而且进行了数据类型的转换。是否存在不变化数据类型的方法,对日期型数据进行处理。答案就是trunc函数。
trunc(date)
截断函数trunc的作用就是将日期类型数据按照指定格式截断,返回一个日期变量数据。例如:
SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
TO_CHAR(SYSDATE,'YYYY-MM-DDHH2
------------------------------
2010-12-10 20:39:58
SQL> select trunc(sysdate) from dual;
TRUNC(SYSDATE)
--------------
2010-12-10
SQL> select to_char(trunc(sysdate),'yyyy-mm-dd hh24:mi:ss') from dual;
TO_CHAR(TRUNC(SYSDATE),'YYYY-M
------------------------------
2010-12-10 00:00:00
默认情况下,sysdate函数返回的日期类型数据包括当前的具体时间。通过trunc(date)的处理,直接截取到天信息,返回指定天的零时。
trunc函数还支持一个重载参数,格式字符串:trunc(date,‘format’),用于指定截断的位置。如下:
//截断到年
SQL> select trunc(sysdate,'yyyy') from dual;
TRUNC(SYSDATE,'YYYY')
---------------------
2010-1-1
//截断到月
SQL> select trunc(sysdate,'mm') from dual;
TRUNC(SYSDATE,'MM')
-------------------
2010-12-1
//截断到日
SQL> select trunc(sysdate,'dd') from dual;
TRUNC(SYSDATE,'DD')
-------------------
2010-12-10
//截断到小时
SQL> select trunc(sysdate,'hh24') from dual;
TRUNC(SYSDATE,'HH24')
---------------------
2010-12-10 20:00:00
//截断到分钟
SQL> select trunc(sysdate,'mi') from dual;
TRUNC(SYSDATE,'MI')
-------------------
2010-12-10 20:52:00
使用不同的格式标志,可以指示不同的截断位置,获取各种零刻时间。
|
格式字符串 |
说明 |
年 |
yyyy或者year |
年度第一天(一月一日零时) |
月 |
mm或者month |
月份第一天(一日零时) |
日 |
dd或者day |
日期零时(00:00:00) |
小时 |
hh或者hh24 |
几时整(XX:00:00) |
分 |
mi |
几分整(XX:XX:00) |
借助trunc函数和日期类型加减处理,我们可以实现一些特殊日期的设置,实现日期功能,使用在例如Job调度方面。
//明天零点
SQL> select to_char(trunc(sysdate)+1,'yyyy-mm-dd hh24:mi:ss') from dual;
TO_CHAR(TRUNC(SYSDATE)+1,'YYYY
------------------------------
2010-12-11 00:00:00
//当天早上十点
SQL> select to_char(trunc(sysdate)+10/24,'yyyy-mm-dd hh24:mi:ss') from dual;
TO_CHAR(TRUNC(SYSDATE)+10/24,'
------------------------------
2010-12-10 10:00:00
//当月三号,上午10点半
SQL> select to_char(trunc(sysdate,'mm')+2+10/24+1/48, 'yyyy-mm-dd hh24:mi:ss') from dual;
注:trunc(sysdate,'mm')将时间取到当前月的1号零时零分零秒,那么加上2就表示当前月的3好零时零分零秒,再加上'10/24'('10/24'本身表示10个小时)就是表示当月3号的十点零分零秒,再加上'1/48'('1/48'本身表示30分钟)就表示当月3号十点三十分零秒
TO_CHAR(TRUNC(SYSDATE,'MM')+2+
------------------------------
2010-12-03 10:30:00
较复杂的to_char,trunc更加可以发挥日期类型数值本身的特色和优势,无论是代码整洁度还是处理效率都是值得关注的。
额外多说一句,trunc本身还具有处理数字截断功能,用于截断指定位数的数字类型。
//默认截断到整数,不进行四舍五入;
SQL> select trunc(15.743) from dual;
TRUNC(15.743)
-------------
15
//截断到小数点后一位;
SQL> select trunc(15.793,1) from dual;
TRUNC(15.793,1)
---------------
15.7
//截断到小数点前一位;
SQL> select trunc(15.793,-1) from dual;
TRUNC(15.793,-1)
----------------
10
trunc对数字和日期类型处理,也折射出日期类型数据和数字之间的间接关系。
原文地址:http://space.itpub.net/17203031/viewspace-681548
trunc不仅可以用来处理日期,还可以用来处理数字
TRUNC(i1,i2)截取i1的i2位而不四舍五入,如果i2是正就截取小数点右边第几位,如果是i2是负就是截取小数点左边第几位。
例如:
- select TRUNC(0.10005767,1) from dual;
-
- TRUNC(0.10005767,1) 1 0.1
而如果trunc函数没有指定参i2,那么其作用为取整,且取整的时候不会四舍五入
例如:
- select TRUNC(2.60005767) from dual;
-
TRUNC(2.60005767)
round函数和trunc函数的区别:
ROUND(i1,i2)四舍五入,i1四舍五入,如果i2是正保留小数点后i2位。如果是i2是负数,表示保留小数点前面(左边第几位)
TRUNC(i1,i2)截取i1的i2位而不四舍五入,如果i2是正就截取小数点右边第几位,如果是i2是负就是截取小数点左边第几位。
Quartz2.1与1.X有了部分变化,写下配置过程供同好者参考!
1、下载quartz
http://www.terracotta.org/download/reflector.jsp?b=tcdistributions&i=quartz-2.1.5.tar.gz将slf4j-log4j12-1.6.1.jar
slf4j-api-1.6.1.jar
quartz-all-2.1.5.jar
放入WEB-INF\lib下
2、编写自己的job
3、编写配置文件
quartz.properties:
quartz_job.xml:
web.xml:加入一个servlet,主要quartz.properties文件的位置,我是跟我的quartz_job.xml文件放在一起
4、启动应用服务器,一切ok
5、关于触发器的时间控制说明:
先说干货:quartz_job.xml中的
<trigger>
<cron>
<name>report-trigger</name>
<group>Report_Group</group>
<job-name>ReportControlScheduler</job-name>
<job-group>Report</job-group>
<cron-expression>0 0/3 * * * ?</cron-expression>
</cron>
</trigger>
就是对触发时间的描述,我这里采用的是CronTrigger的方式。下边详细描述了时间的控制。
Trigger是一个抽象类,它有三个子类:SimpleTrigger,CronTrigger和NthIncludedDayTrigger。前两个比较常用。
1。SimpleTrigger:这是一个非常简单的类,我们可以定义作业的触发时间,并选择性的设定重复间隔和重复次数。
2。CronTrigger:这个触发器的功能比较强大,而且非常灵活,但是你需要掌握有关Cron表达式的知识。如果你是一个Unix系统爱好者,你很可能已经具备这种知识,但是如果你不了解Cron表达式,请看下面的Cron详解:
Cron表达式由6或7个由空格分隔的时间字段组成,如表1所示: 表1 Cron表达式时间字段
位置 |
时间域名 |
允许值 |
允许的特殊字符 |
1 |
秒 |
0-59 |
, - * / |
2 |
分钟 |
0-59 |
, - * / |
3 |
小时 |
0-23 |
, - * / |
4 |
日期 |
1-31 |
, - * ? / L W C |
5 |
月份 |
1-12 |
, - * / |
6 |
星期 |
1-7 |
, - * ? / L C # |
7 |
年(可选) |
空值1970-2099 |
, - * / |
Cron表达式的时间字段除允许设置数值外,还可使用一些特殊的字符,提供列表、范围、通配符等功能,细说如下:
●星号(*):可用在所有字段中,表示对应时间域的每一个时刻,例如,*在分钟字段时,表示“每分钟”;
●问号(?):该字符只在日期和星期字段中使用,它通常指定为“无意义的值”,相当于点位符;
●减号(-):表达一个范围,如在小时字段中使用“10-12”,则表示从10到12点,即10,11,12;
●逗号(,):表达一个列表值,如在星期字段中使用“MON,WED,FRI”,则表示星期一,星期三和星期五;
●斜杠(/):x/y表达一个等步长序列,x为起始值,y为增量步长值。如在分钟字段中使用0/15,则表示为0,15,30和45秒,而5/15在分钟字段中表示5,20,35,50,你也可以使用*/y,它等同于0/y;
●L:该字符只在日期和星期字段中使用,代表“Last”的意思,但它在两个字段中意思不同。L在日期字段中,表示这个月份的最后一天,如一月的31号,非闰年二月的28号;如果L用在星期中,则表示星期六,等同于7。但是,如果L出现在星期字段里,而且在前面有一个数值X,则表示“这个月的最后X天”,例如,6L表示该月的最后星期五;
●W:该字符只能出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日。例如15W表示离该月15号最近的工作日,如果该月15号是星期六,则匹配14号星期五;如果15日是星期日,则匹配16号星期一;如果15号是星期二,那结果就是15号星期二。但必须注意关联的匹配日期不能够跨月,如你指定1W,如果1号是星期六,结果匹配的是3号星期一,而非上个月最后的那天。W字符串只能指定单一日期,而不能指定日期范围;
●LW组合:在日期字段可以组合使用LW,它的意思是当月的最后一个工作日;
●井号(#):该字符只能在星期字段中使用,表示当月某个工作日。如6#3表示当月的第三个星期五(6表示星期五,#3表示当前的第三个),而4#5表示当月的第五个星期三,假设当月没有第五个星期三,忽略不触发;
● C:该字符只在日期和星期字段中使用,代表“Calendar”的意思。它的意思是计划所关联的日期,如果日期没有被关联,则相当于日历中所有日期。例如5C在日期字段中就相当于日历5日以后的第一天。1C在星期字段中相当于星期日后的第一天。Cron表达式对特殊字符的大小写不敏感,对代表星期的缩写英文大小写也不敏感。表2下面给出一些完整的Cron表示式的实例:
表2 Cron表示式示例
表示式 |
说明 |
"0 0 12 * * ? " |
每天12点运行 |
"0 15 10 ? * *" |
每天10:15运行 |
"0 15 10 * * ?" |
每天10:15运行 |
"0 15 10 * * ? *" |
每天10:15运行 |
"0 15 10 * * ? 2008" |
在2008年的每天10:15运行 |
"0 * 14 * * ?" |
每天14点到15点之间每分钟运行一次,开始于14:00,结束于14:59。 |
"0 0/5 14 * * ?" |
每天14点到15点每5分钟运行一次,开始于14:00,结束于14:55。 |
"0 0/5 14,18 * * ?" |
每天14点到15点每5分钟运行一次,此外每天18点到19点每5钟也运行一次。 |
"0 0-5 14 * * ?" |
每天14:00点到14:05,每分钟运行一次。 |
"0 10,44 14 ? 3 WED" |
3月每周三的14:10分到14:44,每分钟运行一次。 |
"0 15 10 ? * MON-FRI" |
每周一,二,三,四,五的10:15分运行。 |
"0 15 10 15 * ?" |
每月15日10:15分运行。 |
"0 15 10 L * ?" |
每月最后一天10:15分运行。 |
"0 15 10 ? * 6L" |
每月最后一个星期五10:15分运行。 |
"0 15 10 ? * 6L 2007-2009" |
在2007,2008,2009年每个月的最后一个星期五的10:15分运行。 |
"0 15 10 ? * 6#3" |
每月第三个星期五的10:15分运行。 |
LoginAny 使用笔记
想实现在家办公,当公司有急事的时候,可以在家就处理掉;不必在家里和公司之间copy文件,免去劳苦奔波之苦。于是开始用远程软件。
1. VNN. 免费,主要面向游戏平台。
申请2个用户,互相加为密友,能够2台机器互访,但是只有vnnc302201-winall.zip版本能用(密友功能),且不能升级,一旦升级之后,将没有了密友功能。
用了一段时间,很不错。但不久之后,本地域内3389端口封了。理解,因为远程桌面的3389是个不安全的端口。
其实,把被控机器的Terminal Service 3389端口改掉, 理论上也是可行的,但是还是比较麻烦。
2. Hamachi, 很好用的的软件。推荐,IP局域网穿透。 3389端口还是不能连接,道理同上。
3. 改用LoginAny. 免费版每月只能远程桌面20分钟,文件传输3次。速度超快。 远程桌面是LoginAny开发的,所以不再用3389端口。
自己研究下能否逆向工程下…
———先看文件传输功能———–
打开eXeScope分析资源,首先查看文字:"文件传输已经达到最大使用次数!",String Id: 484
得知Dialog: 1218是提示对话框, Dialog: 1219是文件传输Form.
打开OllyICE,反编译后,
- 搜索4C2(1218), 找提示对话框的代码,自己标注附近的代码,这是一个功能函数。
搜索4C3(1219), 找文件传输Form相关代码。
搜索1E4(484), 找"文件传输已经达到最大使用次数!"的相关代码。
004938D0 /$ 55 push ebp
004938D1 |. 8BEC mov ebp, esp
004938D3 |. 6A FF push -1
004938D5 |. 68 87C25B00 push 005BC287 ; SE 处理程序安装
004938DA |. 64:A1 0000000>mov eax, dword ptr fs:[0]
004938E0 |. 50 push eax
004938E1 |. 64:8925 00000>mov dword ptr fs:[0], esp
004938E8 |. 81EC BC000000 sub esp, 0BC
004938EE |. A1 BCEB6200 mov eax, dword ptr [62EBBC]
004938F3 |. 33C5 xor eax, ebp
004938F5 |. 8945 EC mov dword ptr [ebp-14], eax
004938F8 |. 898D 40FFFFFF mov dword ptr [ebp-C0], ecx
004938FE |. C785 4CFFFFFF>mov dword ptr [ebp-B4], 1
00493908 |. 6A 01 push 1
0049390A |. 8B85 4CFFFFFF mov eax, dword ptr [ebp-B4]
00493910 |. 50 push eax
00493911 |. 8B8D 40FFFFFF mov ecx, dword ptr [ebp-C0]
00493917 |. E8 D4EFFFFF call 004928F0 ; 关键Call !!!!
0049391C |. 85C0 test eax, eax
0049391E |. 75 05 jnz short 00493925
00493920 |. E9 F8000000 jmp 00493A1D
00493925 |> C785 48FFFFFF>mov dword ptr [ebp-B8], 0
0049392F |. 8D4D F0 lea ecx, dword ptr [ebp-10]
00493932 |. FF15 28B95C00 call dword ptr [<&MFC71.#310_ATL::CStringT<char,StrTrai>; MFC71.7C173199
00493938 |. C745 FC 00000>mov dword ptr [ebp-4], 0
0049393F |. 6A 00 push 0
00493941 |. 8D8D 54FFFFFF lea ecx, dword ptr [ebp-AC]
00493947 |. E8 64D30800 call 00520CB0
0049394C |. C645 FC 01 mov byte ptr [ebp-4], 1
00493950 |. 8B8D 4CFFFFFF mov ecx, dword ptr [ebp-B4]
00493956 |. 51 push ecx
00493957 |. 68 DD000000 push 0DD
0049395C |. 8D55 F0 lea edx, dword ptr [ebp-10]
0049395F |. 52 push edx
00493960 |. 8D85 54FFFFFF lea eax, dword ptr [ebp-AC]
00493966 |. 50 push eax
00493967 |. 8D8D 48FFFFFF lea ecx, dword ptr [ebp-B8]
0049396D |. 51 push ecx
0049396E |. 8B8D 40FFFFFF mov ecx, dword ptr [ebp-C0]
00493974 |. E8 A7190000 call 00495320 ; MessageBox ….
00493979 |. 85C0 test eax, eax
0049397B |. 75 21 jnz short 0049399E
0049397D |. C645 FC 00 mov byte ptr [ebp-4], 0
00493981 |. 8D8D 54FFFFFF lea ecx, dword ptr [ebp-AC]
00493987 |. E8 24D40800 call 00520DB0
0049398C |. C745 FC FFFFF>mov dword ptr [ebp-4], -1
00493993 |. 8D4D F0 lea ecx, dword ptr [ebp-10]
00493996 |. FF15 68B95C00 call dword ptr [<&MFC71.#578_ATL::CStringT<char,StrTrai>; MFC71.7C1771B1
0049399C |. EB 7F jmp short 00493A1D
0049399E |> 8B95 48FFFFFF mov edx, dword ptr [ebp-B8]
004939A4 |. 52 push edx
004939A5 |. 68 2CF16200 push 0062F12C
004939AA |. 51 push ecx
004939AB |. 8BCC mov ecx, esp
004939AD |. 89A5 44FFFFFF mov dword ptr [ebp-BC], esp
004939B3 |. 8D45 F0 lea eax, dword ptr [ebp-10]
004939B6 |. 50 push eax
004939B7 |. FF15 38B95C00 call dword ptr [<&MFC71.#297_ATL::CStringT<char,StrTrai>; MFC71.7C14E575
004939BD |. 8985 3CFFFFFF mov dword ptr [ebp-C4], eax
004939C3 |. 8D8D 54FFFFFF lea ecx, dword ptr [ebp-AC]
004939C9 |. 51 push ecx
004939CA |. B9 E4F26200 mov ecx, 0062F2E4
004939CF |. E8 ECDAFCFF call 004614C0 ; 调用打开文件传输Form
004939D4 |. 8985 38FFFFFF mov dword ptr [ebp-C8], eax
004939DA |. 8B95 38FFFFFF mov edx, dword ptr [ebp-C8]
004939E0 |. 8995 50FFFFFF mov dword ptr [ebp-B0], edx
004939E6 |. 6A 05 push 5
004939E8 |. 8B8D 50FFFFFF mov ecx, dword ptr [ebp-B0]
004939EE |. E8 6DCC1100 call <jmp.&MFC71.#6090_CWnd::ShowWindow>
004939F3 |. 8B8D 50FFFFFF mov ecx, dword ptr [ebp-B0]
004939F9 |. E8 12D8FAFF call 00441210
004939FE |. C645 FC 00 mov byte ptr [ebp-4], 0
00493A02 |. 8D8D 54FFFFFF lea ecx, dword ptr [ebp-AC]
00493A08 |. E8 A3D30800 call 00520DB0
00493A0D |. C745 FC FFFFF>mov dword ptr [ebp-4], -1
00493A14 |. 8D4D F0 lea ecx, dword ptr [ebp-10]
00493A17 |. FF15 68B95C00 call dword ptr [<&MFC71.#578_ATL::CStringT<char,StrTrai>; MFC71.7C1771B1
00493A1D |> 8B4D F4 mov ecx, dword ptr [ebp-C]
00493A20 |. 64:890D 00000>mov dword ptr fs:[0], ecx
00493A27 |. 8B4D EC mov ecx, dword ptr [ebp-14]
00493A2A |. 33CD xor ecx, ebp
00493A2C |. E8 5ADE1100 call 005B188B
00493A31 |. 8BE5 mov esp, ebp
00493A33 |. 5D pop ebp
00493A34 \. C3 retn
在0049 3917发现关键Call.
决定修改其后的跳转,
00493920 |. E9 F8000000 jmp 00493A1D 这一行是跳过调用打开文件传输Form的代码。
把它改为:
00493920 |. 90 90909090 Nop 什么也不做
经试验,文件传输功能可以超过3次的使用了。
———远程桌面的功能———-
远程桌面的功能只能连接20分钟。 解决办法还是老一套:
打开eXeScope分析资源,找到对话框:远程桌面,ID=1306.
打开OllyICE,搜索常量1306,很快定位下面代码:
00493670 /$ 55 push ebp
00493671 |. 8BEC mov ebp, esp
00493673 |. 6A FF push -1
00493675 |. 68 69C25B00 push 005BC269 ; SE 处理程序安装
0049367A |. 64:A1 0000000>mov eax, dword ptr fs:[0]
00493680 |. 50 push eax
00493681 |. 64:8925 00000>mov dword ptr fs:[0], esp
00493688 |. 81EC D4000000 sub esp, 0D4
0049368E |. A1 BCEB6200 mov eax, dword ptr [62EBBC]
00493693 |. 33C5 xor eax, ebp
00493695 |. 8945 EC mov dword ptr [ebp-14], eax
00493698 |. 898D 30FFFFFF mov dword ptr [ebp-D0], ecx
0049369E |. C785 50FFFFFF>mov dword ptr [ebp-B0], 0
004936A8 |. 6A 01 push 1
004936AA |. 8B85 50FFFFFF mov eax, dword ptr [ebp-B0]
004936B0 |. 50 push eax
004936B1 |. 8B8D 30FFFFFF mov ecx, dword ptr [ebp-D0]
004936B7 |. E8 34F2FFFF call 004928F0 ; 关键Call–remote desk.
004936BC |. 85C0 test eax, eax
004936BE |. 75 05 jnz short 004936C5
004936C0 |. E9 F0010000 jmp 004938B5
004936C5 |> C785 4CFFFFFF>mov dword ptr [ebp-B4], 0
004936CF |. 6A 00 push 0
004936D1 |. 8D8D 54FFFFFF lea ecx, dword ptr [ebp-AC]
004936D7 |. E8 D4D50800 call 00520CB0
004936DC |. C745 FC 00000>mov dword ptr [ebp-4], 0
004936E3 |. 8D4D F0 lea ecx, dword ptr [ebp-10]
004936E6 |. FF15 28B95C00 call dword ptr [<&MFC71.#310_ATL::CStringT<char,StrTrai>; MFC71.7C173199
004936EC |. C645 FC 01 mov byte ptr [ebp-4], 1
004936F0 |. 8B8D 50FFFFFF mov ecx, dword ptr [ebp-B0]
004936F6 |. 51 push ecx
004936F7 |. 68 19010000 push 119
004936FC |. 8D55 F0 lea edx, dword ptr [ebp-10]
004936FF |. 52 push edx
00493700 |. 8D85 54FFFFFF lea eax, dword ptr [ebp-AC]
00493706 |. 50 push eax
00493707 |. 8D8D 4CFFFFFF lea ecx, dword ptr [ebp-B4]
0049370D |. 51 push ecx
0049370E |. 8B8D 30FFFFFF mov ecx, dword ptr [ebp-D0]
00493714 |. E8 071C0000 call 00495320 ; 消息处理
00493719 |. 85C0 test eax, eax
0049371B |. 75 24 jnz short 00493741
0049371D |. C645 FC 00 mov byte ptr [ebp-4], 0
00493721 |. 8D4D F0 lea ecx, dword ptr [ebp-10]
00493724 |. FF15 68B95C00 call dword ptr [<&MFC71.#578_ATL::CStringT<char,StrTrai>; MFC71.7C1771B1
0049372A |. C745 FC FFFFF>mov dword ptr [ebp-4], -1
00493731 |. 8D8D 54FFFFFF lea ecx, dword ptr [ebp-AC]
00493737 |. E8 74D60800 call 00520DB0 ; 字符处理
0049373C |. E9 74010000 jmp 004938B5
00493741 |> 817D A4 01030>cmp dword ptr [ebp-5C], 90301
00493748 |. 0F83 E8000000 jnb 00493836
0049374E |. 8B95 4CFFFFFF mov edx, dword ptr [ebp-B4]
00493754 |. 52 push edx
00493755 |. 6A 00 push 0
00493757 |. 51 push ecx
00493758 |. 8BCC mov ecx, esp
0049375A |. 89A5 38FFFFFF mov dword ptr [ebp-C8], esp
00493760 |. 8D45 F0 lea eax, dword ptr [ebp-10]
00493763 |. 50 push eax
00493764 |. FF15 38B95C00 call dword ptr [<&MFC71.#297_ATL::CStringT<char,StrTrai>; MFC71.7C14E575
0049376A |. 8985 2CFFFFFF mov dword ptr [ebp-D4], eax
00493770 |. 8D8D 54FFFFFF lea ecx, dword ptr [ebp-AC]
00493776 |. 51 push ecx
00493777 |. B9 E4F26200 mov ecx, 0062F2E4
0049377C |. E8 BFD7FCFF call 00460F40 ; ???? XX new opeator
00493781 |. 8985 28FFFFFF mov dword ptr [ebp-D8], eax
00493787 |. 8B95 28FFFFFF mov edx, dword ptr [ebp-D8]
0049378D |. 8995 48FFFFFF mov dword ptr [ebp-B8], edx
00493793 |. 83BD 48FFFFFF>cmp dword ptr [ebp-B8], 0
0049379A |. 0F85 94000000 jnz 00493834
004937A0 |. 8D8D 40FFFFFF lea ecx, dword ptr [ebp-C0]
004937A6 |. FF15 28B95C00 call dword ptr [<&MFC71.#310_ATL::CStringT<char,StrTrai>; MFC71.7C173199
004937AC |. C645 FC 02 mov byte ptr [ebp-4], 2
004937B0 |. 8D8D 44FFFFFF lea ecx, dword ptr [ebp-BC]
004937B6 |. FF15 28B95C00 call dword ptr [<&MFC71.#310_ATL::CStringT<char,StrTrai>; MFC71.7C173199
004937BC |. C645 FC 03 mov byte ptr [ebp-4], 3
004937C0 |. FF15 90AA5C00 call dword ptr [<&KERNEL32.GetLastError>] ; [GetLastError
004937C6 |. 50 push eax
004937C7 |. 68 42010000 push 142
004937CC |. 8D85 44FFFFFF lea eax, dword ptr [ebp-BC]
004937D2 |. 50 push eax
004937D3 |. FF15 3CB95C00 call dword ptr [<&MFC71.#2321_ATL::CStringT<char,StrTra>; MFC71.7C18B260
004937D9 |. 83C4 0C add esp, 0C
004937DC |. 68 00E00000 push 0E000
004937E1 |. 8D8D 40FFFFFF lea ecx, dword ptr [ebp-C0]
004937E7 |. FF15 2CB95C00 call dword ptr [<&MFC71.#4035_ATL::CStringT<char,StrTra>; MFC71.7C153789
004937ED |. 6A 40 push 40
004937EF |. 8D8D 40FFFFFF lea ecx, dword ptr [ebp-C0]
004937F5 |. FF15 30B95C00 call dword ptr [<&MFC71.#876_ATL::CSimpleStringT<char,1>; MFC71.7C158BCD
004937FB |. 50 push eax
004937FC |. 8D8D 44FFFFFF lea ecx, dword ptr [ebp-BC]
00493802 |. FF15 30B95C00 call dword ptr [<&MFC71.#876_ATL::CSimpleStringT<char,1>; MFC71.7C158BCD
00493808 |. 50 push eax
00493809 |. 8B8D 30FFFFFF mov ecx, dword ptr [ebp-D0]
0049380F |. E8 5ECE1100 call <jmp.&MFC71.#4104_CWnd::MessageBoxA>
00493814 |. C645 FC 02 mov byte ptr [ebp-4], 2
00493818 |. 8D8D 44FFFFFF lea ecx, dword ptr [ebp-BC]
0049381E |. FF15 68B95C00 call dword ptr [<&MFC71.#578_ATL::CStringT<char,StrTrai>; MFC71.7C1771B1
00493824 |. C645 FC 01 mov byte ptr [ebp-4], 1
00493828 |. 8D8D 40FFFFFF lea ecx, dword ptr [ebp-C0]
0049382E |. FF15 68B95C00 call dword ptr [<&MFC71.#578_ATL::CStringT<char,StrTrai>; MFC71.7C1771B1
00493834 |> EB 60 jmp short 00493896 ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00493836 |> 8B8D 4CFFFFFF mov ecx, dword ptr [ebp-B4]
0049383C |. 51 push ecx
0049383D |. 68 2CF16200 push 0062F12C
00493842 |. 51 push ecx
00493843 |. 8BCC mov ecx, esp
00493845 |. 89A5 34FFFFFF mov dword ptr [ebp-CC], esp
0049384B |. 8D55 F0 lea edx, dword ptr [ebp-10]
0049384E |. 52 push edx
0049384F |. FF15 38B95C00 call dword ptr [<&MFC71.#297_ATL::CStringT<char,StrTrai>; MFC71.7C14E575
00493855 |. 8985 24FFFFFF mov dword ptr [ebp-DC], eax
0049385B |. 8D85 54FFFFFF lea eax, dword ptr [ebp-AC]
00493861 |. 50 push eax
00493862 |. B9 E4F26200 mov ecx, 0062F2E4
00493867 |. E8 74D9FCFF call 004611E0 ; 调用1:远程桌面的Form
0049386C |. 8985 20FFFFFF mov dword ptr [ebp-E0], eax
00493872 |. 8B8D 20FFFFFF mov ecx, dword ptr [ebp-E0]
00493878 |. 898D 3CFFFFFF mov dword ptr [ebp-C4], ecx
0049387E |. 6A 05 push 5
00493880 |. 8B8D 3CFFFFFF mov ecx, dword ptr [ebp-C4]
00493886 |. E8 D5CD1100 call <jmp.&MFC71.#6090_CWnd::ShowWindow>
0049388B |. 8B8D 3CFFFFFF mov ecx, dword ptr [ebp-C4]
00493891 |. E8 1A72F9FF call 0042AAB0
00493896 |> C645 FC 00 mov byte ptr [ebp-4], 0
0049389A |. 8D4D F0 lea ecx, dword ptr [ebp-10]
0049389D |. FF15 68B95C00 call dword ptr [<&MFC71.#578_ATL::CStringT<char,StrTrai>; MFC71.7C1771B1
004938A3 |. C745 FC FFFFF>mov dword ptr [ebp-4], -1
004938AA |. 8D8D 54FFFFFF lea ecx, dword ptr [ebp-AC]
004938B0 |. E8 FBD40800 call 00520DB0
004938B5 |> 8B4D F4 mov ecx, dword ptr [ebp-C]
004938B8 |. 64:890D 00000>mov dword ptr fs:[0], ecx
004938BF |. 8B4D EC mov ecx, dword ptr [ebp-14]
004938C2 |. 33CD xor ecx, ebp
004938C4 |. E8 C2DF1100 call 005B188B
004938C9 |. 8BE5 mov esp, ebp
004938CB |. 5D pop ebp
004938CC \. C3 retn
找到关键Call.
004936B7 |. E8 34F2FFFF call 004928F0 ; 关键Call–remote desk.
修改关键call之后的跳转:
004936C0 |. E9 F0010000 jmp 004938B5
修改为什么都不作。免得它影响后面的代码。
用9090909090 填充。
经试验,远程桌面功能可以超过20分钟的使用了。
实际摸索中还是走了不少弯路,总结经验为:在OllyDbg中,看过的弄明白的函数,要自己加上注释。 在看其他相关的代码的时候,极有可能就碰到了自己曾经注释过的代码,这样一下子就全通了。