常用的告警方式大致有:短信、郵件、應(yīng)用程序 (beep提示,圖標(biāo)提示,升窗提示等),可是不能一直坐在電腦前看著應(yīng)用程序,或者用腳本部署監(jiān)控,根本沒(méi)有程序界面,所以通常用短信、郵件兩種方式告警。
一. 告警方式
1. 短信
用程序發(fā)短信的方式一般有這兩種:
(1) 硬件
需要1張SIM卡,1個(gè)SIM卡讀卡設(shè)備 (比如:短信貓),然后把設(shè)備連接到電腦,應(yīng)用程序根據(jù)設(shè)備的軟件接口,傳參并發(fā)送短信。記得把SIM卡設(shè)備放在信號(hào)好,無(wú)干擾的地方;
如果有大量短信要發(fā),1張SIM卡是不夠用的,而且發(fā)送過(guò)度頻繁,可能被運(yùn)營(yíng)商視為惡意短信,把SIM卡號(hào)加入黑名單,那么就需要多張SIM卡甚至多個(gè)讀卡設(shè)備。
顯示號(hào)碼為當(dāng)前SIM卡號(hào)碼,大多供應(yīng)商都支持DLL、HTTP等多種接口,當(dāng)然也可以基于接口二次開(kāi)發(fā)。
DLL接口方法參考:SmsManager.sendTextMessage(…)
(2) 第三方短信接口
有多種接口形式提供,比如:
Web Service形式,HTTP形式,還有郵件接口:往1380013900@xxx.com發(fā)個(gè)短小的郵件,這個(gè)郵件會(huì)以短信的形式轉(zhuǎn)發(fā)到
手機(jī)上,等等。只要往接口傳參數(shù),告訴它發(fā)給誰(shuí),發(fā)什么內(nèi)容,就可以了。
顯示號(hào)碼為某個(gè)SIM卡號(hào)碼,或者為固定號(hào)碼 (如:106開(kāi)頭的),這取決于短信平臺(tái)和運(yùn)營(yíng)商的實(shí)現(xiàn)方式,因?yàn)檫\(yùn)營(yíng)商發(fā)短信是不要卡的,直接可以發(fā)給目標(biāo)號(hào)碼,而且可以顯示為固定的某個(gè)號(hào)碼。
Web Service接口地址參考:http://123.456.789.000/SmsManager.asmx?wsdl
Http接口地址參考:http://api.abc.xyz/sms/send.html
2. 郵件
凡是實(shí)現(xiàn)了SMTP協(xié)議的組件,都可以發(fā)送郵件。
在
Windows環(huán)境下,有系統(tǒng)自帶的組件CDO (Collaboration Data Objects,以前叫OLE Messaging 或者Active Messaging),是MAPI庫(kù)的COM封裝。不管是自己開(kāi)發(fā)程序,使用VBS,還是
SQL Server的SQL Mail/Database Mail,通常都是調(diào)用的這個(gè)組件。
SMTP協(xié)議要求的參數(shù)大致如下:
SMTP Hostname: SMTP服務(wù)器名,如mail.test.com或者IP
SMTP Port: SMTP服務(wù)端口,25
SMTP Username: 通過(guò)SMTP發(fā)送郵件用來(lái)驗(yàn)證的用戶名, 如果不要求身份驗(yàn)證,留空
SMTP Password: 通過(guò)SMTP發(fā)送郵件用來(lái)驗(yàn)證的密碼, 如果不要求身份驗(yàn)證,留空
二. 選擇告警方式并配置
1. 短信
(1) 監(jiān)控工具/應(yīng)用程序中,通常都留有短信接口的配置,配置接口地址即可;
(2) 在腳本中配置,Windows環(huán)境通常要借助OLE Automation;
OLE Automation后來(lái)改名叫Automation,是Windows上基于COM,用于腳本語(yǔ)言實(shí)現(xiàn)進(jìn)程間通訊的機(jī)制,腳本如:VBS, SQL, Powershell,不包括BAT(BAT可以調(diào)用VBS)。
SQL Server中使用OLE Automation調(diào)用Web Service短信接口如下:
exec sp_configure 'show advanced options', 1; RECONFIGURE; exec sp_configure 'Ole Automation Procedures', 1; RECONFIGURE; declare @text_message nvarchar(180) ,@phone_number nvarchar(15) ,@soap_object int ,@status int ,@output nvarchar(255) set @text_message = N'Testing Mail' set @phone_number = N'138000139000' --Create MSSOAP.SoapClient object exec @status=sp_OACreate 'MSSOAP.SoapClient', @soap_object out --SmsManager is Web Service name exec @status = sp_OAMethod @object, 'mssoapinit', null, 'http://123.456.789.000/SmsManager.asmx?wsdl', 'SmsManager' --SendTextMessage is webservice method exec @status = sp_OAMethod @object, 'SendTextMessage', @output OUT, @phone_number, @text_message if @status <> 0 begin exec sp_OAGetErrorInfo @soap_object select @soap_object end else begin select @output end --Destroy MSSOAP.SoapClient object exec @status = sp_OADestroy @soap_object GO |
對(duì)于HTTP, DLL接口,和SOAP接口類(lèi)似,用OLE Automation也都可以調(diào)用,主要區(qū)別就是在CreateObject() 時(shí)。
以VBS為例,調(diào)用HTTP, DLL時(shí)CreateObject()如下:
Dim http
Set http = CreateObject("Msxml2.XMLHTTP")
Dim dll
Set dll = CreateObject("工程名.類(lèi)名")
2. 郵件
(1) 監(jiān)控工具/應(yīng)用程序中,通常都留有SMTP配置項(xiàng),配置SMTP參數(shù)即可;
(2) 在腳本中配置,Windows環(huán)境通常要借助OLE Automation;
VBS發(fā)送郵件如下:
Dim ns ns = "http://schemas.microsoft.com/cdo/configuration/" Dim title, content title = "db_maint_alert" content = "" content = content&"Hi All," content = content&chr(13)&chr(10) content = content&" " content = content&chr(13)&chr(10) content = content&"----test mail----" Msgbox('~1~') Set cm = CreateObject("CDO.Message") cm.from = "from_user_name@abc.com" cm.to = "to_user_name@abc.com" cm.cc = "cc_user_name@abc.com" cm.subject = title cm.textbody = content 'cm.AddAttachment "" Msgbox('~2~') 'sendusing: 1 = pickup, 2 = port 'smtpauthenticate: 0 = anonymous,1 = common,2 = NTLM 'smtpusessl: 0 = no,1 = yes With cm.configuration.fields .item(ns & "sendusing") = 2 .item(ns & "smtpserver") = "xxx.xxx.xxx.xxx" .item(ns & "smtpserverport") = 25 .item(ns & "smtpauthenticate") = 1 .item(ns & "sendusername") = "user_name@abc.com" .item(ns & "sendpassword") = "*****************" .item(ns & "smtpconnectiontimeout") = 10 .item(ns & "smtpusessl") = 0 .update End With Msgbox('~3~') cm.send Set cm = nothing Msgbox('~success~') |
SQL Server 2000發(fā)送郵件如下:
SQL Server 2000有SQL Mail,不過(guò)必須要同服務(wù)器上安裝一個(gè)實(shí)現(xiàn)了MAPI的郵件程序,如:OUTLOOK,因?yàn)镾QL Mail需要借用郵件應(yīng)用程序的MAPI來(lái)發(fā)送郵件,配置起來(lái)不太方便,所以使用類(lèi)似上面VBS的OLE Automation方法。
use master; if OBJECT_ID('sp_SendDatabaseMail') is not null drop proc sp_SendDatabaseMail go CREATE PROCEDURE sp_SendDatabaseMail @recipients varchar(8000), --'001@abc.com; 002@abc.com;' @Subject varchar(400) = '', @HtmlBody varchar(8000) = '' as Declare @From varchar(100) Declare @To varchar(100) Declare @Bcc varchar(500) Declare @AddAttachment varchar(100) Declare @object int Declare @hr int Declare @source varchar(255) Declare @description varchar(500) Declare @output varchar(1000) set @From = 'SqlAlert@abc.com' set @To = @recipients set @Bcc = '' set @AddAttachment = '' --set @HtmlBody= '<body><h1><font color=Red>' +@HtmlBody+'</font></h1></body>' EXEC @hr = sp_OACreate 'CDO.Message', @object OUT EXEC @hr = sp_OASetProperty @object, 'Configuration.fields("http://schemas.microsoft.com/cdo/configuration/sendusing").Value','2' EXEC @hr = sp_OASetProperty @object, 'Configuration.fields("http://schemas.microsoft.com/cdo/configuration/smtpserver").Value', 'xxx.xxx.xxx.xxx' EXEC @hr = sp_OASetProperty @object, 'Configuration.fields("http://schemas.microsoft.com/cdo/configuration/smtpserverport").Value','25' EXEC @hr = sp_OASetProperty @object, 'Configuration.fields("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate").Value','1' EXEC @hr = sp_OASetProperty @object, 'Configuration.fields("http://schemas.microsoft.com/cdo/configuration/sendusername").Value','user_name@abc.com' EXEC @hr = sp_OASetProperty @object, 'Configuration.fields("http://schemas.microsoft.com/cdo/configuration/sendpassword").Value','*****************' EXEC @hr = sp_OAMethod @object, 'Configuration.Fields.Update', null EXEC @hr = sp_OASetProperty @object, 'To', @To EXEC @hr = sp_OASetProperty @object, 'Bcc', @Bcc EXEC @hr = sp_OASetProperty @object, 'From', @From EXEC @hr = sp_OASetProperty @object, 'Subject', @Subject EXEC @hr = sp_OASetProperty @object, 'HtmlBody', @HtmlBody --add attachment if @AddAttachment<>'' EXEC @hr = sp_OAMethod @object, 'AddAttachment',NULL,@AddAttachment IF @hr <>0 select @hr BEGIN EXEC @hr = sp_OAGetErrorInfo NULL, @source OUT, @description OUT IF @hr = 0 BEGIN SELECT @output = ' Source: ' + @source PRINT @output SELECT @output = ' Description: ' + @description PRINT @output END ELSE BEGIN PRINT ' sp_OAGetErrorInfo failed.' RETURN END END --send mail EXEC @hr = sp_OAMethod @object, 'Send', NULL IF @hr <>0 select @hr BEGIN EXEC @hr = sp_OAGetErrorInfo NULL, @source OUT, @description OUT IF @hr = 0 BEGIN SELECT @output = ' Source: ' + @source PRINT @output SELECT @output = ' Description: ' + @description PRINT @output END ELSE BEGIN PRINT ' sp_OAGetErrorInfo failed.' RETURN END end PRINT 'Send Success!!!' --destroy object EXEC @hr = sp_OADestroy @object |
調(diào)用上面這個(gè)SP來(lái)發(fā)郵件:
EXEC sp_SendDatabaseMail
@recipients = '001@test.com; 002@test.com;',
@body = 'This is a testing mail',
@HtmlBody = 'Testing Database Mail'
SQL Server 2005起,使用Database Mail,腳本如下:
--1. 啟用database mail
use master
GO
exec sp_configure 'show advanced options',1
reconfigure
exec sp_configure 'Database mail XPs',1
reconfigure
GO
--2. 添加account
exec msdb..sysmail_add_account_sp
@account_name = 'SqlAlert' -- mail account
,@email_address = 'SqlAlert@test.com' -- sendmail address
,@display_name = 'SqlAlert' -- sendusername
,@replyto_address = null
,@description = null
,@mailserver_name = '***,***,***,***' -- SMTP Address
,@mailserver_type = 'SMTP' -- SQL 2005 only support SMTP
,@port = 25 -- port
--,@username = '*********@test.com' -- account
--,@password = '******************' -- pwd
,@use_default_credentials = 0
,@enable_ssl = 0 --is ssl enabled on SMTP server
,@account_id = null
--3. 添加profile
exec msdb..sysmail_add_profile_sp
@profile_name = 'SqlAlert' -- profile name
,@description = 'dba mail profile' -- profile description
,@profile_id = null
--4. 關(guān)聯(lián)account and profile
exec msdb..sysmail_add_profileaccount_sp
@profile_name = 'SqlAlert' -- profile name
,@account_name = 'SqlAlert' -- account name
,@sequence_number = 1 -- account order in profile
--5. 發(fā)送database mail
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'SqlAlert',
@recipients = '001@test.com; 002@test.com;',
@body = 'This is a testing mail',
@subject = 'Testing Database Mail';
GO
注意:SMTP服務(wù)器的配置,比如:是否使用smtp用戶驗(yàn)證,SSL是否開(kāi)啟,必須要和服務(wù)端一致,否則無(wú)法發(fā)送郵件。
其他
(1) 告警的次數(shù):被告警的問(wèn)題也許正在處理中,告警還在反復(fù)頻繁發(fā)送,尤其用腳本輪詢時(shí),注意設(shè)置次數(shù)和發(fā)送間隔;
(2) 告警的歷史記錄:短信或者郵件告警,最好都在數(shù)據(jù)庫(kù)中留一份記錄;
(3) 字符編碼:如果應(yīng)用程序/接口不支持中文,可以把中文轉(zhuǎn)成UTF-8的字符編碼發(fā)送,然后再解析回來(lái)。
目錄
在ACM/ICPC中使用Java需要注意的問(wèn)題
Java與高精度計(jì)算
1.Java在ACM/ICPC中的特點(diǎn)
Java的語(yǔ)法和C++幾乎相同
Java在執(zhí)行計(jì)算密集任務(wù)的時(shí)候并不比C/C++慢多少,只是IO操作較慢而已
Java 簡(jiǎn)單而功能強(qiáng)大,有些東西用Java實(shí)現(xiàn)起來(lái)更為方便
比如:輸入輸出、字符串解析、高精度
Java不易犯細(xì)微的錯(cuò)誤
C/C++中的指針
“if (n = m) ... ”
Java與Eclipse
2.在ACM/ICPC中使用Java需要注意的問(wèn)題
java程序結(jié)構(gòu)
Java I/O
JDK1.5.0新增的Scanner類(lèi)很適合用于AMC/ICPC的輸入
使用Scanner類(lèi)的一般步驟
1.導(dǎo)入Scanner類(lèi)
import java.util.Scanner;
2.創(chuàng)建Scanner類(lèi)的對(duì)象
Scanner cin=new Scanner(System.in); //從標(biāo)準(zhǔn)輸入讀入數(shù)據(jù)
Scanner cin=new Scanner(“12 30”)); //從字符串讀入數(shù)據(jù)
3.使用Scanner類(lèi)的對(duì)象讀入各種類(lèi)型的數(shù)據(jù)
cin.nextInt()
cin.nextDouble();
…
Scanner類(lèi)的常用方法
1.讀入數(shù)據(jù)
2.判斷是否還有數(shù)據(jù)
cin.hasNext() 或 cin.hasNextInt() 或 cin.hasNextDouble()
Scanner類(lèi)的用方法示例:
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
char ch=(char)sc.nextInt();
System.out.print(ch);
}
}
}
標(biāo)準(zhǔn)輸出
System.out.print(…); //不輸出換行 System.out.println(…); //輸出換行 import java.io.*; public class Main{ static PrintStream cout=System.out; public static void main(String[] args){ int n=3,m=5; cout.println(n); // 輸出3 //同一行輸出多個(gè)整數(shù)可以用 cout.println(n+" "+m); } } |
用DecimalFormat類(lèi)控制浮點(diǎn)數(shù)小數(shù)位數(shù)
import java.text.DecimalFormat;
控制方法
構(gòu)造特定的DecimalFormat對(duì)象:DecimalFormat f=new DecimalFormat(“#.00#”);
構(gòu)造函數(shù)中的參數(shù)是模式字符串,0指一位數(shù)字,#指除0以外的數(shù)字
使用DecimaFormat對(duì)象格式化需要輸出的浮點(diǎn)數(shù):System.out.println(f.format(12.1234));
DecimalFormat示例
import java.text.*; public class decimalformat{ public static void main(String[] args){ DecimalFormat f = new DecimalFormat("#.00#"); DecimalFormat g = new DecimalFormat("0.000"); double a = 123.4509, b = 0.12; System.out.println(f.format(a)); System.out.println(g.format(a)); System.out.println(f.format(b)); System.out.println(g.format(b)); } } |
運(yùn)行結(jié)果:
123.451
123.451
.12
0.120
格式化輸出的另一種方法是利用System.out.printf(“格式字符串”,…),其用法和c的printf基本一致
int a=10;
float b=2.35f;
System.out.printf("%d %10.5f\n", a, b);
字符串(String)
String類(lèi)常用方法:
構(gòu)造字符串:
String s=“abcde”;
char[] chs={‘a’,’b’,’c’,’d’,’e’};
String s=new String(chs);
取得字符串中某個(gè)字符:
char ch=s.charAt(1); //ch=‘b’;
求子串:
System.out.println(s.substring(0, 3)) // output “abc"
System.out.println(s.substring(1, 3)) // output “bc"
System.out.println(s.substring(1)) // output “bcde"
拆分字符串:
String s=“123:34:55”;
String[] ss = s.split(“:”);
for(int i=0;i<ss.length;i++) System.out.println(ss[i]);
運(yùn)行結(jié)果:
123
34
55
替換字符串:
String s=“2009-07-26”;
System.out.println( s.replace(‘-’,’//’) ); //輸出2009/07/26
String s=“0.123456”;
System.out.println( s.replaceAll(“^0”,””) ); //輸出.123456
String中的字符不能改變,如果需要改變可以使用StringBuffer
其他注意的事項(xiàng)
Java數(shù)組是對(duì)象,定義后必須初始化,如 int[] a = new int[100]; 數(shù)組長(zhǎng)度由length成員得到,如System.out.println(a.length);
Arrays類(lèi)提供的一些有用方法:
Arrays.fill()
Arrays.sort()
Arrays.binarySearch()
布爾類(lèi)型為 boolean,只有true和false二值,在 if (...) / while (...) 等語(yǔ)句的條件中必須為boolean類(lèi) 型。
在C/C++中的 if (n % 2) ... 在Java中無(wú)法編譯通過(guò)。
Java也提供了類(lèi)似STL的集合類(lèi):
Vector,ArrayList,Map,Queue,Stack,Hashtable
3.Java與高精度計(jì)算
PKU1001-exponentiation(求冪):
Sample Input 95.123 12 0.4321 20 5.1234 15 6.7592 9 98.999 10 1.0100 12 Sample Output 548815620517731830194541.899025343415715973535967221869852721 . 00000005148554641076956121994511276767154838481760200726351203835 429763013462401 43992025569.928573701266488041146654993318703707511666295476720493 953024 29448126.764121021618164430206909037173276672 90429072743629540498.107596019456651774561044010001 1.126825030131969720661201 |
用C/C++解決的方法
C/C++的pow函數(shù)無(wú)法達(dá)到需要的精度
C/C++用數(shù)組來(lái)模擬乘法運(yùn)算提高精度
java代碼:
import java.math.*; import java.util.*; public class Main{ public static void main(String[] args){ Scanner in=new Scanner(System.in); while(in.hasNext()){ BigDecimal val=in.nextBigDecimal(); int n=in.nextInt(); BigDecimal ret=val.pow(n).stripTrailingZeros(); System.out.println( ret.toPlainString().replaceAll("^0", "") ); } } } |
BigDecimal類(lèi)
高精度的有符號(hào)十進(jìn)制數(shù)字
構(gòu)造一個(gè)高精度數(shù)字
BigDecimal (int val) BigDecimal (double val) BigDecimal (String val) BigDecimal d1=new BigDecimal(1); BigDecimal d2=new BigDecimal(0.1); BigDecimal d3=new BigDecimal("0.1"); System.out.println("d1="+d1); System.out.println("d2="+d2); System.out.println("d3="+d3); BigDecimal類(lèi)常用方法: BigDecimal add(BigDecimal augend) // “+” BigDecimal subtract(BigDecimal subtrahend) // “-” BigDecimal multiply(BigDecimal multiplicand) // “*” BigDecimal divide(BigDecimal divisor) // “/” BigDecimal remainder(BigDecimal divisor) // “%” BigDecimal pow(int n) //“求冪” String toPlainString() //返回不帶指數(shù)的字符串表示 String toString() //返回帶指數(shù)的字符串表示 |
PKU高精度計(jì)算題目:
1131、1205、1220、1405、1503、1604 1894、2084、2305、2325、2389、2413 3101、3199
咱們碼農(nóng)其實(shí)是很單純的,說(shuō)白了搬磚怎么搬不是搬啊對(duì)不對(duì)?所以老板讓咋搬咱們就怎么搬,大部分人也沒(méi)搞明白這些玩意兒背后到底是個(gè)什么思路。
但是兄弟我和其他碼農(nóng)不一樣,我是個(gè)愛(ài)思考的人。所以在搬磚之余,我就會(huì)去找一些書(shū)來(lái)看,比如經(jīng)濟(jì)學(xué)、心理學(xué)、業(yè)務(wù)流程管理、銷(xiāo)售管理之類(lèi)的,一來(lái)可以漲漲姿勢(shì),二來(lái)也嘗試站在老板的角度來(lái)觀察一下咱們搬磚的情況。
一開(kāi)始吧,我也看不出啥門(mén)道。各種方法論看上去都挺客觀的,據(jù)說(shuō)有的可以準(zhǔn)確控制搬磚的進(jìn)度,有的能統(tǒng)一磚塊的質(zhì)量,還有的能讓咱們搬磚的時(shí)候既高效又開(kāi)心。
這樣問(wèn)題就來(lái)了,搬磚技術(shù)到底哪家強(qiáng)呢?
哥思考了很久,后來(lái)站在老板的角度終于想明白了:之所以有各種不同的方法論,是因?yàn)閷?duì)于軟件開(kāi)發(fā)有不同的假設(shè)前提(assumption — 順帶說(shuō)一句,這個(gè)單詞厲害了,做過(guò)科研的同學(xué)們都知道,所有的科學(xué)理論都是基于一套assumption的。一般的科學(xué)家對(duì)前人的成果修修補(bǔ)補(bǔ),牛叉的科學(xué)家發(fā)現(xiàn)新的方法和領(lǐng)域,而傳奇的科學(xué)家都是推翻前人的assumption,直接顛覆或創(chuàng)立一整套理論。啊,跑題了…)。不同的假設(shè)前提意思是說(shuō),在老板眼里碼農(nóng)是個(gè)啥角色?不同角色對(duì)應(yīng)的就是不同的管理思路,就會(huì)導(dǎo)致不同的管理方法論。
歷史的輪回總是驚人的相似。其實(shí)軟件開(kāi)發(fā)是一個(gè)行業(yè),也難免經(jīng)歷其他行業(yè)的發(fā)展歷程。我們先來(lái)看看工業(yè)界:工業(yè)革命之前,日用品都是手
工作坊生產(chǎn)出來(lái)的,工匠的手藝差別很大,這種差別就體現(xiàn)在產(chǎn)品和工匠的收入上,比如普通鞋匠花五天做一雙鞋賣(mài)給村民,一個(gè)月能掙3個(gè)銀幣,而頂級(jí)鞋匠花三個(gè)月給貴族訂制一雙鞋,掙30個(gè)金幣。那個(gè)時(shí)候,衡量工匠工作效率的核心指標(biāo)不是工作時(shí)間,而是手藝。
這個(gè)階段如果有管理方法的話,主要也是針對(duì)學(xué)徒的。學(xué)徒一直跟著師傅
學(xué)習(xí),直到手藝也達(dá)到師傅的標(biāo)準(zhǔn),可以獨(dú)當(dāng)一面。這時(shí)候的管理方法,主要是讓學(xué)徒盡可能掌握師傅的手藝,提高技術(shù)水平。
后來(lái)工業(yè)革命了,有聰明人做出了蒸汽機(jī)以及各種自動(dòng)機(jī)器,實(shí)現(xiàn)了流水線生產(chǎn),根據(jù)某些頂級(jí)工藝師設(shè)計(jì)好的模具進(jìn)行自動(dòng)化生產(chǎn),流水線上的工人只是負(fù)責(zé)某個(gè)環(huán)節(jié)的裝配和質(zhì)檢等簡(jiǎn)單工作,就不需要有太高的手藝了,只要具備基本知識(shí),經(jīng)過(guò)流水線操作培訓(xùn)就可以上崗。這時(shí)候,衡量工人工作效率的核心指標(biāo)就不是手藝,而是工作時(shí)間。
這是為什么呢?因?yàn)椋魉€的生產(chǎn)速度是固定的,質(zhì)量也是標(biāo)準(zhǔn)的,所以一個(gè)工人每天能做出多少產(chǎn)品和他站在流水線旁的時(shí)間長(zhǎng)短成正比。所以這個(gè)階段的管理方法也不再看重工人提高手藝,而是關(guān)注出勤情況,所以相應(yīng)的考勤打卡、病事假管理等等制度就一步步完善起來(lái)。
其實(shí)說(shuō)白了,現(xiàn)在的軟件開(kāi)發(fā)行業(yè)就正在經(jīng)歷從作坊到工廠的轉(zhuǎn)變,有些公司轉(zhuǎn)變得比較快,有的轉(zhuǎn)變得慢一些。越來(lái)越多的開(kāi)發(fā)框架、開(kāi)發(fā)工具、庫(kù)、模板就構(gòu)成了很多的自動(dòng)化流水線,讓程序員這個(gè)職業(yè)的門(mén)檻越來(lái)越低。作為軟件工程師,在老板的眼里,也有偏工人和偏工匠的不同,所以就會(huì)有不同的管理方法出來(lái)。
再說(shuō)到管理方法論和相應(yīng)的假設(shè)前提,比如CMM是什么?就是軟件行業(yè)的富士康管理方法。在實(shí)施CMM的公司老板眼里,他關(guān)注的其實(shí)是開(kāi)發(fā)的流程。只要流程執(zhí)行好了,每個(gè)碼農(nóng)都是無(wú)差別的,就像流水線上的一個(gè)個(gè)工人一樣,今天走一個(gè),明天就能招來(lái)一個(gè),要求也不高,基本上會(huì)寫(xiě)if…else…就行了,對(duì)整體工作完全沒(méi)有影響。考核員工的標(biāo)準(zhǔn)也比較容易量化,比如代碼行數(shù)、出勤時(shí)間之類(lèi)。
敏捷開(kāi)發(fā)呢?老板對(duì)工程師創(chuàng)造力的期望要高很多,希望每個(gè)團(tuán)隊(duì)成員能獨(dú)當(dāng)一面,這種模式下的工程師更像一個(gè)工匠,做事的自由度也會(huì)大一些。這種管理方式下,績(jī)效考核的復(fù)雜度就要大一些了,不能簡(jiǎn)單地看寫(xiě)了多少代碼,可能是看功能點(diǎn)數(shù),或者結(jié)合其他成員的主觀評(píng)價(jià)。當(dāng)然,這種方式下對(duì)工程師水平的要求也會(huì)比較高,作坊里總不能隨便找個(gè)人就開(kāi)始干活吧?
其他種種管理方法,其實(shí)都可以從這個(gè)角度去分析。不一定要看到它的開(kāi)發(fā)方法論,從公司的外部表現(xiàn)就能大概齊看出來(lái)了。比如一家公司說(shuō)福利好管三餐,上班要打卡甚至是996模式,辦公室里還免費(fèi)提供睡袋,薪水也不高,那么你基本就是去做工人的。反之,如果某公司不用打卡不記考勤,只管午飯但很好吃,沒(méi)有老板天天盯著你寫(xiě)了多少代碼,身邊都是高手,而且薪水又很高……呃,國(guó)內(nèi)真有這樣的公司?假如有,那其他的就不用管了,趕緊去吧。
大部分公司其實(shí)都是介乎兩個(gè)極端之間的,你可以具體分析,是離工人近一點(diǎn)呢,還是離工匠近一點(diǎn)。
為啥要從這個(gè)角度去看呢?因?yàn)閷?duì)自己的成長(zhǎng)影響是不一樣的,工人講究的是熟練,工作中鉆研的方向也不是大的技術(shù)創(chuàng)新(老板不需要你鉆研這個(gè),而且你也沒(méi)有時(shí)間沒(méi)有條件去鉆研工作中用不到的東西),而是如何優(yōu)化模板等特別細(xì)節(jié)上的改進(jìn),一旦失去這個(gè)工作,你的經(jīng)驗(yàn)可能在別的地方用處不大。工廠適合踏實(shí)、肯吃苦、執(zhí)行力強(qiáng)、能干臟活累活的人,在這種人員流動(dòng)大的地方能堅(jiān)持下來(lái),其實(shí)也會(huì)有很好的職業(yè)發(fā)展機(jī)會(huì)。
如果你是那種喜歡新鮮感、愛(ài)鉆研新技術(shù)、對(duì)于重復(fù)性的勞動(dòng)興趣不大的人,最好還是盡量去那種強(qiáng)調(diào)巧干勝過(guò)苦干的地方。一般那里高人比較多,學(xué)習(xí)的條件好,提升空間比較大,但是前提是你要聰明、勤快、自學(xué)能力強(qiáng)。在這種地方呆上幾年,就能積累很多東西。
不過(guò)現(xiàn)在行業(yè)里也有讓人看不懂的公司,沒(méi)辦法用這個(gè)套路分析,或者說(shuō),它們是一種奇怪的混合變異體。比如有的
互聯(lián)網(wǎng)公司強(qiáng)調(diào)以人為本,取消了一線管理職位,實(shí)行扁平化的管理,又實(shí)行996嚴(yán)格考勤制度下的敏捷開(kāi)發(fā),對(duì)程序員主要考核代碼量和bug數(shù)等等……
這種思路大概是想把高水平的工匠們集中到工廠里進(jìn)行流水線化的管理,類(lèi)似中西醫(yī)結(jié)合,先拍片子再抓方子。老碼農(nóng)在此無(wú)奈地表示,這種變異體的管理方式太有創(chuàng)意,無(wú)法評(píng)價(jià),我只能承認(rèn)搬磚技術(shù)最強(qiáng)的就是他們家了。
誤打誤撞進(jìn)入
配置管理這個(gè)行業(yè)約2年,還是有很多東西不清楚。網(wǎng)上倒是有很多軟件類(lèi)配置管理的知識(shí)可以獲取、
學(xué)習(xí)。但總覺(jué)得使不上勁,好像有一層云霧籠罩著,摸不清方向。曾經(jīng)一度想加入
測(cè)試或研發(fā)團(tuán)隊(duì),通過(guò)了解研發(fā)流程,以便提出合適的配置流程和方案。無(wú)奈還是隔靴搔癢地在綜合辦里坐著,只能通過(guò)和研發(fā)人員溝通、看博客混論壇來(lái)了解這個(gè)領(lǐng)域的狀態(tài)。
今天又仔細(xì)看了構(gòu)建管理的相關(guān)定義,突然有了一些豁然開(kāi)朗的感覺(jué)。寫(xiě)出來(lái)和各位同仁探討,不足之處,還望不吝賜教。
配置管理是縮寫(xiě)是CM (Configuration Management),而業(yè)界很多人卻稱自己是SCM(Software Configuration Mangement, 軟件配置管理)。但是卻沒(méi)有與之相對(duì)應(yīng)的HCM (Hardware Configauration Management)。如果在
谷歌或
百度搜索配置管理,順藤摸瓜會(huì)發(fā)現(xiàn)與之關(guān)聯(lián)密切的一些術(shù)語(yǔ),比如:構(gòu)建,編譯,打包,發(fā)布,部署等等。
軟件配置管理的體系和工具都已經(jīng)很成熟(但這不表示我們這個(gè)國(guó)家的多數(shù)軟件公司已經(jīng)在用它們),而硬件方面的就較少。而這套成熟的軟件系統(tǒng)又顯然不太適用于芯片類(lèi)和系統(tǒng)類(lèi)的產(chǎn)品。
造成這種配置管理軟件強(qiáng)而硬件弱的現(xiàn)象,筆者考慮主要是下面的原因:
1)配置管理對(duì)工具的要求較高。由于軟件行業(yè)在這方面有著天然的優(yōu)勢(shì),對(duì)應(yīng)的解決方案就比較多(實(shí)現(xiàn)相對(duì)容易)。例如
IBM和MS就不乏這樣針對(duì)軟件研發(fā)過(guò)程的產(chǎn)品。
2)軟件公司的開(kāi)發(fā)模型大致相近(或分為幾類(lèi))。這類(lèi)產(chǎn)品將標(biāo)準(zhǔn)的軟件研發(fā)過(guò)程包含在內(nèi),很快在其它軟件公司中得到應(yīng)用和推廣。
而芯片類(lèi)和系統(tǒng)類(lèi)的工程師在開(kāi)發(fā)類(lèi)似定制軟件的技術(shù)實(shí)力和動(dòng)力方面都不足(不會(huì)像軟件公司那樣做好了還可以作為產(chǎn)品銷(xiāo)售)。因此,芯片行業(yè)缺少通用的配置流程和可選工具就不奇怪了。
目前,我們能做的就是按照公司的研發(fā)流程和cmmi等標(biāo)準(zhǔn)的要求,參考當(dāng)前軟件配置管理的優(yōu)秀實(shí)踐,定制地開(kāi)發(fā)復(fù)合公司需求的配置管理方案。解決代碼管理,編譯,測(cè)試,發(fā)布等問(wèn)題。
芯片產(chǎn)品包括:芯片設(shè)計(jì)(最終形成芯片的硬件部分)和固件設(shè)計(jì)(boot、cos、驅(qū)動(dòng)、下載工具等)。
對(duì)于芯片硬件的設(shè)計(jì),其研發(fā)流程很長(zhǎng)。與軟件類(lèi)的差別就比較大了,比如加入了仿真、模擬、版圖等環(huán)節(jié)。
對(duì)于芯片固件的設(shè)計(jì),可以參考普通軟件類(lèi)產(chǎn)品的配置管理流程。
當(dāng)然,雖然可以借鑒現(xiàn)成的流程,但工具卻不一定能套用。因?yàn)樾酒碳捎玫氖乔度胧介_(kāi)發(fā)(例如用C語(yǔ)言編寫(xiě))。
軟件配置管理的思路有很多值得借鑒之處——比如,構(gòu)建自動(dòng)化、測(cè)試自動(dòng)化、自動(dòng)打包、自動(dòng)編譯。這些工具或環(huán)境,其實(shí)就是將研發(fā)流程中可以讓機(jī)器做(而且可能比人做更高效、準(zhǔn)確)的部分單獨(dú)拿出來(lái),盡可能地讓機(jī)器(編譯服務(wù)器、構(gòu)建服務(wù)器)實(shí)現(xiàn)。 包括版本控制、質(zhì)量控制(自動(dòng)測(cè)試)、編譯。
當(dāng)然,以上的分析也只是為芯片類(lèi)的配置管理找到了一個(gè)可能的方向,剩下就是進(jìn)一步的確定需求、制定解決方案、實(shí)施、試點(diǎn)、推廣。
如果有在
華為海思或其它芯片類(lèi)公司
工作的配管,看到這篇
文章,也可以與我交流。 yanyuzuo@qq.com
但是,拿發(fā)展成熟的制造業(yè)來(lái)說(shuō),ERP系統(tǒng)幾乎已經(jīng)成為標(biāo)配,各個(gè)公司的ERP系統(tǒng)也許會(huì)有細(xì)節(jié)不同的地方,但其功能卻相差無(wú)幾。
配置管理也是一樣,我們可能需要定制,但是一定有一套基礎(chǔ)的系統(tǒng)(base),是放之四海而皆準(zhǔn)的。
以前關(guān)注點(diǎn)一直在怎么提高應(yīng)用程序的質(zhì)量,沒(méi)太在意代碼級(jí)別的質(zhì)量。最近因?yàn)槟承┮蛩氐耐苿?dòng),需要關(guān)注到代碼級(jí)別的質(zhì)量去,把質(zhì)量
工作盡量往前推,也符合質(zhì)量控制的原則。 試用了一下
sonarqube(老版本的叫sonar,ww.sonarqube.org),對(duì)代碼的提升的確有很多的作用,sonarqube能從7個(gè)維度來(lái)對(duì)代碼質(zhì)量進(jìn)行度量。多大的作用,大家實(shí)踐下就很容易看出來(lái)。尤其是建議大家把rules里面的說(shuō)明和例子都好好看看,對(duì)以后自己寫(xiě)代碼的時(shí)候,質(zhì)量提高有很大好處。
Sonarqube安裝:
Sonarqube一共分3 部分:
這里我用的是
mysql數(shù)據(jù)庫(kù),直接執(zhí)行
SQL:
CREATEDATABASEsonarCHARACTERSETutf8COLLATEutf8_general_ci;
賦予后面連接sonarqube的數(shù)據(jù)庫(kù)用戶讀寫(xiě)權(quán)限即可
web服務(wù): 修改sonarqube/conf/sonar.properties
# Permissions to create tables, indices and triggers must be granted to JDBC user. # The schema must be created first. sonar.jdbc.username=mysql_username sonar.jdbc.password=mysql_password # Comment the following line to deactivate the default embedded database. #sonar.jdbc.url=jdbc:h2:tcp://localhost:9092/sonar #----- MySQL 5.x # Comment the embedded database and uncomment the following line to use MySQL sonar.jdbc.url=jdbc:mysql://192.168.22.99:3306/sonarqube?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=t sonar.web.host=0.0.0.0 sonar.web.context=/sonarqube sonar.web.port=9001 |
sonarqube自帶
web服務(wù)器,性能也足夠好,不需要配置tomcat什么的,到這里整個(gè)sonar web服務(wù)配置完成了,到sonarqube/bin/linux-x86-64目錄下,啟動(dòng)./sonar.sh start即可,啟動(dòng)后有任何問(wèn)題可以查看log: sonarqube/logs/sonar.log, 通過(guò)瀏覽器訪問(wèn)http://192.168.22.99:9001/sonarqube, 打開(kāi)登陸頁(yè)面,默認(rèn)管理員賬戶是admin/admin
分析器:
Sonarqube通過(guò)插件 支持20+種語(yǔ)言, Java, python, C#, C/C++, PL/SQL, Cobol等, 但C語(yǔ)言的插件是收費(fèi)的。到這里http://docs.codehaus.org/display/SONAR/Plugin+Library 下載對(duì)應(yīng)語(yǔ)言的插件,放置到sonarqube/extensions/plugins目錄下,重啟web服務(wù)即可。
分析器主要5種:
SonarQube Runner(萬(wàn)能,支持后面幾種方式的工程),
Maven(和maven編譯工程集成),
SonarQube Ant Task(和ant編譯工程集成),
Gradle(和Gradle編譯工具集成,很少聽(tīng)過(guò)),
CI Engine(主要和Jenkins , Hudson等CI工具集成)。
以下主要講Sonarqube runner分析器的使用:
下載Sonarqube 分析器:http://docs.codehaus.org/display/SONAR/Installing+and+Configuring+SonarQube+Runner, 解壓后修改conf目錄下的sonar-runner.properties, 如下例子。
#----- Default SonarQube server sonar.host.url=http://192.168.23.94:9001/sonarqube #----- PostgreSQL #sonar.jdbc.url=jdbc:postgresql://localhost/sonar #----- MySQL sonar.jdbc.url=jdbc:mysql://192.168.23.99:3306/sonarqube_qa?useUnicode=true&characterEncoding=utf8 #----- Oracle #sonar.jdbc.url=jdbc:oracle:thin:@localhost/XE #----- Microsoft SQLServer #sonar.jdbc.url=jdbc:jtds:sqlserver://localhost/sonar;SelectMethod=Cursor #----- Global database settings sonar.jdbc.username=mysql_username sonar.jdbc.password=mysql_password #----- Default source code encoding sonar.sourceEncoding=UTF-8 #----- Security (when 'sonar.forceAuthentication' is set to 'true') sonar.login=admin sonar.password=admin |
把sonarruner/bin加入到path目錄下,在環(huán)境變量里面加上SONAR_RUNNER_HOME="/home//sonarruner"。
到這里整個(gè)Sonarqube的運(yùn)行環(huán)境就全部配置完成了,下一篇講解怎么運(yùn)行分析器。
很多情況下,寫(xiě)了一堆的
test case,希望某一些test case必須在某個(gè)test case之后執(zhí)行。比如,
測(cè)試某一個(gè)Dao代碼,希望添加的case在最前面,然后是修改或者查詢,最后才是刪除,以前的做法把所有的方法都集中到某一個(gè)方法去執(zhí)行,一個(gè)個(gè)羅列好,比較麻煩。比較幸福的事情就是JUnit4.11之后提供了MethodSorters,可以有三種方式對(duì)test執(zhí)行順序進(jìn)行指定,如下:
/** * Sorts the test methods by the method name, in lexicographic order, with {@link Method#toString()} used as a tiebreaker */ NAME_ASCENDING(MethodSorter.NAME_ASCENDING), /** * Leaves the test methods in the order returned by the JVM. Note that the order from the JVM may vary from run to run */ JVM(null), /** * Sorts the test methods in a deterministic, but not predictable, order */ DEFAULT(MethodSorter.DEFAULT); |
可以小試牛刀一下:
使用DEFAULT方式:
package com.netease.test.junit; import org.apache.log4j.Logger; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; /** * User: hzwangxx * Date: 14-3-31 * Time: 15:35 */ @FixMethodOrder(MethodSorters.DEFAULT) public class TestOrder { private static final Logger LOG = Logger.getLogger(TestOrder.class); @Test public void testFirst() throws Exception { LOG.info("------1--------"); } @Test public void testSecond() throws Exception { LOG.info("------2--------"); } @Test public void testThird() throws Exception { LOG.info("------3--------"); } } /* output: 2014-03-31 16:04:15,984 0 [main] INFO - ------1-------- 2014-03-31 16:04:15,986 2 [main] INFO - ------3-------- 2014-03-31 16:04:15,987 3 [main] INFO - ------2-------- */ |
換成按字母排序
package com.netease.test.junit; import org.apache.log4j.Logger; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; /** * User: hzwangxx * Date: 14-3-31 * Time: 15:35 */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestOrder { private static final Logger LOG = Logger.getLogger(TestOrder.class); @Test public void testFirst() throws Exception { LOG.info("------1--------"); } @Test public void testSecond() throws Exception { LOG.info("------2--------"); } @Test public void testThird() throws Exception { LOG.info("------3--------"); } } /* 2014-03-31 16:10:25,360 0 [main] INFO - ------1-------- 2014-03-31 16:10:25,361 1 [main] INFO - ------2-------- 2014-03-31 16:10:25,362 2 [main] INFO - ------3-------- */ |
1. Nikto
以下是引用片段: 這是一個(gè)開(kāi)源的
Web 服務(wù)器掃描程序,它可以對(duì)Web 服務(wù)器的多種項(xiàng)目(包括3500個(gè)潛在的危險(xiǎn) 文件/CGI,以及超過(guò)900 個(gè)服務(wù)器版本,還有250 多個(gè)服務(wù)器上的版本特定問(wèn)題)進(jìn)行全面的測(cè) 試。其掃描項(xiàng)目和插件經(jīng)常更新并且可以自動(dòng)更新(如果需要的話)。 Nikto 可以在盡可能短的周期內(nèi)
測(cè)試你的Web 服務(wù)器,這在其日志文件中相當(dāng)明顯。不過(guò),如果 你想試驗(yàn)一下(或者測(cè)試你的IDS系統(tǒng)),它也可以支持LibWhisker 的反IDS方法。 不過(guò),并非每一次檢查都可以找出一個(gè)安全問(wèn)題,雖然多數(shù)情況下是這樣的。有一些項(xiàng)目是僅提 供信息(“info only” )類(lèi)型的檢查,這種檢查可以查找一些并不存在安全漏洞的項(xiàng)目,不過(guò)Web 管理員或安全工程師們并不知道。這些項(xiàng)目通常都可以恰當(dāng)?shù)貥?biāo)記出來(lái)。為我們省去不少麻煩。
2. Paros proxy
以下是引用片段: 這是一個(gè)對(duì)Web 應(yīng)用程序的漏洞進(jìn)行評(píng)估的代理程序,即一個(gè)基于Java 的web 代理程序,可以評(píng)估Web 應(yīng)用程序的漏洞。它支持動(dòng)態(tài)地編輯/查看HTTP/HTTPS,從而改變cookies和表單字段 等項(xiàng)目。它包括一個(gè)Web 通信記錄程序,Web 圈套程序(spider),hash 計(jì)算器,還有一個(gè)可以測(cè)試常見(jiàn)的Web 應(yīng)用程序攻擊(如
SQL 注入式攻擊和跨站腳本攻擊)的掃描器。
3. WebScarab
以下是引用片段: 它可以分析使用HTTP 和HTTPS 協(xié)議進(jìn)行通信的應(yīng)用程序,WebScarab 可以用最簡(jiǎn)單地形式記錄 它觀察的會(huì)話,并允許操作人員以各種方式觀查會(huì)話。如果你需要觀察一個(gè)基于HTTP(S)應(yīng)用程序的運(yùn)行狀態(tài),那么WebScarabi 就可以滿足你這種需要。不管是幫助開(kāi)發(fā)人員調(diào)試其它方面的難題,還是允許安全專業(yè)人員識(shí)別漏洞,它都是一款不錯(cuò)的工具。
4. WebInspect
以下是引用片段: 這是一款強(qiáng)大的Web 應(yīng)用程序掃描程序。SPI Dynamics 的這款應(yīng)用程序安全評(píng)估工具有助于確認(rèn)Web 應(yīng)用中已知的和未知的漏洞。它還可以檢查一個(gè)Web 服務(wù)器是否正確配置,并會(huì)嘗試一些常見(jiàn)的Web 攻擊,如參數(shù)注入、跨站腳本、目錄遍歷攻擊(directory traversal)等等。
5. Whisker/libwhisker
以下是引用片段: Libwhisker 是一個(gè)Perla 模塊,適合于HTTP 測(cè)試。它可以針對(duì)許多已知的安全漏洞,測(cè)試HTTP服務(wù)器,特別是檢測(cè)危險(xiǎn)CGI 的存在。Whisker 是一個(gè)使用libwhisker的掃描程序。
6. Burpsuite
以下是引用片段: 這是一個(gè)可以用于攻擊Web 應(yīng)用程序的集成平臺(tái)。Burp 套件允許一個(gè)攻擊者將人工的和自動(dòng)的技術(shù)結(jié)合起來(lái),以列舉、分析、攻擊Web應(yīng)用程序,或利用這些程序的漏洞。各種各樣的burp工具協(xié)同
工作,共享信息,并允許將一種工具發(fā)現(xiàn)的漏洞形成另外一種工具的基礎(chǔ)。
7. Wikto
以下是引用片段: 可以說(shuō)這是一個(gè)Web 服務(wù)器評(píng)估工具,它可以檢查Web 服務(wù)器中的漏洞,并提供與Nikto 一樣的很多功能,但增加了許多有趣的功能部分,如后端miner 和緊密的
Google 集成。它為MS.NET 環(huán)境編寫(xiě),但用戶需要注冊(cè)才能 其二進(jìn)制文件和源代碼。
8. Acunetix Web Vulnerability Scanner
以下是引用片段: 這是一款商業(yè)級(jí)的Web 漏洞掃描程序,它可以檢查Web 應(yīng)用程序中的漏洞,如SQL 注入、跨站腳本攻擊、身份驗(yàn)證頁(yè)上的弱口令長(zhǎng)度等。它擁有一個(gè)操作方便的圖形用戶界面,并且能夠創(chuàng)建專業(yè)級(jí)的Web 站點(diǎn)安全審核報(bào)告。
9. Watchfire AppScan
以下是引用片段: 這也是一款商業(yè)類(lèi)的Web 漏洞掃描程序。AppScan 在應(yīng)用程序的整個(gè)開(kāi)發(fā)周期都提供
安全測(cè)試,從而測(cè)試簡(jiǎn)化了部件測(cè)試和開(kāi)發(fā)早期的安全保證。它可以掃描許多常見(jiàn)的漏洞,如跨站腳本攻擊、HTTP 響應(yīng)拆分漏洞、參數(shù)篡改、隱式字段處理、后門(mén)/調(diào)試選項(xiàng)、緩沖區(qū)溢出等等。
10. N-Stealth
以下是引用片段: N-Stealth 是一款商業(yè)級(jí)的Web 服務(wù)器安全掃描程序。它比一些免費(fèi)的Web 掃描程序,如 Whisker/libwhisker、Nikto 等的升級(jí)頻率更高,它宣稱含有“30000個(gè)漏洞和漏洞程序”以及 “每天增加大量的漏洞檢查”,不過(guò)這種說(shuō)法令人質(zhì)疑。還要注意,實(shí)際上所有通用的VA 工具,如Nessus, ISS Internet Scanner, Retina, SAINT, Sara 等都包含Web 掃描部件。(雖然這些 工具并非總能保持軟件更新,也不一定很靈活。)N-Stealth 主要為
Windows 平臺(tái)提供掃描,但并不提供源代碼。
商業(yè)產(chǎn)品*國(guó)外
·Acunetix Web Vulnerability Scanner 6
簡(jiǎn)稱WVS,還是不錯(cuò)的掃描工具,不知道檢查 的太細(xì)致還是因?yàn)槁傊?jīng)常評(píng)估一個(gè)網(wǎng)站的時(shí)候一晚上不關(guān)電腦都掃描不萬(wàn)……但是報(bào) 表做的不錯(cuò)。一般用這個(gè)掃描的話,不用等那么久,像區(qū)縣政府的,掃20 分鐘就差不多了。
·IBM Rational AppScan
這個(gè)是IBM 旗下的產(chǎn)品,掃描速度中規(guī)中矩,報(bào)表功能相當(dāng) 強(qiáng)大,可以按照法規(guī)遵從生成不同的報(bào)表,如:ISO27001、OWASP 等,界面也很商業(yè)化。
·HP WebInspect
沒(méi)錯(cuò),的確就是賣(mài)PC 的HP 公司旗下的產(chǎn)品,掃描速度比上面的2 個(gè)都快得多,東西還算不錯(cuò)。不過(guò)這幾天在和NOSEC(下面說(shuō)的“諾賽科技”)掐架,愣是說(shuō)NOSEC 的iiScan 免費(fèi)掃描平臺(tái)侵犯隱私,說(shuō)NOSEC 有國(guó)家背景……這市場(chǎng)了解的!
·N-Stealth
沒(méi)裝成功,不過(guò)很多地方在推薦這個(gè)
·Burp Suite
貌似是《黑客攻防技術(shù)寶典·WEB 實(shí)戰(zhàn)篇》作者公司搞的,安全界牛人。
商業(yè)產(chǎn)品*國(guó)內(nèi)
·智恒聯(lián)盟WebPecker: 網(wǎng)站啄木鳥(niǎo):程序做的不錯(cuò),掃描速度很快。
·諾賽科技Pangolin、Jsky :Pangolin 做SQL 注入掃描,Jsky 全面評(píng)估,就是上文說(shuō)的 NOSEC,網(wǎng)上掃描平臺(tái)是iiScan,后臺(tái)的牛人是zwell。
·安域領(lǐng)創(chuàng)WebRavor:記得流光(FluXay)否?是的,WebRavor 就是小榕所寫(xiě)!小榕 是誰(shuí)?搜下……不用我介紹了吧?
·安恒MatriXay 明鑒WEB 應(yīng)用弱點(diǎn)掃描器:還沒(méi)用過(guò),和NOSEC 一樣,也有網(wǎng)上掃 描平臺(tái)。
綠盟NSFOCUS RSAS 極光遠(yuǎn)程安全評(píng)估系統(tǒng):極光掃描系統(tǒng)新增的WEB 安全評(píng)估插 件,在某客戶處見(jiàn)到過(guò)掃描報(bào)告,不過(guò)沒(méi)用過(guò)產(chǎn)品。依照綠盟的一貫風(fēng)格和綠盟的實(shí)力,應(yīng) 該不錯(cuò)。
免費(fèi)產(chǎn)品
·Nikto:很多地方都在推薦,但游俠本人實(shí)在不喜歡命令行產(chǎn)品……各位喜歡的Google 或Baidu 下吧
·Paros Proxy:基于Java 搞的掃描工具,速度也挺快,在淘寶QA 團(tuán)隊(duì)博客也看到在介 紹這個(gè)軟件。
·WebScarab:傳說(shuō)中很NB 的OWASP 出的產(chǎn)品,不過(guò)我看 地址的時(shí)候貌似更新挺 慢
·Sandcat:掃描速度很快,檢查的項(xiàng)目也挺多。機(jī)子現(xiàn)在就裝了這個(gè)。 ————
·NBSI:應(yīng)該說(shuō)是黑客工具更靠譜,國(guó)內(nèi)最早的,可能也是地球上最早的一批SQL 注入 及后續(xù)工作利用工具,當(dāng)年是黑站掛馬必備……
·HDSI:教主所寫(xiě),支持ASP 和PHP 注入,功能就不多說(shuō)了,也是殺人越貨必備!
·Domain:批量掃描的必備產(chǎn)品,通過(guò)whois 掃描服務(wù)器上的服務(wù)器,在很長(zhǎng)一段時(shí) 間內(nèi)風(fēng)靡黑客圈。 ————
·Nessus:當(dāng)然它有商業(yè)版,不過(guò)我們常用的是免費(fèi)版。脆弱性評(píng)估工具,更擅長(zhǎng)于主 機(jī)、服務(wù)器、網(wǎng)絡(luò)設(shè)備掃描。
·NMAP:主要傾向于端口等的評(píng)估。
·X-Scan:安全焦點(diǎn)出品,多少年過(guò)去了,依然是很強(qiáng)悍的產(chǎn)品。大成天下曾經(jīng)做過(guò)商 業(yè)版的“游刃”,但最近已經(jīng)不更新了,很可惜。
其實(shí)能做評(píng)估的工具還有很多,如:
·Retina Network Security Scanner
·LANguard Network Security Scanner
榕基RJ-iTop 網(wǎng)絡(luò)隱患掃描系統(tǒng)
不過(guò)和Nessus 和NMAP一樣,主要傾向于主機(jī)安全評(píng)估,而不是WEB 應(yīng)用安全評(píng)估。 但我們?cè)赪EB安全評(píng)估的時(shí)候,不可避免的要對(duì)服務(wù)器做安全掃描,因此也是必然要用的工具。
簡(jiǎn)單的ls實(shí)現(xiàn),首先,我們需要遍歷參數(shù)目錄下的各個(gè)文件,再根據(jù)文件相應(yīng)的性質(zhì),讀取文件的權(quán)限,用戶組,用戶名,大小,最后一次訪問(wèn)的時(shí)間,再根據(jù)文件名排序后依次顯示。
具體的函數(shù)聲明如下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <sys/stat.h> 5 #include <fcntl.h> 6 #include <unistd.h> 7 #include <dirent.h> 8 #include <sys/types.h> 9 #include <pwd.h> 10 #include <grp.h> 11 #include <time.h> 12 #define CNT 256 13 int file_name(DIR *fp, char *path, char name[][CNT]); 14 void str_sort(char name[][CNT], int cnt); 15 void mode_to_char(mode_t mode, char *buf); 16 char *time_change(char *time); 17 void show(char name[][CNT], int cnt); |
目錄的遍歷,我們需要知道目錄下讀取到的文件個(gè)數(shù),所以需要返回相應(yīng)的int型值。
目錄的遍歷實(shí)現(xiàn)如下:
1intfile_name(DIR*fp,char*path,charname[][CNT]) 2{ 3intcnt=0; 4structdirent*p; 5while((p=readdir(fp))!=NULL) 6{ 7if(strncmp(p->d_name,".",1)==0||strncmp(p->d_name,"..",2)==0) 8continue; 9strcpy(name[cnt],path); 10strcat(name[cnt],"/"); 11strcat(name[cnt],p->d_name); 12cnt++; 13} 14closedir(fp); 15returncnt; 16} |
然后我們需要了解文件的權(quán)限,文件權(quán)限保存在相對(duì)應(yīng)的參數(shù)char *buf中。
文件權(quán)限的解讀實(shí)現(xiàn)如下:
1 void mode_to_char (mode_t mode, char *buf) 2 { 3 memset(buf, '-', 10); 4 if(S_ISDIR(mode)) 5 buf[0] = 'd'; 6 if(mode & S_IRUSR) 7 buf[1] = 'r'; 8 if(mode & S_IWUSR) 9 buf[2] = 'w'; 10 if(mode & S_IXUSR) 11 buf[3] = 'x'; 12 if(mode & S_IRGRP) 13 buf[4] = 'r'; 14 if(mode & S_IWGRP) 15 buf[5] = 'w'; 16 if(mode & S_IXGRP) 17 buf[6] = 'x'; 18 if(mode & S_IROTH) 19 buf[7] = 'r'; 20 if(mode & S_IWOTH) 21 buf[8] = 'w'; 22 if(mode & S_IXOTH) 23 buf[9] = 'x'; 24 } |
想應(yīng)的,時(shí)間的顯示不需要那么精確,所以我們應(yīng)適當(dāng)?shù)目s短時(shí)間精確度。
時(shí)間的顯示實(shí)現(xiàn)如下:
1 char *time_change(char *time)
2 {
3 int index = strlen(time) - 1;
4 for(; time[index] != ':'; index --);
5 time[index] = '\0';
6 return time + 4;
7 }
然后,我們需要根據(jù)文件名稱按照字典序排序。
排序的實(shí)現(xiàn)如下:
1 void str_sort(char name[][CNT], int cnt) 2 { 3 int index, pos; 4 char str[CNT]; 5 for(pos = 1; pos < cnt; pos ++) 6 { 7 strcpy(str, name[pos]); 8 for(index = pos - 1; index >= 0; index --) 9 if(strcmp(name[index], str) > 0) 10 strcpy(name[index + 1], name[index]); 11 else 12 break; 13 strcpy(name[index + 1], str); 14 } 15 } |
最后,我們?cè)诰帉?xiě)一個(gè)簡(jiǎn)單的show()函數(shù),來(lái)顯示各個(gè)文件的信息。
show函數(shù)實(shí)現(xiàn)如下:
1 void show(char name[][CNT], int cnt) 2 { 3 int index; 4 char mode[10]; 5 char *str; 6 struct stat buf; 7 for(index = 0; index < cnt; index ++) 8 { 9 memset(&buf, 0, sizeof(buf)); 10 if(stat(name[index], &buf) == -1) 11 { 12 printf("stat error!!\n"); 13 exit(1); 14 } 15 mode_to_char(buf.st_mode, mode); 16 str = ctime(&buf.st_atime); 17 str = time_change(str); 18 int i; 19 for(i = strlen(name[index]) - 1; name[index][i] != '/'; i --); 20 i++; 21 printf("%10s.%2d %5s %5s%5d%13s %s\n", mode, buf.st_nlink, getpwuid(buf.st_uid)->pw_name, getgrgid(buf.st_gid)->gr_name, buf.st_size, str, name[index] + i); 22 } 23 } |
這里需要注意:
getpwuid()返回的不是我們要的用戶名,我們需要的是該結(jié)構(gòu)體中的一個(gè)變量——pw_name,同樣的getgrid()也應(yīng)做相應(yīng)的轉(zhuǎn)換。
測(cè)試代碼如下:
1 #include "head.h" 2 int main(int argc, char *argv[]) 3 { 4 DIR *fp; 5 char name[CNT][CNT]; 6 int cnt; 7 fp = opendir(argv[1]); 8 if(fp == NULL) 9 { 10 printf("opendir error!!\n"); 11 exit(1); 12 } 13 cnt = file_name(fp, argv[1], name); 14 str_sort(name, cnt); 15 show(name, cnt); 16 return 0; 17 } |
對(duì)于一個(gè)以
數(shù)據(jù)庫(kù)為中心的應(yīng)用,數(shù)據(jù)庫(kù)的優(yōu)化直接影響到程序的性能,因此數(shù)據(jù)庫(kù)性能至關(guān)重要。一般來(lái)說(shuō),要保證數(shù)據(jù)庫(kù)的效率,要做好以下幾個(gè)方面的
工作:
1、 數(shù)據(jù)庫(kù)表設(shè)計(jì):
表的設(shè)計(jì)合理化(符合3NF);
2、添加適當(dāng)索引(index):
普通索引:
主鍵索引: primary 效率最高,但是只能有一個(gè)
唯一索引:unique
全文索引:fulltext 對(duì)
文章中的詞進(jìn)行索引
空間索引:SPATIAL 很少使用
3、分表技術(shù):
水平分割
垂直分割
4、讀寫(xiě)分離:
寫(xiě):update/delete/insert
5、存儲(chǔ)過(guò)程
模塊化編程,可以提高速度
配置最大并發(fā)數(shù)(默認(rèn)是100),在my.ini配置文件中,一般網(wǎng)站調(diào)整到1000左右。一個(gè)并發(fā)開(kāi)一個(gè)進(jìn)程為之服務(wù),過(guò)大的話將會(huì)占用很大的內(nèi)存;
調(diào)整緩存大小;
7、MySQL硬件服務(wù)器升級(jí)
8、定時(shí)的清除不需要的數(shù)據(jù),定時(shí)進(jìn)行碎片整理(MyISAM)
默認(rèn)已經(jīng)用Groovy把外部數(shù)據(jù)給讀取出來(lái)了,關(guān)鍵是讀取出來(lái)后,如何加載到request中去?這里提供了兩種方法:
1.該Groovy腳本的名稱是"setUp"
def num = Integer.parseInt(testRunner.testCase.getPropertyValue( "count" )) log.info num num = (++num) % 2 testRunner.testCase.setPropertyValue( "count", num + "") String[] acList = ["Loginn"+String.valueOf(Math.random()).substring( 0, 5 ),"Loginn"+String.valueOf(Math.random()).substring( 0, 6 )] log.info num log.info acList[num] acList[num] |
上面的例子是把數(shù)據(jù)放到了一個(gè)數(shù)組中去了,在request中這樣寫(xiě),然后再加一個(gè)dataloop,就可以循環(huán)的來(lái)把值賦給request中,然后運(yùn)行request.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sam="http://www.soapui.org/sample/"> <soapenv:Header/> <soapenv:Body> <sam:login> <username>${setUp#result}</username> </sam:login> </soapenv:Body> </soapenv:Envelope> |
2.該Groovy腳本的名稱是"demo"
testRunner.testCase.testSuite.getTestCaseByName("TestCaseDemo").setPropertyValue("username","Loginn"+String.valueOf(Math.random()).substring( 0, 5 ))
testRunner.testCase.testSuite.getTestCaseByName("TestCaseDemo").setPropertyValue("password","Loginn123")
上面的例子中,TestCaseDemo是指testcase的名稱,在request中這樣寫(xiě):
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sam="http://www.soapui.org/sample/"> <soapenv:Header/> <soapenv:Body> <sam:login> <username>${#TestCase#username}</username> <password>${#TestCase#password}</password> </sam:login> </soapenv:Body> </soapenv:Envelope> |