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被載入到服務器 中?,F有的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所指定的范圍內。由于這個過程是自動調整的,幾乎沒有必要修改這些指令的缺省值??梢圆⑿刑幚淼目蛻舳说淖畲髷盗咳Q于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
ReportControlJob.java package net.risesoft.quartz;
import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException;
public class ReportControlJob implements Job { private static int count = 0; public void execute(JobExecutionContext arg0) throws JobExecutionException { System.out.println("hello,world!"+arg0.getFireInstanceId()+"--"+arg0.getFireTime()+"---"+arg0.getNextFireTime()+"---"+count++); } }
3、編寫配置文件
quartz.properties:
quartz.propertiesv #ReportControlScheduler為你的job類 org.quartz.scheduler.instanceName = ReportControlScheduler org.quartz.scheduler.instanceId = one orgorg.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.threadCount = 1 org.quartz.threadPool.threadPriority = 4 org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin org.quartz.plugin.jobInitializer.fileNames = /config/quartz/quartz_job.xml org.quartz.plugin.jobInitializer.failOnFileNotFound = true org.quartz.scheduler.instanceName = ReportControlScheduler org.quartz.scheduler.instanceId = one orgorg.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.threadCount = 1 org.quartz.threadPool.threadPriority = 4 org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin #xml配置文件存放位置,我放在了src/config/quartz/ 下了,編譯后會放到classes/config/quartzconfig/quartz/ 下 org.quartz.plugin.jobInitializer.fileNames = /config/quartz/quartz_job.xml org.quartz.plugin.jobInitializer.failOnFileNotFound = true quartz_job.xml:
quart_job.xml <?xml version='1.0' encoding='utf-8'?> <job-scheduling-data xmlns=" xmlns:xsi=" xsi:schemaLocation="http://www.quartz-scheduler.org/xml/JobSchedulingData version="1.8"> <schedule> <job> <name>ReportControlScheduler</name> <group>Report</group> <description>報表控制填報鎖</description> <job-class>net.risesoft.quartz.ReportControlJob</job-class> </job> <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> </schedule> </job-scheduling-data> web.xml:加入一個servlet,主要quartz.properties文件的位置,我是跟我的quartz_job.xml文件放在一起
web.xml <servlet> <servlet-name>QuartzInitializer</servlet-name> <servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class> <init-param> <param-name>config-file</param-name> <param-value>/config/quartz/quartz.properties </param-value> </init-param> <init-param> <param-name>shutdown-on-unload</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>start-scheduler-on-load</param-name> <param-value>true</param-value> </init-param> <load-on-startup> 1 </load-on-startup> </servlet>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中,看過的弄明白的函數,要自己加上注釋。 在看其他相關的代碼的時候,極有可能就碰到了自己曾經注釋過的代碼,這樣一下子就全通了。