# encoding: utf-8 #!/usr/bin/python import os import time import MySQLdb #设置目录 timearray = time.localtiime(time.time()) timedir = time.strftime("%Y/%m/%d/",timearray) monitordir = "/var/spool/asterisk/monitor/"+timedir vi conv.p # 打开数据库连接 db = MySQLdb.connect("localhost","root","Elastixdb","asteriskcdrdb" ) # 使用cursor()方法获取操作游标 cursor = db.cursor() sql = "SELECT recordingfile from cdr where recordingfile like '%.wav';" try: # 执行SQL语句 cursor.execute(sql) # 获取所有记录列表 results = cursor.fetchall() for row in results: recordingfile = row[0] if os.path.exists(monitordir+recordingfile): print "转换:%s" % monitordir+recordingfile os.system("sox "+monitordir+recordingfile+" "+monitordir+recordingfile.replace('wav','gsm')) os.remove(monitordir+recordingfile.replace('gsm','wav')) sql = "update cdr set recordingfile=replace(recordingfile,'wav','gsm') where recordingfile='"+recordingfile+"';" cursor.execute(sql) db.commit() else: print "找不到文件:%s" % monitordir+recordingfile except: print "Error: unable to fecth data" # 关闭数据库连接 db.close()
#NoEnv ;首先你要在ftp创建upload文件夹 FileInstall, ftp_upload.exe, ftp_upload.exe Gui, add, edit, x0 y0 w300 h20 vpath, Gui, Add, Button, x300 y0 w100 h20 gsfile, 浏览 Gui, add, edit, x0 y20 w300 h20 vdpath, Gui, Add, Button, x300 y20 w100 h20 gupload, 上传获取URL gui, show, , Nano云文件外链(FTP上传) ;定义你的ftp用户名密码 result := FtpOpen("ftp.nanoyun.com",,"xxxxx/xxxxxcdn","xxxxxxxpass") if result = 0 { MsgBox, 4112, 错误, 无法连接到服务器 ExitApp } return sfile: FileSelectFile, path, , , 选择要上传的文件, (*jpg;*.png;*.gif;*.zip;*.rar;*.zip;*.7z;*.ahk;*.aau;*.exe) ;允许上传的文件类型 if path { IfNotInString, path, %A_Space% GuiControl, , path, % path else { FileCopy, % path, % npath := RegExReplace(path," ","_") GuiControl, , path, % npath } GuiControl, , dpath, } return upload: Gui, Submit, NoHide if path { FileDelete, result.txt SplitPath, path, , , ext md5 := FileMD5(path) /* 外部工具方案 RunWait, % ComSpec " /c ftp_upload.exe ftp.nanoyun.com user pass " path " /upload/" md5 "." ext " >result.txt", , Hide FileRead, result, result.txt if result MsgBox, 64, 提示, % result */ result := FtpPutFile(path, "/upload/" md5 "." ext, 2) if result = 0 { MsgBox, 4112, 错误, 上传遇到错误! return } MsgBox, 64, 提示, % result "`n已复制到剪切板!" GuiControl, , dpath, % Clipboard := "http://cdn.ywwx.com.cn/upload/" md5 "." ext ;此处是你的外链网址 需要修改 } return GuiClose: FtpClose() ExitApp ;ftp函数集 FtpCreateDirectory(DirName) { ;创建目录 global ic_hInternet r := DllCall("wininet\FtpCreateDirectoryA", "uint", ic_hInternet, "str", DirName) If (ErrorLevel != 0 or r = 0) return 0 else return 1 } FtpRemoveDirectory(DirName) { ;移除目录 global ic_hInternet r := DllCall("wininet\FtpRemoveDirectoryA", "uint", ic_hInternet, "str", DirName) If (ErrorLevel != 0 or r = 0) return 0 else return 1 } FtpSetCurrentDirectory(DirName) { ;设置当前目录 global ic_hInternet r := DllCall("wininet\FtpSetCurrentDirectoryA", "uint", ic_hInternet, "str", DirName) If (ErrorLevel != 0 or r = 0) return 0 else return 1 } FtpPutFile(LocalFile, NewRemoteFile="", Flags=0) { ;上传文件 ;Flags: ;FTP_TRANSFER_TYPE_UNKNOWN = 0 (Defaults to FTP_TRANSFER_TYPE_BINARY) ;FTP_TRANSFER_TYPE_ASCII = 1 文本方式 ;FTP_TRANSFER_TYPE_BINARY = 2 二进制方式 If NewRemoteFile= NewRemoteFile := LocalFile global ic_hInternet r := DllCall("wininet\FtpPutFileA" , "uint", ic_hInternet , "str", LocalFile , "str", NewRemoteFile , "uint", Flags , "uint", 0) ;dwContext If (ErrorLevel != 0 or r = 0) return 0 else return 1 } FtpGetFile(RemoteFile, NewFile="", Flags=0) { ;下载文件 ;Flags: ;FTP_TRANSFER_TYPE_UNKNOWN = 0 (Defaults to FTP_TRANSFER_TYPE_BINARY) ;FTP_TRANSFER_TYPE_ASCII = 1 ;FTP_TRANSFER_TYPE_BINARY = 2 If NewFile= NewFile := RemoteFile global ic_hInternet r := DllCall("wininet\FtpGetFileA" , "uint", ic_hInternet , "str", RemoteFile , "str", NewFile , "int", 1 ;do not overwrite existing files , "uint", 0 ;dwFlagsAndAttributes , "uint", Flags , "uint", 0) ;dwContext If (ErrorLevel != 0 or r = 0) return 0 else return 1 } FtpGetFileSize(FileName, Flags=0) { ;获取文件大小 ;Flags: ;FTP_TRANSFER_TYPE_UNKNOWN = 0 (Defaults to FTP_TRANSFER_TYPE_BINARY) ;FTP_TRANSFER_TYPE_ASCII = 1 ;FTP_TRANSFER_TYPE_BINARY = 2 global ic_hInternet fof_hInternet := DllCall("wininet\FtpOpenFileA" , "uint", ic_hInternet , "str", FileName , "uint", 0x80000000 ;dwAccess: GENERIC_READ , "uint", Flags , "uint", 0) ;dwContext If (ErrorLevel != 0 or fof_hInternet = 0) return -1 FileSize := DllCall("wininet\FtpGetFileSize", "uint", fof_hInternet, "uint", 0) DllCall("wininet\InternetCloseHandle", "UInt", fof_hInternet) return, FileSize } FtpDeleteFile(FileName) { ;删除文件 global ic_hInternet r := DllCall("wininet\FtpDeleteFileA", "uint", ic_hInternet, "str", FileName) If (ErrorLevel != 0 or r = 0) return 0 else return 1 } FtpRenameFile(Existing, New) { ;重命名文件 global ic_hInternet r := DllCall("wininet\FtpRenameFileA", "uint", ic_hInternet, "str", Existing, "str", New) If (ErrorLevel != 0 or r = 0) return 0 else return 1 } FtpOpen(Server, Port=21, Username=0, Password=0 ,Proxy="", ProxyBypass="") { ;打开ftp连接 IfEqual, Username, 0, SetEnv, Username, anonymous IfEqual, Password, 0, SetEnv, Password, anonymous If (Proxy != "") AccessType=3 Else AccessType=1 ;#define INTERNET_OPEN_TYPE_PRECONFIG 0 // use registry configuration ;#define INTERNET_OPEN_TYPE_DIRECT 1 // direct to net ;#define INTERNET_OPEN_TYPE_PROXY 3 // via named proxy ;#define INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY 4 // prevent using java/script/INS global ic_hInternet, io_hInternet, hModule hModule := DllCall("LoadLibrary", "str", "wininet.dll") io_hInternet := DllCall("wininet\InternetOpenA" , "str", A_ScriptName ;lpszAgent , "UInt", AccessType , "str", Proxy , "str", ProxyBypass , "UInt", 0) ;dwFlags If (ErrorLevel != 0 or io_hInternet = 0) { FtpClose() return 0 } ic_hInternet := DllCall("wininet\InternetConnectA" , "uint", io_hInternet , "str", Server , "uint", Port , "str", Username , "str", Password , "uint" , 1 ;dwService (INTERNET_SERVICE_FTP = 1) , "uint", 0 ;dwFlags , "uint", 0) ;dwContext If (ErrorLevel != 0 or ic_hInternet = 0) return 0 else return 1 } FtpClose() { ;关闭ftp连接 global ic_hInternet, io_hInternet, hModule DllCall("wininet\InternetCloseHandle", "UInt", ic_hInternet) DllCall("wininet\InternetCloseHandle", "UInt", io_hInternet) DllCall("FreeLibrary", "UInt", hModule) } FileMD5(filename) ;计算文件MD5值 { return CalcFileHash(filename, 0x8003, 64 * 1024) } CalcFileHash(filename, algid, continue = 0, byref hash = 0, byref hashlength = 0) ;计算文件hash { fpos := "" if (!(f := FileOpen(filename, "r"))) { return } f.pos := 0 if (!continue && f.length > 0x7fffffff) { return } if (!continue) { VarSetCapacity(data, f.length, 0) f.rawRead(&data, f.length) f.pos := oldpos return CalcAddrHash(&data, f.length, algid, hash, hashlength) } hashlength := 0 while (f.pos < f.length) { readlength := (f.length - fpos > continue) ? continue : f.length - f.pos VarSetCapacity(data, hashlength + readlength, 0) DllCall("RtlMoveMemory", "Ptr", &data, "Ptr", &hash, "Ptr", hashlength) f.rawRead(&data + hashlength, readlength) h := CalcAddrHash(&data, hashlength + readlength, algid, hash, hashlength) } return h } CalcAddrHash(addr, length, algid, byref hash = 0, byref hashlength = 0) { static h := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f"] static b := h.minIndex() hProv := hHash := o := "" if (DllCall("advapi32\CryptAcquireContext", "Ptr*", hProv, "Ptr", 0, "Ptr", 0, "UInt", 24, "UInt", 0xf0000000)) { if (DllCall("advapi32\CryptCreateHash", "Ptr", hProv, "UInt", algid, "UInt", 0, "UInt", 0, "Ptr*", hHash)) { if (DllCall("advapi32\CryptHashData", "Ptr", hHash, "Ptr", addr, "UInt", length, "UInt", 0)) { if (DllCall("advapi32\CryptGetHashParam", "Ptr", hHash, "UInt", 2, "Ptr", 0, "UInt*", hashlength, "UInt", 0)) { VarSetCapacity(hash, hashlength, 0) if (DllCall("advapi32\CryptGetHashParam", "Ptr", hHash, "UInt", 2, "Ptr", &hash, "UInt*", hashlength, "UInt", 0)) { loop % hashlength { v := NumGet(hash, A_Index - 1, "UChar") o .= h[(v >> 4) + b] h[(v & 0xf) + b] } } } } DllCall("advapi32\CryptDestroyHash", "Ptr", hHash) } DllCall("advapi32\CryptReleaseContext", "Ptr", hProv, "UInt", 0) } return o }
import console; import inet.ftp; var p = string.split(_CMDLINE," "); if(p[1]!=null and p[2]!=null and p[3]!=null and p[4]!=null and p[5]!=null){ ftp = inet.ftp(p[1],p[2],p[3]); if(!ftp){ console.log("请输入正确的服务器参数"); return; } file = ftp.upload(p[4],p[5],2) ftp.close() }else{ console.log('参数:服务器 用户名 密码 源文件 目标ftp路径\n所有参数不能包含空格'); } console.close();
import console; import mysql.client; //本地数据库 console.log("正在连接本地数据库服务器..."); var localdb,err = mysql.client( server = "localhost"; uid = "root"; pwd = "123456"; ); if(!localdb){ console.log("连接数据库失败",err) return; } localdb.selectDb("blog"); console.log("本地数据库连接成功"); //远端数据库 console.log("正在连接远端数据库服务器..."); var remotedb,err = mysql.client( server = "8.8.8.8"; uid = "xxxxx"; pwd = "xxxxx"; ); if(!remotedb){ console.log("连接数据库失败",err) return; } remotedb.selectDb("blog"); console.log("远端数据库连接成功"); //同步本地日志到远端 console.log("同步本地日志到远端"); //查询最大ID var result = remotedb.query("SELECT max(ID) as MAXID FROM wp_posts"); var remote_post_max_id = result.fetchObject()["MAXID"]; //console.log("远端最大ID:"++remote_post_max_id) result.free(); //查询本地 var result = localdb.query("SELECT ID FROM wp_posts where ID>"++tostring(remote_post_max_id)); var local_post_sync_count = result.numRows(); console.log("需同步"++local_post_sync_count) result.free(); //执行同步 if(local_post_sync_count>0){ //首先替换网址 localdb.exec("update wp_posts set post_content=replace(post_content,'thinkai.net','thinkai.net') where ID>"++tostring(remote_post_max_id)); var result = localdb.query("SELECT * FROM wp_posts where ID>"++tostring(remote_post_max_id)); for(i=1;local_post_sync_count){ var row = result.fetchObject(); console.log(string.concat("同步ID:",row['ID']," 标题:",row['post_title'])); remotedb.exec("insert into wp_posts values (@ID, @post_author, @post_date, @post_date_gmt, @post_content, @post_title, @post_excerpt, @post_status, @comment_status, @ping_status, @post_password, @post_name, @to_ping, @pinged, @post_modified, @post_modified_gmt, @post_content_filtered, @post_parent, @guid, @menu_order, @post_type, @post_mime_type, @comment_count)",row) } } //同步本地日志分类到远端 console.log("同步本地日志分类到远端"); //查询最大ID var result = remotedb.query("SELECT max(object_id) as MAXID FROM wp_term_relationships"); var remote_term_max_id = result.fetchObject()["MAXID"]; result.free(); //查询本地 var result = localdb.query("SELECT object_id FROM wp_term_relationships where object_id>"++tostring(remote_term_max_id)); var local_term_sync_count = result.numRows(); console.log("需同步"++local_term_sync_count) result.free(); //执行同步 if(local_term_sync_count>0){ var result = localdb.query("SELECT * FROM wp_term_relationships where object_id>"++tostring(remote_term_max_id)); for(i=1;local_term_sync_count){ var row = result.fetchObject(); console.log(string.concat("同步ID:",row['object_id'])); remotedb.exec("insert into wp_term_relationships values (@object_id, @term_taxonomy_id, @term_order)",row) } } //同步本地分类项目到远端 console.log("同步本地分类项目到远端"); //查询最大ID var result = remotedb.query("SELECT max(term_taxonomy_id) as MAXID FROM wp_term_taxonomy"); var remote_termt_max_id = result.fetchObject()["MAXID"]; result.free(); //查询本地 var result = localdb.query("SELECT term_taxonomy_id FROM wp_term_taxonomy where term_taxonomy_id>"++tostring(remote_termt_max_id)); var local_termt_sync_count = result.numRows(); console.log("需同步"++local_termt_sync_count) result.free(); //执行同步 if(local_termt_sync_count>0){ var result = localdb.query("SELECT * FROM wp_term_taxonomy where term_taxonomy_id>"++tostring(remote_termt_max_id)); for(i=1;local_termt_sync_count){ var row = result.fetchObject(); console.log(string.concat("同步ID:",row['term_taxonomy_id'])); remotedb.exec("insert into wp_term_taxonomy values (@term_taxonomy_id, @term_id, @taxonomy, @description, @parent, @count)",row) } } //查询最大ID var result = remotedb.query("SELECT max(term_id) as MAXID FROM wp_terms"); var remote_term_max_id = result.fetchObject()["MAXID"]; result.free(); //查询本地 var result = localdb.query("SELECT term_id FROM wp_terms where term_id>"++tostring(remote_term_max_id)); var local_term_sync_count = result.numRows(); console.log("需同步"++local_term_sync_count) result.free(); //执行同步 if(local_term_sync_count>0){ var result = localdb.query("SELECT * FROM wp_terms where term_id>"++tostring(remote_term_max_id)); for(i=1;local_term_sync_count){ var row = result.fetchObject(); console.log(string.concat("同步ID:",row['term_id'])); remotedb.exec("insert into wp_terms values (@term_id, @name, @slug, @term_group)",row) } } localdb.close(); remotedb.close(); console.pause();
首先你得有个获取队列情况的接口。如果使用ami的话太麻烦,接收的数据控制不好断节,所以我用了php+shell的形式获取数据。由于是局域网内使用,所以没加验证,有需求的自己加一下。
vi /var/www/html/cli.php
按i进入插入模式,粘贴上如下代码:
<?php if(isset($_GET["cmd"])){ //先判断是否是预期参数 $fp=popen("asterisk -x \"".$_GET["cmd"]."\"","r"); //asterisk -x单句命令执行 while(!feof($fp)) echo fgets($fp,4096); pclose($fp); } ?>
按Esc输入":wq"保存退出。好了这个接口就可以使用来执行Asterisk CLI命令了。
然后通过你自己的坐席数据库接口,结合ahk写一个客户端。
;数据库配置信息 host = 135.230.71.1 api = http://%host%/sqlapi.php #MaxMem 1024 ;检查连通性 if Not InStr(ping_info := ping(host),"正常") { MsgBox, 4112, 网络错误, % ping_info ExitApp } ;创建GUI gui, add, edit, x0 y0 w800 h400 vshow, gui, show, , 本地呼叫系统坐席队列监控 gui, +AlwaysOnTop +Resize ;循环监控坐席状态 3秒间隔 Loop { out = Queue := QueueStatus() ;获取队列状态数组 tp := get_result_obj("select 队列,业务 from [我是口令呼叫系统数据库].[dbo].[呼叫系统业务分派] where 状态=1 and ((cast(getdate() as time) between 开始时间1 and 结束时间1) or (cast(getdate() as time) between 开始时间2 and 结束时间2));") ;这是一个获取当前正在执行的任务的语句 task := [] for k,v in tp task[v[1]] := v[2] tp := get_result_obj("select 分机,工号,姓名 from [我是口令呼叫系统数据库].[dbo].[呼叫系统分机信息] where [工号] is not null") ;获取已经登记的坐席信息 user := [] for k,v in tp user[v[1]] := {"id":v[2],"name":v[3]} ;格式化输出 for group,gv in Queue { out .= task[group] "(" group ") 策略:" gv["strategy"] " " gv["incall"] "个等待来电 平均摘机时间:" gv["holdtime"] "(秒)平均通话时长:" gv["talktime"] "(秒)`n" for exten,mv in gv["member"] { sp = loop % 20-strlen(user[exten]["name"]) sp .= " " ;很笨的一种汉化替换方法 status := RegExReplace(mv["status"],"In use","通话中") status := RegExReplace(status,"Not in use","空闲") status := RegExReplace(status,"Ringing","振铃") status := RegExReplace(status,"Unavailable","不可用") status := RegExReplace(status,"On hold","保持") out .= " 坐席:" user[exten]["name"] "(" user[exten]["id"] " " exten ")" sp " 类型:" mv["kind"] " 状态:" status " 本次签入后呼叫量:" mv["callcount"] " 最后一次摘机:" mv["lastcalltime"] "秒前`n" } for k,cv in gv["caller"] out .= " 来电:" k "." cv["phone"] " 等待时间:" cv["wait"] "秒`n" out .= "`n" } GuiControl, , show, % out Sleep, 3000 } Return ;界面调整尺寸 GuiSize: GuiControl, move, show, % "w" A_GuiWidth "h" A_GuiHeight Return ;获取状态函数 QueueStatus(){ src := URLDownloadToVar("http://135.230.71.2/cli.php?cmd=queue show") ;你的Asterisk的cli接口 queues := [] Loop, Parse, src, `n, `r { line := A_LoopField if RegExMatch(line,"(\d+) has (\d+) calls \(max unlimited\) in '(\w+)' strategy \((\d+)s holdtime, (\d+)s talktime\), W:\d+, C:\d+, A:\d+, SL:[0-9\.]+% within \d+s",qtm) ;队列标题匹配 { cqueue := qtm1 queues[cqueue] := {"incall":qtm2,"strategy":qtm3,"holdtime":qtm4,"talktime":qtm5,member:{},caller:{}} } else if RegExMatch(line,"\s+sip/(\d+) with penalty 1 \(ringinuse disabled\) \((\w+)\) \((.+)\) has taken (\d+) calls \(last was (\d+) secs ago\)",mcm) ;坐席匹配1 queues[cqueue]["member"][mcm1] := {"kind":mcm2,"status":mcm3,"callcount":mcm4,"lastcalltime":mcm5} else if RegExMatch(line,"\s+sip/(\d+) with penalty 1 \(ringinuse disabled\) \((\w+)\) \((.+)\) has taken no calls yet",mcm) ;坐席匹配2 queues[cqueue]["member"][mcm1] := {"kind":mcm2,"status":mcm3,"callcount":0,"lastcalltime":"NULL"} else if RegExMatch(line,"\s+(\d+). DAHDI/i1/(\d+)-\w+ \(wait: 0:(\d+), prio: 0\)",ccm) ;来电匹配 queues[cqueue]["caller"][ccm1] := {"phone":ccm2,"wait":ccm3} } Return queues } ;返回csv带标题格式查询结果 get_result_with_colname(sql){ global api result := URLDownloadToVar(api "?str=" urlencode(sql "我是口令") "&o=1","UTF-8") return RegExReplace(result,"`n$","") } ;返回csv查询结果 get_result(sql){ global api result := URLDownloadToVar(api "?str=" urlencode(sql "我是口令"),"UTF-8") return RegExReplace(result,"`n$","") } ;返回查询数组 get_result_obj(sql){ global api result := URLDownloadToVar(api "?str=" urlencode(sql "我是口令"),"UTF-8") ;return RegExReplace(result,"`n$","") line := strsplit(result,"`n","`r") for k,v in line { if v line[k] := strsplit(v,",") Else line.remove(k) } return line } ;返回1行数据 get_1_result(sql){ global api result := URLDownloadToVar(api "?str=" urlencode(sql "我是口令"),"UTF-8") return RegExReplace(result,"^([^\n]*)\n.*$","$1") } ;返回执行影响结果 get_rowcount(sql){ global api result := URLDownloadToVar(api "?str=" urlencode(sql "我是口令") "&o=2","UTF-8") return RegExReplace(result,"^([^\n]*)\n.*$","$1") } URLDownloadToVar(url, Encoding = "",Method="GET",postData=""){ ;网址,编码,请求方式,post数据 hObject:=ComObjCreate("WinHttp.WinHttpRequest.5.1") if Method = GET { Try { hObject.Open("GET",url) hObject.Send() } catch e return -1 } else if Method = POST { Try { hObject.Open("POST",url,False) hObject.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded") hObject.Send(postData) } catch e return -1 } if (Encoding && hObject.ResponseBody) { oADO := ComObjCreate("adodb.stream") oADO.Type := 1 oADO.Mode := 3 oADO.Open() oADO.Write(hObject.ResponseBody) oADO.Position := 0 oADO.Type := 2 oADO.Charset := Encoding return oADO.ReadText(), oADO.Close() } return hObject.ResponseText } Ansi2UTF8(sString) { Ansi2Unicode(sString, wString, 0) Unicode2Ansi(wString, zString, 65001) Return zString } UTF82Ansi(zString) { Ansi2Unicode(zString, wString, 65001) Unicode2Ansi(wString, sString, 0) Return sString } Ansi2Unicode(ByRef sString, ByRef wString, CP = 0) { nSize := DllCall("MultiByteToWideChar" , "Uint", CP , "Uint", 0 , "Uint", &sString , "int", -1 , "Uint", 0 , "int", 0) VarSetCapacity(wString, nSize * 2) DllCall("MultiByteToWideChar" , "Uint", CP , "Uint", 0 , "Uint", &sString , "int", -1 , "Uint", &wString , "int", nSize) } Unicode2Ansi(ByRef wString, ByRef sString, CP = 0) { nSize := DllCall("WideCharToMultiByte" , "Uint", CP , "Uint", 0 , "Uint", &wString , "int", -1 , "Uint", 0 , "int", 0 , "Uint", 0 , "Uint", 0) VarSetCapacity(sString, nSize) DllCall("WideCharToMultiByte" , "Uint", CP , "Uint", 0 , "Uint", &wString , "int", -1 , "str", sString , "int", nSize , "Uint", 0 , "Uint", 0) } urlencode(string){ string := Ansi2UTF8(string) StringLen, len, string Loop % len { SetFormat, IntegerFast, hex StringMid, out, string, %A_Index%, 1 hex := Asc(out) hex2 := hex StringReplace, hex, hex, 0x, , All SetFormat, IntegerFast, d hex2 := hex2 If (hex2==33 || (hex2>=39 && hex2 <=42) || hex2==45 || hex2 ==46 || (hex2>=48 && hex2<=57) || (hex2>=65 && hex2<=90) || hex2==95 || (hex2>=97 && hex2<=122) || hex2==126) content .= out Else content .= "`%" hex } Return content } ping(ip){ FileEncoding, RunWait, %ComSpec% /c ping -n 1 %ip% >%A_Temp%\ahk_ping.tmp, , Hide FileRead, content, %A_Temp%\ahk_ping.tmp StringReplace, content, content, `r, , All StringSplit, var, content, `n If content Contains 请求超时,Request timed out Return "请求超时" If content Contains 找不到主机,could not find host Return "找不到主机 " If content Contains 无法访问目标主机,Destination host unreachable Return "无法访问目标主机 " Else { time := RegExReplace(var3, "(来自|Reply from) \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}[\s的回复|]*: (字节|bytes)=\d{1,3}\ (时间|time)[=<](\d{1,3})ms TTL=\d{1,3}","$4") Return "正常 time:" time "ms" } FileEncoding, UTF-8 } ;调试用 输出数组 show_obj(obj,menu_name:=""){ static id if menu_name = { main = 1 id++ menu_name := id } Menu, % menu_name, add, Menu, % menu_name, DeleteAll for k,v in obj { if (IsObject(v)) { id++ submenu_name := id Menu, % submenu_name, add, Menu, % submenu_name, DeleteAll Menu, % menu_name, add, % k ? "【" k "】[obj]" : "", :%submenu_name% show_obj(v,submenu_name) } Else { Menu, % menu_name, add, % k ? "【" k "】" v: "", MenuHandler } } if main = 1 menu,% menu_name, show MenuHandler: return } GuiClose: ExitApp
好了,看下效果:
RunAs, Administrator, ;用户名 密码 try Run, %ComSpec% /c, , hide catch error ;错误对象 MsgBox, 4112, % error["Message"], % error["Extra"] RunAs
;加载你的dll 注意像下面这种文件名里面有多个点的写全文件名 hModule := DllCall("LoadLibrary", "Str", "time.cqp.dll", "Ptr") ;无参数类型返回字符串 ;Ptr1 := DllCall("time.cqp.dll\info") ;返回指针 ;带参数类型返回字符串 ;注意一定要用numput,不然指针飞了报0x0000005的错 ;长度自己定好 VarSetCapacity(p1,3),VarSetCapacity(p2,3),VarSetCapacity(p3,3),VarSetCapacity(p4,3) numput(0x313233,p1),numput(0x343536,p2),numput(0x373839,p3),numput(0x404142,p4) ;注意这里指针一定要用&变量的格式传入指针 参数记得写全 不然报错-4 Ptr2 := DllCall("time.cqp.dll\plugmain","Ptr",&p1,"Ptr",&p2,"Ptr",&p3,"Ptr",&p4,"Ptr",&p4) Error := ErrorLevel ;保存错误值 Str = ;初始输出字符串变量 Loop { UChar := NumGet(0+Ptr2,A_index-1,"UChar") if (UChar=0x0) ;以0结束 break Str .= Chr(UChar) } MsgBox % Str "`n" Error
从AHK_L 46+开始增加了StrPut()和StrGet()来读取写入字符串到内存。
hModule := DllCall("LoadLibrary", "Str", "time.cqp.dll", "Ptr") StrPutVar("你",p1),StrPutVar("是",p2),StrPutVar("谁",p3),StrPutVar("啊",p4),StrPutVar("?",p5) Ptr2 := DllCall("time.cqp.dll\plugmain","Ptr",&p1,"Ptr",&p2,"Ptr",&p3,"Ptr",&p4,"Ptr",&p5) Error := ErrorLevel ;保存错误值 MsgBox % StrGet(Ptr2) "`n" Error StrPutVar(string, ByRef var, encoding:="") { ; 确定容量. VarSetCapacity( var, StrPut(string, encoding) ; StrPut 返回字符数, 但 VarSetCapacity 需要字节数. * ((encoding="utf-16"||encoding="cp1200") ? 2 : 1) ) ; 复制或转换字符串. return StrPut(string, &var, encoding) }
;Autohotkey+Web Short Message(com.wangtai.smstwoman)短信接口 ;Thinkai@2015-01-05 ;注意每次运行APP的管理网址都不一样 ManageUrl = http://192.168.1.106:1984/8119 ;获取参数 RegExMatch(ManageUrl,"^(http://.*:\d*/)(\d{4})",parameter) global parameter1 global parameter2 ;运用实例 ;发短信 if (SendMsg(10001,7)=1) MsgBox, 64, 提示, 短信发送成功 ;接收回复 NewMessage := GetNewMsg() From := NewMessage[1]["person"] ? NewMessage[1]["person"] "(" NewMessage[1]["address"] ")" : "未知(" NewMessage[1]["address"] ")" MsgBox % "From:" From "`n" NewMessage[1]["body"] ;获取联系人 Contact := GetContacts() for k,v in Contact { MsgBox, 64, 提示, 第一个联系人是%v%`,号码是%k% Return } ;获取新消息函数(调用后收到的) GetNewMsg(){ ;返回数组说明 ;数组[1]: ; _id:消息ID ; address:号码 ; body:短信正文 ; date:收信Uinx时间戳 ; person:联系人 Loop { res := URLDownloadToVar(parameter1 "get_new_msg/" parameter2 "/", "utf-8","POST") ;获取最新短信的JSON数据 if (strlen(res)>2) Return json_toobj(res) Sleep, 100 } } ;获取联系人函数 GetContacts(){ obj := {} ;初始数组 res := URLDownloadToVar(parameter1 "get_contacts/" parameter2 "/", "utf-8","POST") ;获取联系人的JSON数据 ;处理格式问题 StringTrimLeft, res, res, 1 StringTrimRight, res, res, 1 StringSplit, var, res, `, loop % var0 { tmp_var := var%A_index% RegExMatch(tmp_var,"""(.*)"":""(.*)""",m) m1 := RegExReplace(m1,"\s","") m1 := RegExReplace(m1,"\+86","") obj["" m1] := m2 ;注意此处数组key的类型 } Return obj ;返回数组 obj[电话号码] := 联系人姓名 } ;发短信函数 SendMsg(to,msg){ ;号码,消息 msg := urlencode(msg) Return URLDownloadToVar(parameter1 "send/" parameter2 "/" to "/", "utf-8","POST","msg=" msg) } URLDownloadToVar(url, Encoding = "",Method="GET",postData=""){ ;网址,编码,请求方式,post数据 hObject:=ComObjCreate("WinHttp.WinHttpRequest.5.1") if Method = GET { hObject.Open("GET",url) Try hObject.Send() catch e return -1 } else if Method = POST { hObject.Open("POST",url,False) hObject.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded") Try hObject.Send(postData) catch e return -1 } if Encoding { oADO := ComObjCreate("adodb.stream") oADO.Type := 1 oADO.Mode := 3 oADO.Open() oADO.Write(hObject.ResponseBody) oADO.Position := 0 oADO.Type := 2 oADO.Charset := Encoding return oADO.ReadText(), oADO.Close() } return hObject.ResponseText } urlencode(string){ string := Ansi2UTF8(string) StringLen, len, string Loop % len { SetFormat, IntegerFast, hex ;运算结果为HEX StringMid, out, string, %A_Index%, 1 hex := Asc(out) ;获取单字节ascii值 hex2 := hex ;另存变量 StringReplace, hex, hex, 0x, , All SetFormat, IntegerFast, d hex2 := hex2 ;十进制化 ;判断是否可见单字节字符 是则直接连接 否则编码 If (hex2==33 || (hex2>=39 && hex2 <=42) || hex2==45 || hex2 ==46 || (hex2>=48 && hex2<=57) || (hex2>=65 && hex2<=90) || hex2==95 || (hex2>=97 && hex2<=122) || hex2==126) content .= out Else content .= "`%" hex } Return content } Ansi2Oem(sString) { Ansi2Unicode(sString, wString, 0) Unicode2Ansi(wString, zString, 1) Return zString } Oem2Ansi(zString) { Ansi2Unicode(zString, wString, 1) Unicode2Ansi(wString, sString, 0) Return sString } Ansi2UTF8(sString) { Ansi2Unicode(sString, wString, 0) Unicode2Ansi(wString, zString, 65001) Return zString } UTF82Ansi(zString) { Ansi2Unicode(zString, wString, 65001) Unicode2Ansi(wString, sString, 0) Return sString } Ansi2Unicode(ByRef sString, ByRef wString, CP = 0) { nSize := DllCall("MultiByteToWideChar" , "Uint", CP , "Uint", 0 , "Uint", &sString , "int", -1 , "Uint", 0 , "int", 0) VarSetCapacity(wString, nSize * 2) DllCall("MultiByteToWideChar" , "Uint", CP , "Uint", 0 , "Uint", &sString , "int", -1 , "Uint", &wString , "int", nSize) } Unicode2Ansi(ByRef wString, ByRef sString, CP = 0) { nSize := DllCall("WideCharToMultiByte" , "Uint", CP , "Uint", 0 , "Uint", &wString , "int", -1 , "Uint", 0 , "int", 0 , "Uint", 0 , "Uint", 0) VarSetCapacity(sString, nSize) DllCall("WideCharToMultiByte" , "Uint", CP , "Uint", 0 , "Uint", &wString , "int", -1 , "str", sString , "int", nSize , "Uint", 0 , "Uint", 0) } json_toobj(str){ quot := """" ; firmcoded specifically for readability. Hardcode for (minor) performance gain ws := "`t`n`r " Chr(160) ; whitespace plus NBSP. This gets trimmed from the markup obj := {} ; dummy object objs := [] ; stack keys := [] ; stack isarrays := [] ; stack literals := [] ; queue y := nest := 0 ; First pass swaps out literal strings so we can parse the markup easily StringGetPos, z, str, %quot% ; initial seek while !ErrorLevel { ; Look for the non-literal quote that ends this string. Encode literal backslashes as '\u005C' because the ; '\u..' entities are decoded last and that prevents literal backslashes from borking normal characters StringGetPos, x, str, %quot%,, % z + 1 while !ErrorLevel { StringMid, key, str, z + 2, x - z - 1 StringReplace, key, key, \\, \u005C, A If SubStr( key, 0 ) != "\" Break StringGetPos, x, str, %quot%,, % x + 1 } ; StringReplace, str, str, %quot%%t%%quot%, %quot% ; this might corrupt the string str := ( z ? SubStr( str, 1, z ) : "" ) quot SubStr( str, x + 2 ) ; this won't ; Decode entities StringReplace, key, key, \%quot%, %quot%, A StringReplace, key, key, \b, % Chr(08), A StringReplace, key, key, \t, % A_Tab, A StringReplace, key, key, \n, `n, A StringReplace, key, key, \f, % Chr(12), A StringReplace, key, key, \r, `r, A StringReplace, key, key, \/, /, A while y := InStr( key, "\u", 0, y + 1 ) if ( A_IsUnicode || Abs( "0x" SubStr( key, y + 2, 4 ) ) < 0x100 ) key := ( y = 1 ? "" : SubStr( key, 1, y - 1 ) ) Chr( "0x" SubStr( key, y + 2, 4 ) ) SubStr( key, y + 6 ) literals.insert(key) StringGetPos, z, str, %quot%,, % z + 1 ; seek } ; Second pass parses the markup and builds the object iteratively, swapping placeholders as they are encountered key := isarray := 1 ; The outer loop splits the blob into paths at markers where nest level decreases Loop Parse, str, % "]}" { StringReplace, str, A_LoopField, [, [], A ; mark any array open-brackets ; This inner loop splits the path into segments at markers that signal nest level increases Loop Parse, str, % "[{" { ; The first segment might contain members that belong to the previous object ; Otherwise, push the previous object and key to their stacks and start a new object if ( A_Index != 1 ) { objs.insert( obj ) isarrays.insert( isarray ) keys.insert( key ) obj := {} isarray := key := Asc( A_LoopField ) = 93 } ; arrrrays are made by pirates and they have index keys if ( isarray ) { Loop Parse, A_LoopField, `,, % ws "]" if ( A_LoopField != "" ) obj[key++] := A_LoopField = quot ? literals.remove(1) : A_LoopField } ; otherwise, parse the segment as key/value pairs else { Loop Parse, A_LoopField, `, Loop Parse, A_LoopField, :, % ws if ( A_Index = 1 ) key := A_LoopField = quot ? literals.remove(1) : A_LoopField else if ( A_Index = 2 && A_LoopField != "" ) obj[key] := A_LoopField = quot ? literals.remove(1) : A_LoopField } nest += A_Index > 1 } ; Loop Parse, str, % "[{" If !--nest Break ; Insert the newly closed object into the one on top of the stack, then pop the stack pbj := obj obj := objs.remove() obj[key := keys.remove()] := pbj If ( isarray := isarrays.remove() ) key++ } ; Loop Parse, str, % "]}" Return obj }
#下载 wget http://fossies.org/unix/privat/DenyHosts-2.6.tar.gz #解压 tar -zxvf DenyHosts-2.6.tar.gz #为了方便改个名 mv DenyHosts-2.6 denyhost #进入目录 cd denyhost #安装python yum install python -y #安装denyhost,脚本 python setup.py install #进入配置目录 cd /usr/share/denyhosts/ #为了方便改变配置文件名称 cp daemon-control-dist daemon-control #修改服务文件名称 cp denyhosts.cfg-dist denyhosts.cfg #提高安全级别,修改权限 chown root daemon-control chmod 700 daemon-control #创建启动服务连接 ln -s /usr/share/denyhosts/daemon-control /etc/init.d/denyhosts #添加启动项 chkconfig --add denyhosts #配置denyhosts.cfg vi denyhosts.cfg
填充以下内容
SECURE_LOG = /var/log/secure #ssh日志文件 HOSTS_DENY = /etc/hosts.deny #将阻止IP写入到hosts.deny PURGE_DENY = 5m #过多久后清除已经禁止的,其中w代表周,d代表天,h代表小时,s代表秒,m代表分钟 BLOCK_SERVICE = sshd #阻止服务名 DENY_THRESHOLD_INVALID = 5 #允许无效用户(在/etc/passwd未列出)登录失败次数,允许无效用户登录失败的次数. DENY_THRESHOLD_VALID = 5 #允许普通用户登录失败的次数 DENY_THRESHOLD_ROOT = 5 #允许root登录失败的次数 DENY_THRESHOLD_RESTRICTED = 1 #设定 deny host 写入到该资料夹 WORK_DIR = /usr/share/denyhosts/data #将deny的host或ip纪录到Work_dir中 SUSPICIOUS_LOGIN_REPORT_ALLOWED_HOSTS = YES HOSTNAME_LOOKUP=YES #是否做域名反解 LOCK_FILE = /var/lock/subsys/denyhosts #将DenyHOts启动的pid纪录到LOCK_FILE中,已确保服务正确启动,防止同时启动多个服务。 ADMIN_EMAIL = denyhosts@163.com #设置管理员邮件地址 SMTP_HOST = localhost SMTP_PORT = 25 SMTP_FROM = DenyHosts SMTP_SUBJECT = DenyHosts Report AGE_RESET_VALID=1d #有效用户登录失败计数归零的时间 AGE_RESET_ROOT=1d #root用户登录失败计数归零的时间 AGE_RESET_RESTRICTED=5d #用户的失败登录计数重置为0的时间(/usr/share/denyhosts/data/restricted-usernames) AGE_RESET_INVALID=10d #无效用户登录失败计数归零的时间 DAEMON_LOG = /var/log/denyhosts #自己的日志文件 DAEMON_SLEEP = 30s DAEMON_PURGE = 5m #该项与PURGE_DENY 设置成一样,也是清除hosts.deniedssh 用户的时间
如果想删除一个已经禁止的主机IP,并加入到允许主机例表,只在 /etc/hosts.deny 删除是没用的。需要进入 /var/lib/denyhosts 目录,进入以下操作:
1、停止DenyHosts服务:
service denyhosts stop
2、在 /etc/hosts.deny 中删除你想取消的主机IP
3、编辑 DenyHosts 工作目录的所有文件,通过
grep 192.168.1.191 /usr/share/denyhosts/data/*
然后一个个删除文件中你想取消的主机IP所在的行:
* /usr/share/denyhosts/data/hosts
* /usr/share/denyhosts/data/hosts-restricted
* /usr/share/denyhosts/data/hosts-root
* /usr/share/denyhosts/data/hosts-valid
* /usr/share/denyhosts/data/users-hosts
4、添加你想允许的主机IP地址到/var/lib/denyhosts/allowed-hosts
vi /usr/share/denyhosts/data/allowed-hostsps
然后逐行输入你的IP
thinkai.net 192.168.1.*
5、启动DenyHosts服务:
service denyhosts start
报错排查
#service denyhost start
starting DenyHosts: /usr/bin/env python /usr/bin/denyhosts.py –daemon
–config=/usr/share/denyhosts/denyhosts.cfg
python: can't open file '/usr/bin/denyhosts.py': [Errno 2] No such file or
directory
cd /usr/share/denyhosts/ vi daemon-control
DENYHOSTS_BIN = "/usr/bin/denyhosts.py"
改为
DENYHOSTS_BIN = "/usr/local/bin/denyhosts.py"
cd /usr/local/lib/python2.7/site-packages/ cp -rp DenyHosts /usr/lib/python2.4/site-packages/ /etc/init.d/denyhosts restart
vi /etc/passwd
按i键进入编辑状态
修改第1行第1个root为新的用户名
按esc键退出编辑状态,并输入:x保存并退出
vi /etc/shadow
修改第1行第1个root为新的用户名
按esc键退出编辑状态,并输入:x!强制保存并退出
补充:为了正常使用sudo,需要修改/etc/sudoers的设置,修改方法如下:
visudo
找到root ALL=(ALL) ALL
在下面添加一行:新用户名 ALL=(ALL) ALL
:x保存退出
43 queries in 1.414 seconds |