From 01e8b333964b0df20c60156ad8d100d908fffd26 Mon Sep 17 00:00:00 2001 From: colben Date: Sun, 29 Aug 2021 00:02:47 +0800 Subject: [PATCH] first commit --- Linux读取或修改系统时间/Makefile | 25 ++ Linux读取或修改系统时间/demo | Bin 0 -> 7518 bytes Linux读取或修改系统时间/main.c | 54 +++ Linux读取或修改系统时间/main.o | Bin 0 -> 1812 bytes Linux读取或修改系统时间/readme.txt | 1 + gtk透明列表/exe | Bin 0 -> 13175 bytes gtk透明列表/list.c | 142 ++++++++ gtk透明列表/list.h | 30 ++ gtk透明列表/main.c | 46 +++ gtk透明列表/makefile | 39 +++ gtk透明列表/test.glade | 46 +++ music.py | 98 ++++++ python进程池.py | 64 ++++ readme.md | 2 + shell数组实现进程池.sh | 79 +++++ shell有名管道实现进程池.sh | 38 +++ 光标操作/Print_Esc.c | 94 ++++++ 光标操作/Print_Esc.h | 34 ++ 光标操作/console.c | 57 ++++ 光标操作/console.h | 33 ++ 光标操作/cursor_demo/Makefile | 15 + 光标操作/cursor_demo/console.c | 63 ++++ 光标操作/cursor_demo/console.h | 34 ++ 光标操作/cursor_demo/test | Bin 0 -> 7524 bytes 光标操作/cursor_demo/test.c | 14 + 常用函数/ColbenFuns.c | 32 ++ 常用函数/gtk_functions.c | 234 +++++++++++++ 常用函数/netword_functions.c | 114 +++++++ 常用函数/posix定义的取消点1.bmp | Bin 0 -> 763914 bytes 常用函数/posix定义的取消点2.bmp | Bin 0 -> 2284270 bytes 常用函数/sql_functions.c | 67 ++++ 常用函数/sys_functions.c | 205 ++++++++++++ 常用脚本/agent.py | 212 ++++++++++++ 常用脚本/ipflow | 61 ++++ 常用脚本/oracle/oracle_mul.py | 232 +++++++++++++ 常用脚本/oracle/partition_day.py | 305 +++++++++++++++++ 常用脚本/oracle/partition_month.py | 187 +++++++++++ 常用脚本/oracle/partition_year.py | 188 +++++++++++ 常用脚本/oracle/table_partition.cfg | 65 ++++ 常用脚本/oracle/table_partition.py | 177 ++++++++++ 常用脚本/python/msg_log.ini | 18 + 常用脚本/python/rising_log.py | 206 ++++++++++++ 常用脚本/python/rollback_log.cfg | 5 + 常用脚本/python/rollback_log.py | 131 ++++++++ 常用脚本/shell/check_net.sh | 67 ++++ 常用脚本/shell/install.sh | 55 +++ 常用脚本/shell/processes | 19 ++ 常用脚本/shell/rc.all | 180 ++++++++++ 常用脚本/shell/rc.all_mul | 184 ++++++++++ 常用脚本/shell/rc.pwatch | 50 +++ 常用脚本/shell/rc.pwatch_mul | 51 +++ 常用脚本/transfer | 351 ++++++++++++++++++++ 52 files changed, 4404 insertions(+) create mode 100644 Linux读取或修改系统时间/Makefile create mode 100644 Linux读取或修改系统时间/demo create mode 100644 Linux读取或修改系统时间/main.c create mode 100644 Linux读取或修改系统时间/main.o create mode 100644 Linux读取或修改系统时间/readme.txt create mode 100755 gtk透明列表/exe create mode 100644 gtk透明列表/list.c create mode 100644 gtk透明列表/list.h create mode 100644 gtk透明列表/main.c create mode 100644 gtk透明列表/makefile create mode 100644 gtk透明列表/test.glade create mode 100644 music.py create mode 100644 python进程池.py create mode 100644 readme.md create mode 100644 shell数组实现进程池.sh create mode 100644 shell有名管道实现进程池.sh create mode 100644 光标操作/Print_Esc.c create mode 100644 光标操作/Print_Esc.h create mode 100644 光标操作/console.c create mode 100644 光标操作/console.h create mode 100644 光标操作/cursor_demo/Makefile create mode 100644 光标操作/cursor_demo/console.c create mode 100644 光标操作/cursor_demo/console.h create mode 100644 光标操作/cursor_demo/test create mode 100644 光标操作/cursor_demo/test.c create mode 100644 常用函数/ColbenFuns.c create mode 100644 常用函数/gtk_functions.c create mode 100644 常用函数/netword_functions.c create mode 100644 常用函数/posix定义的取消点1.bmp create mode 100644 常用函数/posix定义的取消点2.bmp create mode 100644 常用函数/sql_functions.c create mode 100644 常用函数/sys_functions.c create mode 100755 常用脚本/agent.py create mode 100755 常用脚本/ipflow create mode 100755 常用脚本/oracle/oracle_mul.py create mode 100755 常用脚本/oracle/partition_day.py create mode 100755 常用脚本/oracle/partition_month.py create mode 100755 常用脚本/oracle/partition_year.py create mode 100644 常用脚本/oracle/table_partition.cfg create mode 100755 常用脚本/oracle/table_partition.py create mode 100644 常用脚本/python/msg_log.ini create mode 100755 常用脚本/python/rising_log.py create mode 100644 常用脚本/python/rollback_log.cfg create mode 100755 常用脚本/python/rollback_log.py create mode 100755 常用脚本/shell/check_net.sh create mode 100755 常用脚本/shell/install.sh create mode 100644 常用脚本/shell/processes create mode 100755 常用脚本/shell/rc.all create mode 100755 常用脚本/shell/rc.all_mul create mode 100755 常用脚本/shell/rc.pwatch create mode 100755 常用脚本/shell/rc.pwatch_mul create mode 100755 常用脚本/transfer diff --git a/Linux读取或修改系统时间/Makefile b/Linux读取或修改系统时间/Makefile new file mode 100644 index 0000000..45a6280 --- /dev/null +++ b/Linux读取或修改系统时间/Makefile @@ -0,0 +1,25 @@ +SRC := # +SRC += main.c + +#OBJ := $(subst .c,.o,$(SRC)) +OBJ = $(SRC:%.c=%.o) + +CC = gcc +FLAG = -Wall +OPTION = -lpthread -ldl +EXEC_NAME = demo +EXEC_PATH = . + +.PHONY:clean demo + +demo:$(OBJ) + @echo make ... + $(CC) $^ -o $(EXEC_PATH)/$(EXEC_NAME) $(FLAG) $(OPTION) + @echo make over + @echo Execute target is $(EXEC_PATH)/$(EXEC_NAME) +$(OBJ):%.o:%.c + $(CC) -c -o $@ $< $(FLAG) +clean: + @echo clean ... + rm $(EXEC_PATH)/$(EXEC_NAME) *.o -rf + @echo clean over diff --git a/Linux读取或修改系统时间/demo b/Linux读取或修改系统时间/demo new file mode 100644 index 0000000000000000000000000000000000000000..b95f7031a321ba92cc9b414a3e9749f89e85ca9f GIT binary patch literal 7518 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 literal 0 HcmV?d00001 diff --git a/Linux读取或修改系统时间/main.c b/Linux读取或修改系统时间/main.c new file mode 100644 index 0000000..82e2856 --- /dev/null +++ b/Linux读取或修改系统时间/main.c @@ -0,0 +1,54 @@ +#include +#include +#include + +// 时间结构体 +struct tm *local_time; // time to show or modify + +void settime(int tm_hour, int tm_min, int tm_sec) +{ + struct tm *time_set = NULL; + struct timeval tv; + struct timezone tz; + + /* 获取当前时间 */ + gettimeofday(&tv, &tz); + /* 获取当前时间 */ + time_set = gmtime(&tv.tv_sec); + /* 设置当前时间结构体 */ + time_set->tm_hour = tm_hour; + time_set->tm_min = tm_min; + time_set->tm_sec = tm_sec; + /* 获取用秒表示的时间 */ + tv.tv_sec = mktime(time_set); + /* 设置当前时间 */ + settimeofday(&tv, &tz); +} + +void refresh_clock(void) +{ + time_t timep; + + time(&timep); + local_time = localtime(&timep); // 读取系统时间 + + // 时分秒 + int hour = local_time->tm_hour; + int minute = local_time->tm_min; + int second = local_time->tm_sec; + printf("h = %d, m = %d, s = %d\n", hour, minute, second); + +} + + +int main(int argc, char *argv[]) +{ + + printf("修改前的时间:\n"); + refresh_clock(); + settime(11, 34, 50); + + printf("修改后的时间:\n"); + refresh_clock(); + return 0; +} \ No newline at end of file diff --git a/Linux读取或修改系统时间/main.o b/Linux读取或修改系统时间/main.o new file mode 100644 index 0000000000000000000000000000000000000000..b9e5d9e908a17a0ef0e52870496e8b183fcfe7c8 GIT binary patch literal 1812 zcma)6O=}ZT6un8N8vAAZSO^siQl+AfUsZ}IwAQg8MXC^2LOV^SZD^C!WGX6xNL3t4 z#YItZWpVFHL_ts#DP8yj+_f`4N#M-=U1#=<^KYU(88{2twE|}`bR}$#o2#F2 z76G^eb*nR0Gnc7*4SUQjjxVGjZ!)rq&0xuXC_rl~(Q2+U3Gi*>tK?^3GW$k`(nr(V za=X$6jTMEpGWYWFr>W=j!Q|%$*FW8R`t{zEZ!aDg_0H{Os&sXB9!|Gp`p1g?*q-iu z(JhzKt@a`N!0vrxN<6qDqo!#ruB8&q05O>(sLNNfj5na;f0E{XoAQ;*jym-iYmc7k#mFuJ4N7U#W;) zE`=mpDipjTV#Sj0*_e9U6`Pl48UR%|N4X`o03W7|ApHI1Md&E)@Nc!j(1@?xmy6 z^o{mp=phR54C~>u59_70AFa1oBXS0dQgHJ{J1ZlltUJ={=kcypJYV5ph^2v?dr1ZhN-GRUQ^HW$ z8z_5~q24TN42z1ZYRVfe=ZpS;>LR0KeueFMCUFeZb|MCW-;;QQNS4?ra)F4=Tq9!8 zZUSQ%mI;k_HBM`MO~j*{0mj#hyx05#IX;LViEBkT9PwIw8!$A?uLClkA|jq<9CO^R Hu}|YKRsu1) literal 0 HcmV?d00001 diff --git a/Linux读取或修改系统时间/readme.txt b/Linux读取或修改系统时间/readme.txt new file mode 100644 index 0000000..8392613 --- /dev/null +++ b/Linux读取或修改系统时间/readme.txt @@ -0,0 +1 @@ +޸ϵͳʱҪrootȨޣsudoг \ No newline at end of file diff --git a/gtk透明列表/exe b/gtk透明列表/exe new file mode 100755 index 0000000000000000000000000000000000000000..94315ae9185dc9b70441b811a94bd9758121b7f4 GIT binary patch literal 13175 zcmeHNeRxz=dOwp4IA{m~DH|o~ph3aHm{9aVrMn4X_!1#PK>DzFnateeMkX_HJ|J;X zp##b|rlq>8((VUTYwfOEsqW*luFp0Q1hLk#+O>XkHH(o>N?KvfB332+{m!{3b94E4 z?BCs!=j6S=^SXl^=bkzDy)U?Up2y=6Iu(gxK~$CV`euTzx>9jw3cna7rijbM zL@^RYe8n zS@UlLAMlJs{b*h+1K(*M`_9bzAmX}cOXGFX$nt zIWp^xN9Nd(U;5KW9{$&g3!eYRk*OCi%yyUFam&xfk#`j``_FpYd{=rzZ_Ox{O-7!I zJSX_8{-1yN@Wy9u`LJtG=ZVs{?^;#y%S8(}9eeZRQm}`mS{h@gai9k^0409V#rL{! zH4U*7<$vVDk7_0;`SV|9~}$R0c2oci`DW_!6-V_@&3ZKKkxhF-Cj~?GJ2I^5eus;_$Hgmx#~7 zKmMTRV|{}EBx@nGvBIfiNfhw+>D$yKSXN2R?c*1B4C6cBvjONyO%t)p} ziIiaoW6^qJnc3WuOqq$gXegO9lcG7b&WMH@&8QJGH#ktzOc^P&Jtd2pTH4Ks(afTb zHmF_LaH|n96Sk^`TkE3nnAs3&jG9tB9FL_!Eip6Us&dW>%77vLv?<zhjVAP#(rqa#VTK~g)qul%x&hv>6do3VHR+@o5$H}*KrR}MhecbW zC6;OuVTBBXwQP5kBiEEL;ZCNUOT%bPCKVG!v51(zc;TEn1I|s4FC;7jM;eaQZcnx@ z*OVomp+CM^_;)YZe9thIwX}?;)Nkx6Up(vejr0pqvfJys0Bf;~6uj}Ic)665Vlh{c z;$`e7#fzqr^a3HKkYcq?BOQe^0_lY~2asMQ#4OSh>=C4BxrP+WdM@c0Ar_FrxW%Mn zg{UXRM%O@!m)|PVKft@5bb=6TNxvpUgcL7HixlteDCwm_w2@8}B1MYxLp$kZLTn_R zBE%+AoD;T?qTky{uM}c=rr(zjqvM;qi?0zPm-%9FaByo^YDE4tMkTY~x4N6dC)42d zUep?#?8AQ+3{K|gS$yp4LAAlj97T(~zQYo8G%Zd+UzfxjRg16qzTFaYbS*#ePKi0n z7OWM0+a<0frib)xl6VU7EaEnaIr>%&@mh&F3)TYSdWkt3Ry}cz#GDmt6>*isoE>W| zv0q}&lEn`7l}S98xQ$pyynwi!`1olQOy=xan}~ZP<}6yR8YBR6=u*)aj%JGmnJQKrBAptq8| z!NZ5TJ6|Ac522Lbd#WhAZ|{Fz;W_-vQ)y54i?ZSyx?*;2rB_#e<4||@Wamq8ZLEPm zmT&O%#Ztd7zY$Y-U#fW`hz%gyogcs&%B>j4EgMfuvg0fBMHsE@H}MRiNAYaSFQvRP_7sLLKM`YQ zv%XPa`5y<1NQ&?V)f*hV%=QCA44dpzMvtF4^vAId?JC0)v>#b7trm@~% zpdQQCI&}S5>8fIRv!nbws(dEeoCzDsz%QYZpuQ=Jdg+6h(k}EhKLgt{X!$v|{Qdv=sx5C(HqwZr=qmaHBhK0G6IHNIn)t*_Jng{*D5qVC^;9K? zWMCILu=l-SuhRDZ-d(JwirA?m=+qI}DRigjy*23CkzBC%33feqz5I`5xyqk!W;eJP zD>$rNjOouXr71Oaa`5bh*@|*$O=f@9>O15@qe*^c5|&u5-pl_rC1ajF%m*$ziT2*O z@19YzOIy3zOAd};^VEE-?tHagku^N8+_>-Fi3K?^71N>A?mM$LJ7DAR-u&&Uv-jo) zD7Sm#cl4%)jw)A`w~`~De}MIac@}d=fZx&bd>f0EV@S_iF+R)Q=W{Dcvi0aV9?G)y zCGw#>TR%SkF)F~NvUAGwUj0~+3yvT2ES#K*ay1onSt@8yJKgO8*)qdKHh4@o)eRspzctfM&}S7{8TVKG#(0sq!dOvU8*})KqTmk{j;; zH;TVOD{^P+`(UVEZbk3jBSoDRP}$q575cbyag6>5Mr4as3rg}Fd)l>7?G~fs4fi82 z)M1gr(|WT9T;k>VCUUXYE%R${N&ODZpJfBs2+2&a7h~bFd2830t#8VAb3U`b#<80G z2ZMPI)-iax55t9a&~4q#*U(NTn1?=JPTU;K-}f$_4pJVYOL30He?Z8+_&ym>i_e#> zuXN3ykK(G)zU$@uLARVgALox?Xt*8oS1Sj>C+CkXJLm5ssN93z4fYk;3Ux>1{N;xf zmgtTpX&>fqc$d%ePP!ASDYgI`g)hf_LsnUn-}_;a=WRH{;!2-(v9Cj^pN1iseVLDxt6oy@_!k0EWah{jH$%BPz zQy&!bO}|ycwg`iP!7HPKzM31S7eh1H^usvE5-*{I-T z+p7mxF3(R!>zlh@F2~Qs{)$|*va0j>UW{da*9q)CnI1e&J+Sw5(bkixYt%VD$FtM4 zN?5>iCeM7{!EgVZf|-M!8$V5dklA0c`VM1F_p#C2o#_+&6qUbMpNA2fyO*;?{y@cf z5Wn_|L|r`EXvV~H%Zx@l#PU#+i3ViK1q)C(f zx0{8uP;n)8DF$Nw$T;CX9m>vhT~m zzdaF;HTx6s4Mr^8s%?Zlo{7abZvw^DhUooxaPYgJC*WFLpm$=r_{PbB^4|P9>gp9tYiqlYJSkC>{Z=0{v&ude8yTHqZz>=NVA> zT0}dZyO#;iMxSS5iPyUg_5CR0XO$Y*MLnX_H?Op0(U^-;-gfbgOK-k*M&*^1sX?9! zn>#>7ZK-c-(VWpE=4OhE+PZ6BhA!&h;NJ_GNluwH&e^+|EBWJG>n(at z4hH$#!EeKF16+p{+MTb)iu~Q+uLl1nCx3l`e;E8U_>-J`d#q=n>^S%v!4D1bYfDQW zD6T6lyWd+|IzBUENoiHlg3|G|-KAx<2TDt750?6BUoQ3X7wk0n!EV&0JN!QVegyts zi~#N_dhjiqeZ|rl$`JtK8Y~9V2Ajrg%6oMFV&eBKTxHAeRJeMU-=uNnEWg*{3R?8y zl8oybTcP;f>B0Cj_}`HYunEXlBj12L4|yeW6Y_fG`;i|-ehT>oGXeQ(dycd%UzK*@4)GxJ>&R~*zl;1nvaYZBy)OPS;1kGBz8kys&9AGw$v*^f`)3Ab1!hdIzA-If^;A_LL?GGGnhG_7rV@%;`Uzi-%tV_A;DllZYUeDRo(eVF zs5zDnG^Se+G|&ILLS z&w%{q6-dP8m#Khh8BK{$t7%vf)YM4TFhYq$s6)sa`uWZ<#GpLX+7d>?aVW>XfNVu+ z#HTJ12*+Dn@tsf){#T$}OY~u`0U0j>;EW3(kLfC8-1JI08P@@ZA6O@@KPH|rwcIwW zJ)VVlZqP}~%|!u@2XVH`HTw+YYVgdp%S1WmCCFU2l;c|Nhuls8u5CO@8LsJ-$Xw5q ztm&s^)TLC%k7XS;ynZe)ClQ}#iw zA98elt&e>m&LC?!?kxixBp5|G?sHo1Ayq8f;odiZ${c&0D97{wGW$e({MZNlP%h7z zz)Tzy%07&&)-vQ<)6pfvJ$@(9H|HWVF z_Qr}6z|Q^x4kgNSz3K7yVEnm;bblCa^)+B^Kk>C}&>nve=A#C96!zCiC?1FYE~7m7 zi-E@?7HkzTFYx($o%}n2b)t8)1MB%??AU!S{=>j}zWv~T57-$?#`m#K)c2wb|H_4X zUHBw0-wzy5#-@D<%+D6Qf1tgkSi<~f&pQj^i-G^;QLm4`%ZaB0KWUH0*rIZA6YzA% zci8+}fcHb5X9LPdfOVq1-(r2V&oaigZ3bQo|D!$Qibe~@?(rMyB*`CrM(pIzz%PY< z-ZN1D8^AhI{}C5H?ZRb_O^@US z>Ywex^)B4#!s~(g>51!@?PY;=f6B1FzvGhsp$ot0!mk1|lq6*9dl#5N1~ifO$2*VmGhBGF1G7C5PNb5lbW>9xjG)U!b<2#! z3zs(_FykZ{9j9V29Yux_i5tz)cq1YlBdK^IX@t`40zVMiqGrmB1a7$g z#wut&i;xV@Q$IWqHJ3_s2=!AXl5TD7Kotj)VT;2=8H5LuqX-EFQP;yAr0ZMa>7>yi z!s$eUp^VftZ&~fFK_j?iE<;IWC++9Cf3l?Z)`fK_!3LwDcFy9UA;K~Y6;>duR0S*Ix05*o!-w&(Z>rT5_3)rgJ9MxR#5xp1%AZ*} zm~eQ2B862ztBlq>e*~!#l<|@(h_R-o5SC~(wHek1W#q7{bq0kNx+FtTaixx+Rr%u* z)0m7KRwx!hyex;_NGfh4FYM1+4>##De6tY1I@D1Wo@p5Evu+5muq|w)taNN$ps`(F z`zK7qStcz+U)r&wg@E5eYYh0c?U1dxLWwzQc08$+bcdrBER&(NXN}f9BmQ&PU@HG8 zOl2Vg`D~H74tuoAuxNPTZJ~Ge5IACB3j-*B_ZtSnn6-1CBTjlKWYuYR!C0y{|hc7a)l~t5u>DXUAvIta`(ZMQi*4>OdCR(nJ;U8<9L9~t`I%{0842x#CuCpC` tj>5_G@F3?xsIeNZ^MrsqRLE--F6C+r!|+&iD$pC@un2NHcGzju{{s8K`dt73 literal 0 HcmV?d00001 diff --git a/gtk透明列表/list.c b/gtk透明列表/list.c new file mode 100644 index 0000000..97a43a0 --- /dev/null +++ b/gtk透明列表/list.c @@ -0,0 +1,142 @@ +#include +#include +#include "list.h" + +//列表滑动、选中控制/*{{{*/ +static int press_y,previous_y,current_y; //滑动控制变量 +gboolean deal_press_event(GtkWidget *widget,GdkEventButton *event,gpointer data) //按下 +{ + GdkColor color; + LIST *list=(LIST *)data; + if(GDK_2BUTTON_PRESS == event->type) //双击选中 + { + gdk_color_parse(NORMAL_COLOR, &color); + gtk_widget_modify_fg(list->label[list->tab_select], GTK_STATE_NORMAL, &color); + list->tab_select=(int)(event->y-current_y)/(list->tab_height); + gdk_color_parse(HIGH_COLOR, &color); + gtk_widget_modify_fg(list->label[list->tab_select], GTK_STATE_NORMAL, &color); + list_select_back(list); //双击事件回调,由外部实现 + } + press_y=event->y; + previous_y=current_y; + return TRUE; +} + +gboolean deal_motion_event(GtkWidget *widget,GdkEventMotion *event,gpointer data) //拖动 +{ + LIST *list=(LIST *)data; + current_y=previous_y+event->y-press_y; + gtk_fixed_move(GTK_FIXED(list->fixed_bottom),list->fixed_top,0,current_y); + return TRUE; +} + +gboolean deal_release_event(GtkWidget *widget,GdkEventButton *event,gpointer data) //释放 +{ + LIST *list=(LIST *)data; + if((list->tab_show*list->tab_height >= (list->total)*(list->tab_height)) || (current_y >=0)) + current_y=0; + else if(list->tab_show*list->tab_height > current_y+(list->total)*(list->tab_height)) + current_y=list->tab_show*list->tab_height-(list->total)*(list->tab_height); + else; + gtk_fixed_move(GTK_FIXED(list->fixed_bottom),list->fixed_top,0,current_y); + return TRUE; +}/*}}}*/ + +LIST *cgtk_list_new(char **name,int width,int height,int show,gpointer data) //创建列表/*{{{*/ +{ + int i; + GdkColor color; + LIST *list=(LIST *)calloc(1,sizeof(LIST)); //分配列表空间 + list->label=(GtkWidget **)calloc(0,sizeof(GtkWidget *)); //分配列表行空间,初始为0 + list->tab_show=show; + list->tab_width=width; + list->tab_height=height; + list->out=data; + list->event_box=gtk_event_box_new(); + gtk_widget_set_size_request(list->fixed_bottom,width,show*height); + list->fixed_bottom=gtk_fixed_new(); + gtk_widget_set_size_request(list->fixed_bottom,width,show*height); + list->fixed_top=gtk_fixed_new(); + //gtk_widget_set_size_request(list->fixed_bottom,width,show*height); + gtk_container_add(GTK_CONTAINER(list->event_box),list->fixed_bottom); + gtk_fixed_put(GTK_FIXED(list->fixed_bottom),list->fixed_top,0,0); + + g_signal_connect(GTK_OBJECT(list->event_box), "button_press_event", G_CALLBACK(deal_press_event),list); + g_signal_connect(GTK_OBJECT(list->event_box), "motion_notify_event", G_CALLBACK(deal_motion_event),list); + g_signal_connect(GTK_OBJECT(list->event_box), "button_release_event", G_CALLBACK(deal_release_event),list); + + gdk_color_parse(NORMAL_COLOR, &color); + for(i=0;NULL != name[i];i++) + { + if(NULL == (list->label=realloc(list->label,(++(list->total))*sizeof(GtkWidget *)))) + { + printf("\n>>>Can not get more memory space!!!<<<\n"); + return NULL; + } + list->label[i]=gtk_label_new(name[i]); + gtk_widget_modify_fg(list->label[i], GTK_STATE_NORMAL, &color); + gtk_widget_set_size_request(list->label[i],width,height); + gtk_fixed_put(GTK_FIXED(list->fixed_top),list->label[i],0,height*i); + } + return list; +}/*}}}*/ + +int cgtk_list_refresh(LIST *list,char **name) //刷新列表/*{{{*/ +{ + int i; + GdkColor color; + for(i=0;itotal;i++) + gtk_widget_destroy(list->label[i]); + list->total=0; + free(list->label); + list->label=(GtkWidget **)calloc(0,sizeof(GtkWidget *)); //分配列表行空间,初始为0 + gdk_color_parse(NORMAL_COLOR, &color); + for(i=0;NULL != name[i];i++) + { + if(NULL == (list->label=realloc(list->label,(++(list->total))*sizeof(GtkWidget *)))) + { + printf("\n>>>Can not get more memory space!!!<<<\n"); + return -2; + } + list->label[i]=gtk_label_new(name[i]); + gtk_widget_modify_fg(list->label[i], GTK_STATE_NORMAL, &color); + gtk_widget_set_size_request(list->label[i],list->tab_width,list->tab_height); + gtk_fixed_put(GTK_FIXED(list->fixed_top),list->label[i],0,list->tab_height*i); + gtk_widget_show(list->label[i]); + } + return 0; +}/*}}}*/ + +int cgtk_list_set_select_num(LIST *list,int row_num) //修改选中行行号/*{{{*/ +{ + if(0>row_num || list->total<=row_num) + { + printf("\n>>>Set Wrong row_num !!! <<<\n"); + return -1; + } + GdkColor color; + gdk_color_parse(NORMAL_COLOR, &color); + gtk_widget_modify_fg(list->label[list->tab_select], GTK_STATE_NORMAL, &color); + list->tab_select=row_num; + gdk_color_parse(HIGH_COLOR, &color); + gtk_widget_modify_fg(list->label[list->tab_select], GTK_STATE_NORMAL, &color); + return 0; +}/*}}}*/ + +int cgtk_list_get_select_num(LIST *list) //获取选中行行号/*{{{*/ +{ + return list->tab_select; +}/*}}}*/ + +char *cgtk_list_get_select_text(LIST *list) //获取选中行文本/*{{{*/ +{ + char *text=(char *)gtk_label_get_text(GTK_LABEL(list->label[list->tab_select])); + return text; +}/*}}}*/ + +void cgtk_list_destroy(LIST *list) //释放列表占用的空间/*{{{*/ +{ + free(list->label); + free(list); +}/*}}}*/ + diff --git a/gtk透明列表/list.h b/gtk透明列表/list.h new file mode 100644 index 0000000..d4752cb --- /dev/null +++ b/gtk透明列表/list.h @@ -0,0 +1,30 @@ +#ifndef __COLBEN_LIST__ +#define __COLBEN_LIST__ + +#include +#define NORMAL_COLOR "black" //非选中颜色 +#define HIGH_COLOR "white" //选中颜色 + +typedef struct //list句柄 +{ + gint total; //标签总数量 + gint tab_show; //标签显示数量 + gint tab_width; //标签宽度 + gint tab_height; //标签高度 + gint tab_select; //当前选中标签 + gpointer out; //双击事件回调参数 + GtkWidget *event_box; //底层事件盒子,需手动添加到自定义布局中 + GtkWidget *fixed_bottom; //中层固定布局 + GtkWidget *fixed_top; //上层固定布局 + GtkWidget **label; //每一行的信息 +}LIST; + +extern LIST *cgtk_list_new(char **,int,int,int,gpointer); //创建列表,需指定指针数组,列表宽度,单行高度,双击回调参数指针 +extern int cgtk_list_refresh(LIST *,char **); //刷新列表,需指定列表和新指针数组,双击回调参数指针 +extern int cgtk_list_set_select_num(LIST *,int); //设置选中行号 +extern int cgtk_list_get_select_num(LIST *); //获取选中行号 +extern char *cgtk_list_get_select_text(LIST *); //获取选中行文本 +extern void cgtk_list_destroy(LIST *); //释放列表内存空间 +extern void list_select_back(gpointer); //双击事件回调,需外部实现 + +#endif diff --git a/gtk透明列表/main.c b/gtk透明列表/main.c new file mode 100644 index 0000000..e44a3f3 --- /dev/null +++ b/gtk透明列表/main.c @@ -0,0 +1,46 @@ +#include +#include +#include "list.h" + +char *name1[]={"Colben","Shelly","Saferin","Ada","Obo","Kathy",NULL}; //之前 +char *name2[]={"Colben","Shelly","Bather","Ada","Obo","Kathy","Jathy","Rassol","Colben","Shelly","Bather","Rassol","Colben","Shelly","Bather","Ada","Obo","Kathy",NULL}; //之后 + +void list_select_back(gpointer data) //双击选中回调 +{ + LIST *list=(LIST *)data; + gtk_label_set_text(GTK_LABEL(list->out),cgtk_list_get_select_text(list)); + printf("\n>>>>>>----------%d----------<<<<<<\n",cgtk_list_get_select_num(list)); + printf("\n>>>>>>----------%s----------<<<<<<\n",cgtk_list_get_select_text(list)); +} + +void button_refresh_list(GtkWidget *widget,gpointer data) //按钮单击回调 +{ + LIST *list=(LIST *)data; + cgtk_list_refresh(list,name2); +} + +int main(int argc,char *argv[]) +{ + gtk_init(&argc,&argv); + GladeXML *gxml=glade_xml_new("test.glade",NULL,NULL); + GtkWidget *main_window=glade_xml_get_widget(gxml,"window1"); + g_signal_connect(main_window,"destroy",G_CALLBACK(gtk_main_quit),NULL); + + GtkWidget *fixed=glade_xml_get_widget(gxml,"fixed1"); + GtkWidget *label=glade_xml_get_widget(gxml,"label1"); + + LIST *list=cgtk_list_new(name1,240,40,8,label); //创建列表,指针即可,无需分配空间 + if(NULL == list) + { + printf("\n>>>>>> !!! Memory not enough !!! <<<<<<\n"); + return -1; + } + gtk_fixed_put(GTK_FIXED(fixed),list->event_box,500,80); //把列表添加到主窗口的固定布局中 + + GtkWidget *button=glade_xml_get_widget(gxml,"button1"); + g_signal_connect(button,"clicked",G_CALLBACK(button_refresh_list),list); //按钮信号注册 + + gtk_widget_show_all(main_window); + gtk_main(); + return 0; +} diff --git a/gtk透明列表/makefile b/gtk透明列表/makefile new file mode 100644 index 0000000..6764519 --- /dev/null +++ b/gtk透明列表/makefile @@ -0,0 +1,39 @@ +#============================================== +# 文件名:makefile +# 作者: 巴拉克-侯赛因-奥巴马 +# 创建时间:2014-05-23 00:21:34 +# 地址: 美国华盛顿市区中心宾西法尼亚大街1600号 +#============================================== + +cc=gcc + +target=exe + +object_h=list.h + +object_o=main.o list.o + +flags=`pkg-config --cflags --libs gtk+-2.0 libglade-2.0` + +$(target): $(object_o) + @$(cc) -o $@ $^ $(flags) + @echo "成功生成可执行文件: $@ !!" + @echo '^_^ ^_^ ^_^' + +%.o: %.c $(object_h) + @$(cc) -o $@ -c $< $(flags) + @echo '^_^' + @echo "成功编译 $< 生成 $@ 文件!!" + +clean: + @rm -rf $(object_o) + @echo '^_^' + @echo "成功删除所有目标文件!!" + @echo '^_^' + +clear: + @rm -rf $(object_o) $(target) + @echo '^_^' + @echo "成功删除所有非源码文件!!" + @echo '^_^' + diff --git a/gtk透明列表/test.glade b/gtk透明列表/test.glade new file mode 100644 index 0000000..7631f9c --- /dev/null +++ b/gtk透明列表/test.glade @@ -0,0 +1,46 @@ + + + + + + 800 + 480 + False + False + center-always + + + True + False + + + Refresh + 100 + 80 + True + True + True + False + + + 76 + 295 + + + + + 100 + 80 + True + False + label + + + 87 + 74 + + + + + + diff --git a/music.py b/music.py new file mode 100644 index 0000000..8cabdb6 --- /dev/null +++ b/music.py @@ -0,0 +1,98 @@ +#!/usr/bin/python +# -*- encoding:utf-8 -*- +#========================================= +# Filename : music.py +# Filetype : Python +# Author : Colben +# Create : 2015-08-04 20:50:17 +#========================================= + +import sys, os, time, subprocess, re, chardet, urllib2, json, threading + +def load_lrc(lrc_basename): + try: + lrc_contains = open(lrc_basename+'.lrc', 'rb').read() + except: + print '\033[4;0H\033[K\t Local lrc not found, checking internet ...' + try: + lrc_contains = urllib2.urlopen(json.loads(urllib2.urlopen('http://geci.me/api/lyric/'+os.path.split(lrc_basename)[1]).read())['result'][0]['lrc']).read() + except Exception, e: + print '\033[4;0H\033[K\t Lrc not found ...' + return + try: + lrc_fp.close() + except: + pass + encoding = chardet.detect(lrc_contains)['encoding'] + if 'utf-8' != encoding: + lrc_contains = lrc_contains.decode(encoding).encode('utf-8') + for eachline in re.split(r'\n', lrc_contains): + line = re.split(r']', eachline) + if 1 < len(line): + for tm in line[0:-1]: + try: + time = re.match(r'(\d\d)\s*:\s*(\d\d)',tm.strip(' [')).groups() + pos = 60*int(time[0]) + int(time[1]) + lrc[pos] = line[-1] + except Exception, e: + pass + return + +def main(song): + global lrc + lrc = {} + print '\033[2J\033[2;0H\tPlaying %s ...'%song[:60] + try: + p = subprocess.Popen('mplayer %s 2>&1'%song, stdout = subprocess.PIPE, shell = True) + except Exception, e: + print '\033[9;0H\t%s'%e + p.kill() + return 1 + + while True: + match = re.match(r'A:.*[\d:.()]* of (\d+)', p.stdout.read(30)) + if None != p.poll(): + print '\033[9;0H\tFailed to recognize file format .' + return 1 + if not match: + output = p.stdout.readline() + else: + tot_time = int(match.group(1)) - 1 + for jump in range(1, 10): + if 70 >= tot_time/jump: + break + #print '\033[15;0H\ttotal time: %d'%tot_time + break + print '\033[?25l' + thread_load_lrc = threading.Thread(target = load_lrc, args = (os.path.splitext(song)[0], )) + thread_load_lrc.start() + while True: + cur_char = p.stdout.read(1) + if 'A' == cur_char: + try: + cur_time = int(p.stdout.read(5)[1:]) + print '\033[6;0H\033[K\tCurrent %d / Total %d'%(cur_time, tot_time) + print '\033[1;0H', '-'*(tot_time/jump) + print '\033[1;0H', '='*(cur_time/jump) + print '\033[7;0H', '-'*(tot_time/jump) + print '\033[7;0H', '='*(cur_time/jump) + if tot_time <= cur_time: + print '\033[8;0H\033[K\tquit' + break + print '\033[4;0H\033[K\t%s'%lrc[cur_time] + except Exception, e: + #print '\033[17;0H\tERROR:', e + pass + elif 'E' == cur_char: + print '\033[8;0H\033[K\tquit' + break + + p.wait() + print '\033[10;0H\033[?25h' + return 0 + +if '__main__' == __name__: + if 2 != len(sys.argv) or not os.path.isfile(sys.argv[1]): + print '\nUsage:', sys.argv[0], '{exist music filename}\n' + else: + main(sys.argv[1]) diff --git a/python进程池.py b/python进程池.py new file mode 100644 index 0000000..045fd43 --- /dev/null +++ b/python进程池.py @@ -0,0 +1,64 @@ +#!/usr/bin/python2 +# -*- coding:utf-8 -*- +#========================================= +# Filename : process_pool.py +# Author : Colben +# Create : 2018-06-25 16:09 +#========================================= + +from multiprocessing import Process + +# 进程池容量,即同时运行的最多任务数量 +POOL_SIZE = 10 + +# 初始化任务列表,这里用字典存储,key是任务,value是子进程 +PROCESS_LIST = {} + +# 执行一个任务 +def exec_task(): + #print task, '\033[32mbegan ...\033[0m' + pass + +# 检查任务列表情况 +# empty = False 用于查看列表是否已满(达到10个) +# empty = True 用于查看列表是否已空(0个) +def check_pool_state(empty=False): + while True: + print "\033[2J\033[0;0H" + for task, process in PROCESS_LIST.items(): + if process.is_alive(): + print 'Handling', task, '...' + else: + #print task, '\033[32mfinished\033[0m' + PROCESS_LIST.pop(task) + if not empty and POOL_SIZE > len(PROCESS_LIST): break + if empty and 0 == len(PROCESS_LIST):break + sleep(0.5) + return + +# 批量启动任务 +def start_process_pool(tasks): + for task in tasks: + sub_process = Process(target=exec_task, args=(task,)) + # 启动子进程 + sub_process.start() + # 记录子进程信息到任务列表 + PROCESS_LIST[task] = sub_process + # 查看列表是否已满 + check_pool_state() + # 查看列表是否已空 + check_pool_state(empty=True) + return + +# 测试开始 -------- +def main(): + tasks = [6,7,8,9] + # 重写上面的 exec_task 函数,实现阶乘 + start_process_pool(tasks) + return + +if '__main__' == __name__: + main() +# 测试结束 -------- + + diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..31707f6 --- /dev/null +++ b/readme.md @@ -0,0 +1,2 @@ +# 记录常用的代码片段 + diff --git a/shell数组实现进程池.sh b/shell数组实现进程池.sh new file mode 100644 index 0000000..b5ab6ea --- /dev/null +++ b/shell数组实现进程池.sh @@ -0,0 +1,79 @@ +#!/bin/bash +#========================================= +# Filename : process_pool.sh +# Author : Colben +# Create : 2018-06-16 11:56 +#========================================= + +#set -euo pipefail +export LANG=en_US.UTF-8 +#[ 0 = $UID ] || exit 1 +mkdir -p /tmp/agent/results || exit 1 +cd /tmp/agent && rm -f results/* || exit 1 +# 进程池容量 +readonly POOL_SIZE=4 +# 进程池数组,存储子进程 pid +POOL=() + +# 功能: 显示执行结果 +function ShowResult { + local status= + cd results + for task in $(ls); do + status=$(sed -n '$p' $task) + if [ 0 -eq $status ]; then + echo -en "$task > \033[32;1mNORMAL\033[0m > " + else + echo -en "$task > \033[31;1mERROR\033[0m > " + fi + sed -n -e '$d' -e '1,$p' $task | tr '\n' ' ' + echo -e "\033[0m" + done +} + +# 功能: 执行一个任务 +# 根据业务需求自己实现 +function ExecTask { + # for 循环模拟一次任务 + for n in $(seq 1 $1); do + echo 'a' + sleep 1 + done &>> results/$1 #记录输出结果 + # 记录命令返回码 + echo $? >> results/$1 +} + +# 功能: 检查进程池状 +# 参数: 一个非负整数 +# 参数为 0 时检查进程池是否为空 +# 参数为正整数是检查进程池是否已满 +function CheckPool { + while :; do + clear + for pid in ${!POOL[@]}; do + if [ -d /proc/$pid ]; then + echo "Handling ${POOL[$pid]} ..." + else + #echo "Finished ${POOL[$pid]}" + unset POOL[$pid] + fi + done + if [ 0 -eq $1 ]; then + [ 0 -eq ${#POOL[@]} ] && break + else + [ $POOL_SIZE -gt ${#POOL[@]} ] && break + fi + sleep 0.5 + done +} + +# 测试开始 +for task in $(seq 11 18); do # 这里的多任务用几个整数模拟 + CheckPool $POOL_SIZE # 检查进程池是否已满 + ExecTask $task & # 后台启动任务 + POOL[$!]="$task" # 记录任务 pid 到进程池 +done +CheckPool 0 # 检查进程池是否已空 +ShowResult +# 测试结束 + diff --git a/shell有名管道实现进程池.sh b/shell有名管道实现进程池.sh new file mode 100644 index 0000000..2ebf269 --- /dev/null +++ b/shell有名管道实现进程池.sh @@ -0,0 +1,38 @@ +#!/bin/bash +#========================================= +# Filename : process_pool.sh +# Author : Colben +# Create : 2018-12-14 19:04 +#========================================= + +#set -euo pipefail +export LANG=en_US.UTF-8 +#[ 0 = $UID ] || exit 1 +# 创建有名管道,模拟 go 的有缓存 channal +rm -rf pool.pipe && mkfifo pool.pipe || exit 1 +exec 1022<> pool.pipe && rm -f pool.pipe + +# 初始向有名管道写入10个字符 +printf "%10s" '' >&1022 + +# 功能: 执行一个任务 +# 根据业务需求自己实现 +function ExecTask { + local ts=1 + let "ts=$1%4" + sleep $ts +} + +# 测试开始 +for task in $(seq 11 88); do # 这里的多任务用几个整数模拟 + read -n1 -u1022 # 每次执行任务前读出一个字符 + ( + ExecTask $task + echo -n '.' + echo >&1022 # 每次执行任务后再写入一个字符 + ) & # 后台启动任务 +done +wait +echo +# 测试结束 + diff --git a/光标操作/Print_Esc.c b/光标操作/Print_Esc.c new file mode 100644 index 0000000..86f0bf4 --- /dev/null +++ b/光标操作/Print_Esc.c @@ -0,0 +1,94 @@ +#include "Print_Esc.h" + +// +void clear_screen(void) +{// ESC[2J + printf("\033[2J"); + fflush(stdout); +} + +//ӹλõĩ +void clear_to_end(void) +{// ESC[K + printf("\033[K"); + fflush(stdout); + +} //ƶ(x,y) + +void cusor_moveto(int x, int y) +{// ESC[y;xH + printf("\033[%d;%dH",y,x); + fflush(stdout); +} + +//λ +void cusor_get_pos(void) +{// ESC[s + printf("\033[s"); + fflush(stdout); +} + +//ָλ +void cusor_set_pos(void) +{// ESC[u + printf("\033[u"); + fflush(stdout); +} + +//num +void cusor_up(int num) +{ + while(num--) + { // up = ESC[A + printf("\033[A"); + } + fflush(stdout); +} + +//num +void cusor_down(int num) +{ + while(num--) + {// down = ESC[B + printf("\033[B"); + } + fflush(stdout); +} + +//numַ +void cusor_lift(int num) +{ + while(num--) + {// lift = ESC[D + printf("\033[D"); + } + fflush(stdout); +} + +//numַ +void cusor_right(int num) +{ + while(num--) + { // right = ESC[C + printf("\033[C"); + } + fflush(stdout); +} + +//ǰɫ +void set_fg_color(int color) +{// ESC[#m + printf("\033[%dm",color); + fflush(stdout); +} + +//ñɫ +void set_bg_color(int color) +{// ESC[#m + printf("\033[%dm",(color+10)); + fflush(stdout); +} + + + + diff --git a/光标操作/Print_Esc.h b/光标操作/Print_Esc.h new file mode 100644 index 0000000..a366cea --- /dev/null +++ b/光标操作/Print_Esc.h @@ -0,0 +1,34 @@ +#include +#include + +#define COLOR_RED 31 +#define COLOR_BLACK 30 +#define COLOR_GREEN 32 +#define COLOR_BLUE 34 +#define COLOR_YELLOW 33 +#define COLOR_WHITE 37 +#define COLOR_CYAN 36 +#define COLOR_MAGENTA 35 + +// +void clear_screen(void); +//ӹλõĩ +void clear_to_end(void); +//ƶ(x,y) +void cusor_moveto(int x, int y); +//λ +void cusor_get_pos(void); +//ָλ +void cusor_set_pos(void); +//num +void cusor_up(int num); +//num +void cusor_down(int num); +//numַ +void cusor_lift(int num); +//numַ +void cusor_right(int num); +//ǰɫ +void set_fg_color(int color); +//ñɫ +void set_bg_color(int color); diff --git a/光标操作/console.c b/光标操作/console.c new file mode 100644 index 0000000..1973344 --- /dev/null +++ b/光标操作/console.c @@ -0,0 +1,57 @@ +#include +#include +#include "console.h" + +void cusor_moveto(int x, int y) +{// ESC[y;xH + printf("\033[%d;%dH",y,x); + fflush(stdout); +} + +//保存光标位置 +void cusor_get_pos(void) +{// ESC[s + printf("\033[s"); + fflush(stdout); +} + +//恢复光标位置 +void cusor_set_pos(void) +{// ESC[u + printf("\033[u"); + fflush(stdout); +} +void cusor_hide(void) +{ + printf("\033[?25l"); +} +//清屏 +void clear_screen(void) +{// ESC[2J + printf("\033[2J"); + fflush(stdout); +} + +/* +COLOR_RED 红 +COLOR_BLACK 黑 +COLOR_GREEN 绿 +COLOR_BLUE 蓝 +COLOR_YELLOW 黄 +COLOR_WHITE 白 +COLOR_CYAN 青 +COLOR_MAGENTA 洋红 +*/ +//设置前景颜色 +void set_fg_color(int color) +{// ESC[#m + printf("\033[%dm",color); + fflush(stdout); +} + +//设置背景颜色 +void set_bg_color(int color) +{// ESC[#m + printf("\033[%dm",(color+10)); + fflush(stdout); +} \ No newline at end of file diff --git a/光标操作/console.h b/光标操作/console.h new file mode 100644 index 0000000..5ee248c --- /dev/null +++ b/光标操作/console.h @@ -0,0 +1,33 @@ +#ifndef _CONSOLE_H_ +#define _CONSOLE_H_ + +#define COLOR_RED 31 +#define COLOR_BLACK 30 +#define COLOR_GREEN 32 +#define COLOR_BLUE 34 +#define COLOR_YELLOW 33 +#define COLOR_WHITE 37 +#define COLOR_CYAN 36 +#define COLOR_MAGENTA 35 +/* +COLOR_RED 红 +COLOR_BLACK 黑 +COLOR_GREEN 绿 +COLOR_BLUE 蓝 +COLOR_YELLOW 黄 +COLOR_WHITE 白 +COLOR_CYAN 青 +COLOR_MAGENTA 洋红 +*/ + +extern void cusor_moveto(int x, int y);//光标跳转到 y行 x列 +extern void cusor_get_pos(void);//保存光标位置 +extern void cusor_hide(void); +extern void cusor_set_pos(void);//恢复光标位置 +extern void clear_screen(void);//清屏 +extern void set_fg_color(int color);//设置字体前景色 +extern void set_bg_color(int color);//设置字体背景色 + +#endif //_CONSOLE_H_ + + diff --git a/光标操作/cursor_demo/Makefile b/光标操作/cursor_demo/Makefile new file mode 100644 index 0000000..8f31361 --- /dev/null +++ b/光标操作/cursor_demo/Makefile @@ -0,0 +1,15 @@ +CC=gcc +obj=console.o test.o +target=test +CFLAGS=-Wall + +$(target):$(obj) + @$(CC) $^ -o $@ $(CFLAGS) +test.o:test.c + @$(CC) -c $< -o $@ $(CFLAGS) +console.o:console.c + @$(CC) -c $< -o $@ $(CFLAGS) + + +clean: + @rm $(obj) $(target) diff --git a/光标操作/cursor_demo/console.c b/光标操作/cursor_demo/console.c new file mode 100644 index 0000000..a28004e --- /dev/null +++ b/光标操作/cursor_demo/console.c @@ -0,0 +1,63 @@ +#include +#include +#include "console.h" + +void cusor_moveto(int x, int y) +{// ESC[y;xH + printf("\033[%d;%dH",y,x); + fflush(stdout); +} + +//保存光标位置 +void cusor_get_pos(void) +{// ESC[s + printf("\033[s"); + fflush(stdout); +} + +//恢复光标位置 +void cusor_set_pos(void) +{// ESC[u + printf("\033[u"); + fflush(stdout); +} +//隐藏光标 +void cusor_hide(void) +{ + printf("\033[?25l"); +} +//显示光标 +void cusor_show(void) +{ + printf("\33[?25h"); +} +//清屏 +void clear_screen(void) +{// ESC[2J + printf("\033[2J"); + fflush(stdout); +} + +/* +COLOR_RED 红 +COLOR_BLACK 黑 +COLOR_GREEN 绿 +COLOR_BLUE 蓝 +COLOR_YELLOW 黄 +COLOR_WHITE 白 +COLOR_CYAN 青 +COLOR_MAGENTA 洋红 +*/ +//设置前景颜色 +void set_fg_color(int color) +{// ESC[#m + printf("\033[%dm",color); + fflush(stdout); +} + +//设置背景颜色 +void set_bg_color(int color) +{// ESC[#m + printf("\033[%dm",(color+10)); + fflush(stdout); +} \ No newline at end of file diff --git a/光标操作/cursor_demo/console.h b/光标操作/cursor_demo/console.h new file mode 100644 index 0000000..7ea29a3 --- /dev/null +++ b/光标操作/cursor_demo/console.h @@ -0,0 +1,34 @@ +#ifndef _CONSOLE_H_ +#define _CONSOLE_H_ + +#define COLOR_RED 31 +#define COLOR_BLACK 30 +#define COLOR_GREEN 32 +#define COLOR_BLUE 34 +#define COLOR_YELLOW 33 +#define COLOR_WHITE 37 +#define COLOR_CYAN 36 +#define COLOR_MAGENTA 35 +/* +COLOR_RED 红 +COLOR_BLACK 黑 +COLOR_GREEN 绿 +COLOR_BLUE 蓝 +COLOR_YELLOW 黄 +COLOR_WHITE 白 +COLOR_CYAN 青 +COLOR_MAGENTA 洋红 +*/ + +extern void cusor_moveto(int x, int y);//光标跳转到 y行 x列 +extern void cusor_get_pos(void);//保存光标位置 +extern void cusor_hide(void);//隐藏光标 +extern void cusor_show(void);//显示光标 +extern void cusor_set_pos(void);//恢复光标位置 +extern void clear_screen(void);//清屏 +extern void set_fg_color(int color);//设置字体前景色 +extern void set_bg_color(int color);//设置字体背景色 + +#endif //_CONSOLE_H_ + + diff --git a/光标操作/cursor_demo/test b/光标操作/cursor_demo/test new file mode 100644 index 0000000000000000000000000000000000000000..2297bdbfcb9900d6915ebdfe7f40f1c1438d53a0 GIT binary patch literal 7524 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 +#include"console.h" +int main() +{ + clear_screen();//Ļ + cusor_moveto(20, 4);//Ƶ 4У20 + set_fg_color(COLOR_RED);//ɫΪɫ + printf("hello ,i love China!!!\n"); + + cusor_moveto(20, 2);//Ƶ 2У20 + set_fg_color(COLOR_BLUE);//ɫΪɫ + printf("hello ,i love sunplusapp!!\n"); + return 0; +} diff --git a/常用函数/ColbenFuns.c b/常用函数/ColbenFuns.c new file mode 100644 index 0000000..8fef454 --- /dev/null +++ b/常用函数/ColbenFuns.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include + +void gettoks(char *src,TOKS *toks,char *cut) +{ + toks->count=0; + toks->tok=(char **)calloc(++(toks->count),sizeof(char *)); + *(toks->tok)=strtok(src,cut); + while(NULL!=*(toks->tok+toks->count-1)) + { + toks->tok=realloc(toks->tok,sizeof(char *)*(++(toks->count))); + *(toks->tok+toks->count-1)=strtok(NULL,cut); + } + (toks->count)--; +} + +char getch( ) +{ + struct termios oldt, newt; + char ch; + tcgetattr( STDIN_FILENO, &oldt ); + newt = oldt; + newt.c_lflag &= ~( ICANON | ECHO ); + tcsetattr( STDIN_FILENO, TCSANOW, &newt ); + ch = getchar(); + tcsetattr( STDIN_FILENO, TCSANOW, &oldt ); + return ch; +} + diff --git a/常用函数/gtk_functions.c b/常用函数/gtk_functions.c new file mode 100644 index 0000000..fd49f2e --- /dev/null +++ b/常用函数/gtk_functions.c @@ -0,0 +1,234 @@ +//`pkg-config --cflags --libs gtk+-2.0` //编译标志 +#include //头文件 +int main(int argc,char *argv[]) //主函数 +{ + gtk_init(&argc,&argv[]); + GtkWidget *window=gtk_window_new(GTK_WINDOW_TOPLEVEL); //有边框 + GTK_WINDOW_POPUP //无边框 + //控件操作 + gtk_widget_show(window); + gtk_main(); + return 0; +} +void gtk_window_set_title(GtkWindow *window,const gchar *title); //窗口标题 +void gtk_widget_set_size_request(GtkWidget *widget,gint width,gint height); //窗口最小大小 +void gtk_window_set_resizable(GtkWindow *window,gboolean resizable); //窗口伸缩 +void gtk_window_set_position(GtkWindow *window,GtkWindowPosition position); //窗口位置 + GTK_WIN_POS_NONE + GTK_WIN_POS_CENTER + GTK_WIN_POS_MOUSE + GTK_WIN_POS_CENTER_ALWAYS +GdkPixbuf *gdk_pixbuf_new_from_file(const gchar *filename,GError **error); //创建图片资源 + NULL +GdkPixbuf *gdk_pixbuf_scale_simple(const GdkPixbuf *src,int dest_width,int dest_height,GdkInterpType interp_type); //设置图片大小 + GDK_INTERP_BILINEAR +void g_object_unref(GtkObject *object); //释放资源 +GtkWidget *gtk_image_new_from_pixbuf(GdkPixbuf *pixbuf); //通过资源创建图片控件 +void gtk_image_set_from_pixbuf(GtkImage *image,GdkPixbuf *pixbuf); //设置图片控件图片 +void gtk_image_clear(GtkImage *image); //清除图像控件里的图像数据 +GtkWidget *gtk_button_new_with_lable(const gcahr *label); //创建带内容按钮 +void gtk_button_set_label(GtkButton *button,const gchar *label); //设置按钮标签 +const gchar *gtk_button_get_label(GtkButton *button); //获取按钮标签 +void gtk_widget_set_sensitive(GtkWidget *widget,gboolean sensitive); //按钮使能 +void gtk_button_set_image(GtkButton *button,GtkWidget *image); //设置按钮图片 +void gtk_button_set_relief(GtkButton *button,GtkReliefStyle newstyle); //按钮透明度 + GTK_RELIEF_NONE //按钮透明 +void gtk_container_add(GtkContainer *container,GtkWidget *widget); //容器附加控件 +gulong g_signal_connect(gpointer instance,const gchar *detailed_signal,GCallback c_handler,gpointer data); //信号连接回调 +GtkWidget *gtk_hbox_new(gboolean homogeneous,gint spacing); //水平布局 +GtkWidget *gtk_vbox_new(gboolean homogeneous,gint spacing); //垂直布局 +GtkWidget *gtk_label_new(cost gchar *str); //创建标签 +void gtk_label_set_text(GtkLabel *label,const gchar *str); //设置标签内容 +const gchar *gtk_label_get_label(GtkLabel *label); //获取标签内容 +GtkWidget *gtk_table_new(guint rows,guint columns,gboolean homogeneous); //表格布局 +void gtk_table_attach_defaults(GtkTable *table,GtkWidget *widget,guint left_attach,guint right_attach,guint top_attach,guint bottom_attach); //表格布局附加控件 +GtkWidget *gtk_fixed_new(); //固定布局 +void gtk_fixed_put(GtkFixed *fixed,GtkWidget *widget,gint x,gint y); //固定布局附加控件 +GtkWidget *gtk_entry_new(void); //行编辑 +gtk_entry_set_visibility(GtkEntry *entry,gboolean visible); //行编辑显示 +const gchar *gtk_entry_get_text(GtkEngry *entry); //获取行编辑内容 +void gtk_entry_set_text(GtkEngry *entry,const gchar *text); //设置行编辑内容 +"activate" //行编辑触发信号 +GtkWidget *gtk_process_bar_new(); //进度条 +void gtk_process_bar_set_fraction(GtkProgressBar *pbar,gdouble fraction); //设置进度条百分比 +void gtk_process_bar_set_text(GtkProgressBar *pbar,gchar *text); //设置滑槽文本显示 +void gtk_progress_bar_set_orientation(GtkProgressBar *pbar,GtkProgressBarOrientation orientation); //设置进度条移动方向 + GTK_PROGRESS_LEFT_TO_RIGHT + GTK_PROGRESS_RIGHT_TO_LEFT + GTK_PROGRESS_BOTTOM_TO_TOP + GTK_PROGRESS_TOP_TO_BOTTOM +GtkWidget *gtk_scrolled_window_new(GtkAdjustment *hadjustment,GtkAdjustment *vadjustment); //滚动窗口 + NULL NULL +void gtk_scolled_window_set_policy(GtkScolledWindow *scrolled_window,GtkPolicyTypehscrollbar_policy,GtkPolicyType vscrollbar_policy); //滚动条出现的方式 + GTK_POLICY_AUTOMATIC + GTK_POLICY_ALWAYS + GTK_POLICY_NEVER +GtkWidget *gtk_clist_new_with_titles(gint columns,gchar *titles[]); //创建列表 +void gtk_clist_set_column_width(GtkCList *clist,gint column,gint width); //设置列宽 +void gtk_clist_set_column_justification(GtkCList *clist,gint column,GtkJustification justification); //对齐方式 + GTK_JUSTIFY_LEFT + GTK_JUSTIFY_RIGHT + GTK_JUSTIFY_CENTER + GTK_JUSTIFY_CENTER +gint gtk_clist_append(GtkCList *clist,gchar *text[]); //列表添加行 +void gtk_clist_clear(GtkCList *clist); //清空列表所有行 +gint gtk_clist_get_text(GtkCList *clist,gint row,gint column,gchar **text); //获取某行某列内容 +"select_row" //列表行出发信号 +guint g_timeout_add(guint interval,GSourceFunc function,gpointer data); //创建定时器 +gboolean g_source_remove(guint tag); //移除定时器 +void gtk_widget_add_events(GtkWidget *widget,gint events); //控件捕获事件 + GDK_BUTTON_PRESS_MASK + GDK_BUTTON_RELEASE_MASK + GDK_BUTTON_MOTION_MASK + GDK_KEY_PRESS_MASK + GDK_ENTER_NOTIFY_MASK +"button_press_event" //鼠标点击事件信号 +"button_release_event" //鼠标释放事件信号 +gboolean callback(GtkWidget *widget,GdkEventButton *event,gpointer data); //鼠标点击事件回调 + event->x,event->y //获取点击坐标值 + event->button //1左键,2中键,3右键 + event->type //双击GDK_2BUTTON_PRESS + return TRUE; +"motion_notify_event" //鼠标移动事件信号 +gboolean callback(GtkWidget *widget,GdkEventMotion *event,gpointer data); //鼠标移动事件回调 + event->x,event->y //获取移动坐标值 + return TRUE; +"key_press_event" //键盘按下事件的信号 +"key_release_event" //键盘释放事件的信号 +gboolean callback(GtkWidget *widget,GdkEventKey *event,gpointer data); //键盘按下事件回调 + event->keyval //获取键值 + return TRUE; +"expose_event" //曝光事件信号 +gboolean callback(GtkWidget *widget,GdkEventExpose *event,gpointer data); //曝光事件回调 + return FALSE; +#include //Cairo绘图头文件 +void gtk_widget_set_app_paintable(GtkWidgte *widget,gboolean app_paintable); //允许窗口绘图 +cairo_t *gtk_cairo_create(GdkDrawable *drawable); //创建Cairo环境 + drawable->window +void cairo_destroy(cairo_t *cr); //回收资源 +void cairo_set_line_width(cairo_t *cr,double width); //设置线宽 +void cairo_set_source_rgb(cairo_t *cr,double r,double g,double b); //设置颜色,r,g,b从0.0到1.0 +void cairo_move_to(cairo_t *cr,double x,double y); //设置直线起点 +void cairo_line_to(cairo_t *cr,double x,double y); //设置直线终点 +void cairo_rectangle(cairo_t *cr,double x,double y,double width,double height); //设置矩形路径 +void cairo_stroke(cairo_t *cr); //绘制cairo +void cairo_fill(cairo_t *cr); //填充cairo闭合路径 +void cairo_select_font_face(cairo_t *cr,const char *family,cairo_font_slant_t slant,cairo_font_weight_t weight); + 字体 倾斜 加粗 +void cairo_set_font_size(cairo_t *cr,double size); //设置字体大小 +void cairo_show_text(cairo_t *cr,const char *utf8); //显示字符串 +gdk_cairo_set_source_pixbuf(cairo_t *cr,const GdkPixbuf *pixbuf,double pixbuf_x,double pixbuf_y); //设置画图图片 +void cairo_paint(cairo_t *cr); //绘制图片 +void gtk_widget_queue_draw(GtkWidget *widget); //刷新绘图区域 +void gtk_thread_init(void) //gtk创建线程前调用/*{{{*/ +{ + if(FALSE == g_thread_supported()) + { + g_thread_init(NULL); + } + gdk_threads_init(); +}/*}}}*/ +void *pthread_fun(void *data) //线程函数中操作界面需要封装/*{{{*/ +{ + gdk_threads_enter(); + //一个或多个界面操作函数 + gdk_threads_leave(); +}/*}}}*/ +/* 功能: 设置背景图 + * widget: 主窗口 + * w, h: 图片的大小 + * path: 图片路径 + */ +static void chang_background(GtkWidget *widget, int w, int h, const gchar *path)/*{{{*/ +{ + gtk_widget_set_app_paintable(widget, TRUE); //允许窗口可以绘图 + gtk_widget_realize(widget); + + /* 更改背景图时,图片会重叠 + * 这时要手动调用下面的函数,让窗口绘图区域失效,产生窗口重绘制事件(即 expose 事件)。 + */ + gtk_widget_queue_draw(widget); + + GdkPixbuf *src_pixbuf = gdk_pixbuf_new_from_file(path, NULL); // 创建图片资源对象 + // w, h是指定图片的宽度和高度 + GdkPixbuf *dst_pixbuf = gdk_pixbuf_scale_simple(src_pixbuf, w, h, GDK_INTERP_BILINEAR); + + GdkPixmap *pixmap = NULL; + + /* 创建pixmap图像; + * NULL:不需要蒙版; + * 123: 0~255,透明到不透明 + */ + gdk_pixbuf_render_pixmap_and_mask(dst_pixbuf, &pixmap, NULL, 128); + // 通过pixmap给widget设置一张背景图,最后一个参数必须为: FASLE + gdk_window_set_back_pixmap(widget->window, pixmap, FALSE); + + // 释放资源 + g_object_unref(src_pixbuf); + g_object_unref(dst_pixbuf); + g_object_unref(pixmap); +}/*}}}*/ + + /* 功能: 设置控件字体大小 + * widget: 需要改变字体的控件 + * size: 字体大小 + * is_button: TRUE代表控件为按钮,FALSE为其它控件 + */ +static void set_widget_font_size(GtkWidget *widget, int size, gboolean is_button)/*{{{*/ +{ + GtkWidget *labelChild; + PangoFontDescription *font; + gint fontSize = size; + + font = pango_font_description_from_string("Sans"); //"Sans"字体名 + pango_font_description_set_size(font, fontSize*PANGO_SCALE);//设置字体大小 + + if(is_button){ + labelChild = gtk_bin_get_child(GTK_BIN(widget));//取出GtkButton里的label + }else{ + labelChild = widget; + } + + //设置label的字体,这样这个GtkButton上面显示的字体就变了 + gtk_widget_modify_font(GTK_WIDGET(labelChild), font); + pango_font_description_free(font); +}/*}}}*/ + +// 给创建好的image重新设计一张图片 +void load_image(GtkWidget *image, const char *file_path, const int w, const int h )/*{{{*/ +{ + gtk_image_clear( GTK_IMAGE(image) ); // 清除图像 + GdkPixbuf *src_pixbuf = gdk_pixbuf_new_from_file(file_path, NULL); // 创建图片资源 + GdkPixbuf *dest_pixbuf = gdk_pixbuf_scale_simple(src_pixbuf, w, h, GDK_INTERP_BILINEAR); // 指定大小 + gtk_image_set_from_pixbuf(GTK_IMAGE(image), dest_pixbuf); // 图片控件重新设置一张图片(pixbuf) + g_object_unref(src_pixbuf); // 释放资源 + g_object_unref(dest_pixbuf); // 释放资源 +}/*}}}*/ + +/*********************************************** +* 函数功能:设置窗口显示字体颜色 +* 参数类型:widget:需要改变颜色的控件 + color_buf:设置字体颜色,如"red"、"blue" + is_button:是否为button +* 返回类型:成功返回0,失败返回-1 +* 维护记录:2013-12-18 by lihuibo +***********************************************/ +int sungtk_widget_set_font_color(GtkWidget *widget, const char *color_buf, gboolean is_button)/*{{{*/ +{ + if(widget == NULL && color_buf==NULL) + return -1; + + GdkColor color; + GtkWidget *labelChild = NULL; + sungtk_color_get(color_buf, &color); + if(is_button == TRUE){ + labelChild = gtk_bin_get_child(GTK_BIN(widget));//取出GtkButton里的label + gtk_widget_modify_fg(labelChild, GTK_STATE_NORMAL, &color); + gtk_widget_modify_fg(labelChild, GTK_STATE_SELECTED, &color); + gtk_widget_modify_fg(labelChild, GTK_STATE_PRELIGHT, &color); + }else{ + gtk_widget_modify_fg(widget, GTK_STATE_NORMAL, &color); + } + return 0; +}/*}}}*/ + diff --git a/常用函数/netword_functions.c b/常用函数/netword_functions.c new file mode 100644 index 0000000..309cd66 --- /dev/null +++ b/常用函数/netword_functions.c @@ -0,0 +1,114 @@ +#include //字节序、地址转换头文件 +uint32_t htonl(uint32_t hostint32); //32位主机字节序转换成网络字节序,成功返回网络字节序的值 +uint16_t htons(uint16_t hostint16); //16位主机字节序转换成网络字节序,成功返回网络字节序的值 +uint32_t ntohl(uint32_t netint32); //32位网络字节序转换成主机字节序,成功返回主机字节序的值 +uint16_t ntohs(uint16_t netint16); //16位网络自己序转换成主机字节序,成功返回主机字节序的值 +int inet_pton(int family,const char *strptr,void *addrptr); //点分十进制数串转换成32位无符号整数,成功返回1 +const char *inet_ntop(int family,const void *addrptr,char *strptr,size_t len); //32位无符号整数转换成点分十进制数串,成功返回首地址,失败NULL + INET_ADDRSTRLEN 16 + INET6_ADDRSTRLEN 16 +#include //套接字头文件 +int socket(int family,int type, int protocol); //创建套接字,成功返套接字 + AF_INET SOCK_DGRAM 0 + AF_INET6 SOCK_STREAM IPPROTO_TCP + PF_PACKET SOCK_RAW IPPROTO_UDP +#include //地址结构头文件 +struct in_addr +{ + in_addr_t s_addr; //4 byte +}; +struct sockaddr_in //ipv4套接字地址结构,定义时使用 +{ + sa_family_t sin_family; //2 byte + in_port_t sin_port; //2byte + struct in_addr sin_addr; //4 byte + char sin_zero[8]; //8 byte +}; +struct sockaddr //通用套接字地址结,接口函数调用时使用 +{ + sa_family_t sa_family; //2 byte + char sa_data[14]; //14 byte +}; +//INADDR_ANY 本地通配地址,值为0 +ssize_t sendto(int sockfd,const void *buf,size_t nbytes,int flags,const struct sockaddr *to,socklen_t addrlen); //发送UDP数据至to指定的ip,成功返回发送字节数,失败返回-1 + 0 +int bind(int sockfd,const struct sockaddr *myaddr,socklen_t addrlen); //绑定本地协议地址和sockfd,成功返回0 +ssize_t recvfrom(int sockfd,void *buf,size_t nbytes,int flags,struct sockaddr *from,socklen_t *addrlen); //接收UDP数据,保存至from指向的结构,成功返回接收到的字符数,失败-1 + 0 +//TFTP:简单文件传送协议,基于UDP,无用户有效认证,数据传输模式有二进制模式octet和文本模式netascii +//69号端口等待客户端请求,临时端口与客户端通信,每个数据包变化从1开始,需客户端ACK确认,超时重发 +//TCP客户端:知道“服务器”的ip、port,主动连接 +#include //TCP客户端头文件 +int connect(int sockfd,const struct sockaddr *addr,socklen_t len); //主动连接服务器,成功返回0 +ssize_t send(int sockfd,const void *buf,size_t nbytes,int flags); //发送数据,返回成功发送的字节数,不能发送0长度的数据包 +ssize_t recv(int sockfd,void *buf,size_t nbytes,int flags); //接受网络数据,返回成功接收的字节数 +//TCP服务器具备确定地址,明确是服务器,等待连接 +int listen(int sockfd,int backlog); //套接字主动变被动,成功返回0 +int accept(int sockfd,struct sockaddr *cliaddr,socklen_t *addrlen); //从已连接队列中取出一个,否则阻塞,返回已连接套接字 +//关闭一个已连接套接字将导致另一端接收到一个0长度的数据包 +//---------------------------------------------------------------------------- +//多线程TCP服务器并发 +#include /*{{{*/ +#include +#include +#include +#include +#include +#include +#include +#include /*}}}*/ + +void *client_fun(void *arg) //与客户端交互线程 +{ + int connect_fd=(int)arg; //客户端套接字 + + close(connect_fd); + return NULL; +} + +int main(int argc,char *argv[]) +{ + int sock_fd=socket(AF_INET,SOCK_STREAM,0); //创建sockfd/*{{{*/ + if(0 > sock_fd) + { + perror("\nsocket>>>\n"); + return -1; + } + + struct sockaddr_in own_addr,client_addr; //服务器自身和客户端地址结构 + bzero(&own_addr,sizeof(own_addr)); + own_addr.sin_family=AF_INET; + own_addr.sin_port=htons(8000); + own_addr.sin_addr.s_addr=htonl(INADDR_ANY); + + socklen_t own_addr_len=sizeof(own_addr); //地址结构长度 + socklen_t client_addr_len=sizeof(client_addr); + + if(0 != bind(sock_fd,(struct sockaddr *)&own_addr,own_addr_len)) //绑定 + { + perror("\nbind>>>\n"); + close(sock_fd); + return -2; + } + + if(0 != listen(sock_fd,10)) //监听 + { + perror("\nlisten>>>\n"); + close(sock_fd); + return -3; + }/*}}}*/ + + while(1) + { + bzero(&client_addr,sizeof(client_addr)); + int connect_fd=accept(sock_fd,(struct sockaddr *)&client_addr,&client_addr_len); + pthread_t tid; + pthread_create(&tid,NULL,(void *)client_fun,(void *)connect_fd); + pthread_detach(tid); + } + + close(sock_fd); //关闭监听套接字 + return 0; +} +//-------------------------------------------------------------------------------- + diff --git a/常用函数/posix定义的取消点1.bmp b/常用函数/posix定义的取消点1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..6d0264bc46a262c97215874bb14cb233c7ae06ab GIT binary patch literal 763914 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 K2#i2r_5T4L>9jup literal 0 HcmV?d00001 diff --git a/常用函数/sql_functions.c b/常用函数/sql_functions.c new file mode 100644 index 0000000..309636e --- /dev/null +++ b/常用函数/sql_functions.c @@ -0,0 +1,67 @@ +//integer:带符号整形(最多64位) +//real:8字节浮点 +//text:字符,无大小限制 +//bolb:任意类型,无大小限制 +//null:空值 +//! sqlite3 *.db 创建或打开*.db文件 +//! .quit或.exit 退出数据库 +//create table 表名称 (列名称 数据类型,……); 创建表 +//primary key 主键,每个表只能有一个,其列数据不可重复 +//.tables 查看表 +//.schema 查看表结构 +//alter table 表名 add 列名 数据类型; 添加新列 +//alter table 表名 rename to 新表名; 修改表名 +//drop table 表名称; 删除表 +//insert into 表名 values (列值……); 插入新行并赋值,字符串加‘’号 +//insert into 表名 (列名……) values (列值……); 插入新行部分赋值 +//update 表名 set 列……=值…… 匹配条件; 修改where匹配行的列值,空匹配所有 +//delete from 表名 匹配条件; 删除匹配行 +//select * from 表名 匹配条件; +//select 列名…… from 表名 匹配条件; 从表中选取数据 +//.mode colum 左对齐列 +//.headers on 列名显示 +//where 列名 in (列值……) 在where子句中规定多个值 +//where 列1=值1 and 列2=值2 and ... 多个条件与 +//where 列1=值1 or 列2=值2 or ... 多个条件或 +//where 列名 between A and B 选取A、B之间的数据范围 +//where 列名 like 列值 数字相当于“=”,字符串可用“%”通配 +//where 列名 not in/between/like ... +//where not 列1=值1 and/or 列2=值2 and/or ... 原结果集补集 +//order by 列名 (desc) 根据指定列对结果集排序,用dest降序 +//begin; 开始一个事务 +//commit; 确认begin后的全部命令 +//rollback; 取消begin后的所有操作 +int sqlite3_open(char *db_name,sqlite3 **db); //打开数据库,成功返回SQLITE_OK +int sqlite3_close(sqlite3 *db); //关闭数据库,成功返回SQLITE_OK,链接时添加 -lpthread 和 -ldl两个库 +int sqlite3_exec(sqlite3 *db,const char *sql,exechandler_t callback,void *arg,char **errmsg); //执行sql语句,若结果集不空,回调下面callback +typedef int (*exechandler_t)(void *para,int n_column,char **column_value,char **column_name); +int sqlite3_get_table(sqlite3 *db,const char *sql,char ***resultp,int *nrow,int *ncolumn,char **errmsg); //执行sql语句,结果集保存在resultp中 +void sqlite3_free_table(char **resultp); //释放sqlite3_get_table分配的内存 +//函数 +//length() 返回字符串长度 +//lower() 将字符串转换为小写 +//upper() 将字符串转换为大写 +//select 函数名(列名) from 表名; +//聚集函数 +//avg() 返回某列的平均值 +//count() 返回某列的行数 +//max() 返回某列的最大值 +//min() 返回某列的最小值 +//sum() 返回某列值之和 +//select 列名…… from 表名 group by 列名; 根据某一属性重新分组,出现在where子句之后 +//select 函数名 (列名) …… from 表名 group by 列名 having 函数名 (列名) 限制值; 查看满足having条件的分组 +//主键惟一标识一行,对用户无意义,常用语索引,勿更新,无动态变化数据,由计算机自动生成 +//unique 用法同主键,保证一个列中数据惟一,可以有多个,可以修改和更新 +//create table 表名 (列名 数据类型 check (判断语句)); 保证某列数据满足一定条件 +//select 列名…… from 表…… where 判断语句; 用“.”分隔表名和列名 +//create view 视图名 as 语句; 创建视图 +//drop view 视图名; 删除视图 +//create trigger 触发器名 before/after insert/update/delete on 表名 +//begin 语句; end; +//datetime('now') 获取当前系统时间 +//.tables 查看触发器 +//drop trigger 触发器名; 删除触发器 +//create index 索引名 on 表名(列名); //创建索引 +//.indices 查看索引 +//drop index 索引名; 删除索引 + diff --git a/常用函数/sys_functions.c b/常用函数/sys_functions.c new file mode 100644 index 0000000..ec6fc9d --- /dev/null +++ b/常用函数/sys_functions.c @@ -0,0 +1,205 @@ +//####################################################################### +FILE *fopen(const char *path, const char *mode); //打开文件,失败返回NULL +//参数说明: +//参数path字符串包含欲打开的文件路径及文件名,参数mode字符串则代表着流形态。 +//mode有下列几种形态字符串: +//r 以只读方式打开文件,该文件必须存在。 +//r+ 以可读写方式打开文件,该文件必须存在。 +//rb+ 读写打开一个二进制文件,允许读写数据,文件必须存在。 +//rw+ 读写打开一个文本文件,允许读和写。 +//w 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。 +//w+ 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。 +//a 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。(EOF符保留) +//a+ 以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。 (原来的EOF符不保留) +//wb 只写打开或新建一个二进制文件;只允许写数据。 +//wb+ 读写打开或建立一个二进制文件,允许读和写。 +//ab+ 读写打开一个二进制文件,允许读或在文件末追加数据。 +//at+ 打开一个叫string的文件,a表示append,就是说写入处理的时候是接着原来文件已有内容写入,不是从头写入覆盖掉,t表示打开文件的类型是文本文件,+号表示对文件既可以读也可以写。 +//上述的形态字符串都可以再加一个b字符,如rb、w+b或ab+等组合,加入b 字符用来告诉函数库以二进制模式打开文件。如果不加b,表示默认加了t,即rt,wt,其中t表示以文本模式打开文件。由fopen()所建立的新文件会具有S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH(0666)权限,此文件权限也会参考umask值。 +//有些C编译系统可能不完全提供所有这些功能,有的C版本不用"r+","w+","a+",而用"rw","wr","ar"等,读者注意所用系统的规定。 +int fclose(FILE *stream); //关闭一个文件流,成功返回0, 失败返回EOF +int feof(FILE *stream); //文件结束返回非0 +int fseek(FILE *stream, long offset, int fromwhere); //文件位置指针偏移,成功返回0 + //0文件头,1当前,2文件尾 +long ftell(FILE *stream); //返回文件位置指针当前位置 +int fgetc(FILE *stream); //结尾或出错返回EOF +int fputc(int n, FILE *fp); //失败返回EOF +char *fgets(char *buf, int bufsize, FILE *stream); //出错返回NULL +int fputs(const char *str, FILE *fp); //向文件写入字符串,失败返回EOF +size_t fread(void *buffer, size_t size, size_t count, FILE *stream); //读取文件中count*size个字节,成功返回读取到的元素个数(count),否则返回0 +size_t fwrite(const void *buffer, size_t size, size_t count, FILE *stream); //返回实际写入的数据块数目 +int fscanf(FILE *stream, const char *format, [argument...]); +int fprintf(FILE *stream, const char *format, [argument...]); +//####################################################################### +#define STDIN_FILENO 0 //标准输入 +#define STDOUT_FILENO 1 //标准输出 +#define STDERR_FILENO 2 //标准错误 +#include +#include +#include //open、close头文件 +int open(const char *pathname,int flags); //文件存在 +int open(const char *pathname,int flags,mode_t mode); //文件不存在 +//成功返回fd,失败返回-1 +int close (int fd); //关闭文件,成功返回0,失败返回-1 +#include //write,read,remove头文件 +ssize_t write(int fd,const void *addr,size_t count); //写文件,成功返回写入字节个数,失败返回-1 +ssize_t read(int fd,void *addr,size_t count); //读文件,成功返回读出字节个数,失败返回-1 +int remove(const char *pathname); //删除文件,成功返回0,失败返回-1 +#include +#include //进程函数头文件 +pid_t getpid(); //获取本进程号 +pid_t getppid(); //获取父进程号 +pid_t getpgid(); //获取进程组号 +pid_t fork(); //在已有进程中创建子进程 +//成功,子进程返回0,父进程返回子进程ID;失败,返回-1 +unsigned int sleep(unsigned int sec); //进程挂起指定秒数 +//成功返回0,中断返回剩余秒数 +#include //wait、waitpid头文件 +pid_t wait(int *status); //等待子进程结束回收其资源 +//成功返回子进程号,失败返回-1 +WIFEXITED(status); //子进程正常终止取出字段值非零 +WEXITSTATUS(status) //返回保存在status变量8~16位的子进程退出状态(正常退出才可使用) +pid_t waitpid(pid_t pid,int *status,int options); //等待子进程结束回收其资源 +//成功返回子进程号,失败返回-1 +#include //exit头文件 +void exit(int value); //结束进程执行 +#include //_exit头文件,value低八位有效 +void _exit(int value); //结束进程执行,value低八位有效 +#include //atexit头文件 +int atexit(void (*function)(void)); //注册进程结束前调用的函数 +pid_t vfork(); //创建子进程,出错返回-1 +#include //exec函数组头文件 +int execl(const char *pathname,const char *arg0,...,NULL); +int execlp(const char *filename,const char *arg0,...,NULL); +int execle(const char *pathname,const char *arg0,...,NULL,char *const envp[]); +int execv(const char *pathname,char *const argv[]); +int execvp(const char *filename,char *const argv[]); +int execve(const char *pathname,char *const argv[],char *const envp[]); +//exec函数组成功无返回,失败返回-1 +#include //system头文件 +int system(const char *command); //调用系统命令,command空时返回非0,失败返回127或-1 +//Ctrl+c产生中断信号:SIGINT +//Ctrl+\产生中断信号:SIGQUIT +//Ctrl+z产生中断信号:SIGSTOP +//SIGKILL和SIGSTOP的处理方式不可更改 +#include +#include //kill头文件 +int kill(pid_t pid,int signum); //给进程发送信号,成功返回0,失败返回-1 +#include //alarm头文件 +unsigned int alarm(unsigned int seconds); //seconds秒后发出SIGALRM信号,默认终止 +#include //raise头文件 +int raise(int signum); //给进程发送信号,成功返回0,失败返回-1 +#include //abort头文件 +void abort(); //默认向进程发送SIGABRT信号,默认退出 +//终止前刷新缓冲区,关闭文件描述符 +#include //pause头文件 +int pause(); //挂起进程直至捕捉到信号,成功返回-1 +#include //signal头文件 +typedef void (*sighandler_t)(int); +sighandler_t signal(int signum,sighandler_t handler); //注册信号处理函数 + SIG_IGN //忽略信号 + SIG_DFL //执行默认动作 + 自定义 +#include //信号集头文件 +int sigemptyset(sigset_t *set); //初始化一个空信号集,成功返回0,失败返回-1 +int sigfillset(sigset_t *set); //初始化为所有信号的集合,成功返回0,失败返回-1 +int sigismember(const sigset_t *set,int signum); //查询signum是否在set中,在返回1,不在返回0,错误返回-1 +int sigaddset(sigset_t *set,int signum); //加signum到set中,成功返回0,失败返回-1 +int sigdelset(sigset_t *set,int signum); //从set中删除signum,成功返回0,失败返回-1 +int sigprocmask(int how,const sigset_t *set,sigset_t *oldset); //编辑阻塞集,成功返回0,失败返回-1 + SIG_BLOCK //添加set集合 + SIG_UNBLOCK //删除set集合 + SIG_SETMASK //设置为set集合 +#include //管道头文件 +int pipe(int fd[2]); //创建pipe,成功返回0,失败返回-1 +void fcntl(fd,F_SETFL,0); //设置文件阻塞 + O_NONBLOCK //设置文件非阻塞 +int dup(int oldfd); //成功返回新文件描述符,失败返回-1 +int dup2(int oldfd,int newfd); //强制分配并返回newfd,失败返回-1 +//close_on_exec 标志决定文件描述符在执行exec之后是否可用 +int flags; +flags=fcntl(fd,F_GETFD); //获得标志 +flags|=FD_CLOEXEC; //打开标志位 +flags&=~FD_CLOEXEC; //关闭标志位 +fcntl(fd,F_SETFD,flags); //设置标志 +#include +#include //mkfifo头文件 +int mkfifo(const char *pathname,mode_t mode); //创建fifo,成功返回0,文件已存在返回-1 +//不指定NONBLOCK +//open只读打开FIFO,阻塞至某进程为写打开FIFO +//open只写打开FIFO,阻塞至某进程为读打开FIFO +//open以只读只写打开FIFO,调用read阻塞 +//通信中写退出,read不阻塞,写恢复,read阻塞 +//通信中读退出,写进程也退出 +//缓冲区满时write阻塞 +//open以可读可写打开FIFO,open不阻塞,read阻塞,缓冲区满时write阻塞 +#include +#include //ftok头文件 +key_t ftok(const char *pathname, int proj_id); //获取IPC键值,成功返回key,失败返回-1 +#include //msgget头文件 +int msgget(key_t,int msgflg); //创建消息队列,成功返回消息队列标识符,失败返回-1 +typedef struct +{ + long mtype; + char mtext[100]; +}MSG; //消息格式 +int msgsnd(int msgid,const void *msgp,size_t msgsz,int msgflg); //添加消息到队列,成功返回0,失败返回-1 +ssize_t msgrcv(int msgid,void *msgp,size_t msgsz,long msgtyp,int msgflg); //接收消息,成功返回读取消息的长度,失败返回-1 +int msgctl(int msgid,int cmd,struct msgid_ds *buf); //控制消息队列属性,成功返回0,失败返回-1 + IPC_RMID +#include +#include +#include //共享内存头文件 +int shmget(key_t key,size_t size,int shmflg); //创建或打开共享内存,成功返回共享内存标识符,失败返回-1 +void *shmat(int shmid,const void *shmaddr,int shmflg); //映射,成功返回映射地址,失败返回-1 + NULL 0 +int shmdt(const void *shmaddr); //分离共享内存,成功返回0,失败返回-1 +int shmctl(int shmid,int cmd,struct shmid_ds *buf); //共享内存控制,成功返回0,失败返回-1 + IPC_RMID //删除 +void *shmat(int shmid,const void *shmaddr,int shmflg); //映射,成功返回映射地址,失败返回-1 +#include //线程头文件,编译加参数 -lpthread +int pthread_create(pthread_t *thread,const thread_attr_t *attr,void *(*start_routine)(void *),void *arg); //创建线程 + NULL +int pthread_join(pthread_t thread,void **retval); //等子进程结束回收资源,成功返回0,失败返回非0,有阻塞 +int pthread_detach(pthread_t thread); //独立线程,终止时系统回收资源,成功返回0,失败返回非0 +//不终止进程的前提下终止线程 +//1 线程从执行函数中返回 +//2 线程调用pthread_exit +//3 被其他线程取消 +void pthread_exit(void *retval); //退出线程 +int pthread_cancel(pthread_t thread); //发送取消线程信号,成功返回0,失败返回出错编号,无阻塞 +pthread_setcancelstate(int state,int *old_state); //设置线程是否可被取消,默认是 + PTHREAD_CANCEL_DISABLE //不可取消 + PTHREAD_CANCEL_ENABEL //可以取消 +//出现取消点的函数见posix*.bmp +void pthread_setcanceltype(int type,int *oldtype); //立即终止线程 + PTHREAD_CANCEL_ASYNCHRONOUS //立即取消 + PTHREAD_CANCEL_DEFERRED //不立即取消 +void pthread_cleanup_push(void (*routine)(void *),void *arg); //注册线程清理函数 +void pthread_cleanup_pop(int execute); //删除清理函数,0==execute?不清理:清理 +//调用清理函数 +//1 调用pthread_exit退出线程 +//2 相应其他线程取消要求 +//3 非零execute调用pthread_cleanup_pop +int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *arrt); //初始化互斥锁,成功返回0,失败返回非0 + NULL //默认属性 +int pthread_mutex_lock(pthread_mutex_t *mutex); //上锁,阻塞至解锁,成功返回0,失败返回非0 +int pthread_mutex_trylock(pthread_mutex_t *mutex); //上锁,否则立即返回,成功返回0,失败返回非0,非阻塞 +int pthread_mutex_unlock(pthread_mutex_t *mutex); //解锁,成功返回0,失败非0 +int pthread_mutex_destroy(pthread_mutex_t *mutex); //销毁锁,成功返回0,失败返回非0 +#include //信号量头文件 +int sem_init(sem_t *sem,int pshared,unsigned int value); //创建初始化信号量,成功返回0,失败返回-1 + //pshared==0?线程:进程 + //信号初始值 +int sem_wait(sem_t *sem); //信号量值减1,小于0阻塞,成功返回0,失败返回-1 +int sem_trywait(sem_t *sem); //同上,不阻塞 +int sem_post(sem_t *sem); //信号值加1等待唤醒,阻塞,成功返回0,失败返回-1 +int sem_getvalue(sem_t *sem,int *sval); //sval保存sem标识,成功返回0,失败返回-1 +int sem_destroy(sem_t *sem); //删除信号量,成功返回0,失败返回-1 +//进程间通信一般用有名信号量 +#include +#include +#include //有名信号量头文件 +sem_t *sem_open(const char *name,int oflag,mode_t mode,unsigned int value); //创建信号量,成功返回信号量地址,失败返回SEM_FAILED +int sem_close(sem_t *sem); //关闭有名信号量,成功返回0,失败返回-1 +int sem_unlink(const char *name); //删除有名信号量文件,成功返回0,失败返回-1 diff --git a/常用脚本/agent.py b/常用脚本/agent.py new file mode 100755 index 0000000..7476b00 --- /dev/null +++ b/常用脚本/agent.py @@ -0,0 +1,212 @@ +#!/usr/bin/python2 +# -*- coding:utf-8 -*- +#========================================= +# Filename : agent.py +# Filetype : Python +# Author : Colben +# Create : 2016-07-28 13:36:04 +#========================================= + +import os, sys, paramiko, re, csv +from optparse import OptionParser +from multiprocessing import Process, cpu_count, Lock +from time import sleep, time +from threading import Thread + +def print_process_result(): + output_fmt = {} + output_fmt['ERROR'] = '\033[31;5mERROR\033[0m' + output_fmt['WRONG'] = '\033[33;1mWRONG\033[0m' + output_fmt['RIGHT'] = '\033[32mRIGHT\033[0m' + output_fmt['LOCAL'] = '\033[32mLOCAL\033[0m' + csv_rfp = open('/tmp/agent_result.csv', 'rb') + for record in csv.reader(csv_rfp): + record[0] = record[0] + '-'*(15-len(record[0])) + record[1] = output_fmt[record[1]] + print '-> '.join(record) + csv_rfp.close() + return + +def write_csv(record): + process_lock.acquire() + csv_writer.writerow(record) + process_lock.release() + return + +def time_out(record, timeout): + detail = record[2] + begin_time = int(time()) + while int(time()) - begin_time < timeout: + if detail != record[2]: return + sleep(0.5) + write_csv(record) + os.kill(os.getpid(), 9) + return + +def start_timer(record, timeout): + if 0 >= options.timeout: + return + thread_timer = Thread(target = time_out, args = (record, timeout, )) + thread_timer.setDaemon(1) + thread_timer.start() + return + +def ssh_command(ip): + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + record = [ip, 'ERROR', 'CONN TIMEOUT'] + start_timer(record, 10) + try: + ssh.connect(ip, port=22, username='root', pkey=ssh_key) + #ssh.connect(ip, 22, 'root', 'password') + except Exception, e: + record[2] = str(e) + write_csv(record) + return + record[2], record[1] = 'TASK TIMEOUT', 'WRONG' + command = re.sub(r'IIPP', ip, options.remote_cmd) + start_timer(record, options.timeout) + stdin, stdout, stderr = ssh.exec_command(command) + err = stderr.readlines() + out = stdout.readlines() + if err: + record[2] = ' '.join([x.strip() for x in err]) + else: + record[2], record[1] = ' '.join([x.strip() for x in out]), 'RIGHT' + write_csv(record) + return + +def ssh_transport(ip): + record = [ip, 'ERROR', 'CONN TIMEOUT'] + start_timer(record, 10) + try: + t = paramiko.Transport((ip, 22)) + t.connect(username='root', pkey=ssh_key) + #t.connect(username='root', password='password') + except Exception, e: + record[2] = str(e) + write_csv(record) + return + record[2], record[1] = 'TASK TIMEOUT', 'WRONG' + remote_file = re.sub(r'IIPP',ip,os.path.join(options.dst_path, os.path.basename(options.src_file))) + start_timer(record, options.timeout) + try: + sftp = paramiko.SFTPClient.from_transport(t) + sftp.put(options.src_file, remote_file) + record[2], record[1] = '', 'RIGHT' + except Exception, e: + record[2] = str(e) + write_csv(record) + return + +def local_command(ip): + command = re.sub(r'IIPP', ip, options.local_cmd) + record = [ip, 'WRONG', 'TASK TIMEOUT'] + start_timer(record, options.timeout) + result = os.popen(command) + record[2], record[1] = ' '.join([x.strip() for x in result.readlines()]), 'LOCAL' + write_csv(record) + return + +def check_pool_state(empty=False): + while True: + print "\033[2J\033[0;0H" + for ip, process in process_list.items(): + if process.is_alive(): + print 'Handling', ip, '...' + else: + #print ip, '\033[32mfinished\033[0m' + process_list.pop(ip) + if not empty and options.process > len(process_list): break + if empty and 0 == len(process_list):break + sleep(0.5) + return + +def start_process_pool(): + for ip in ips: + if options.remote_cmd: + sub_process = Process(target=ssh_command, args=(ip,)) + elif options.src_file: + sub_process = Process(target=ssh_transport, args=(ip,)) + elif options.local_cmd: + sub_process = Process(target=local_command, args=(ip,)) + else: + print 'Unknown parameter ...' + sys.exit(1) + sub_process.start() + process_list[ip] = sub_process + check_pool_state() + check_pool_state(empty=True) + return + +def get_hosts(hosts_file): + if '/dev/stdin' == hosts_file: + print 'Specify no host file, enter ip manually here ...' + try: + fp = open(hosts_file, 'r') + except Exception, e: + print 'Failed to read hosts_file,', e + sys.exit(1) + ips = [] + for line in fp: + matchs = re.match(r'^(10\.\d{1,3}\.\d{1,3}\.\d{1,3})', line) + if matchs: ips.append(matchs.group(1)) + if 0 == len(ips): + print 'No ips found, quit ...' + return ips + +def initial(): + global csv_writer, process_lock, ssh_key, ips, csv_fp, process_list + try: + ssh_key = paramiko.RSAKey.from_private_key_file('/root/.ssh/id_rsa') + csv_fp = open('/tmp/agent_result.csv', 'wb', 0) + csv_writer = csv.writer(csv_fp) + except Exception, e: + print e + sys.exit(1) + ips = get_hosts(options.host) + process_lock = Lock() + process_list = {} + return + +def get_options(): + global options + usage = '%s\n\t-R remote-cmd -H ip-file -P process-num -T timeout'%sys.argv[0] + usage += '\n\t-S local-file -D remote-dir -H ip-file -P process-num -T timeout' + usage += '\n\t-L local-cmd -H ip-file -P process-num -T timeout' + usage += '\nThe pattern "IIPP" in options "RSDL" will be replaced by the ip contained in each process.' + usage += '\nThe result file is /tmp/agent_result.csv' + parser = OptionParser(usage) + parser.add_option('-R', '--remote_cmd', action='store', help='Run a shell command in remote servers.') + parser.add_option('-S', '--src_file', action='store', help='specify the file to remote servers.') + parser.add_option('-D', '--dst_path', action='store', help='specify the path in remote servers.') + parser.add_option('-L', '--local_cmd', action='store', help='Run a shell command in localhost.') + parser.add_option('-H', '--host', action='store', default='/dev/stdin', help='Specify the file contains ip.') + parser.add_option('-P', '--process', action='store', default=cpu_count(), type='int', help='Specify the num of processes.') + parser.add_option('-T', '--timeout', action='store', default=0, type='int', help='Specify the seconds of timeout.') + options, args = parser.parse_args() + for opt in [options.src_file, options.dst_path, options.local_cmd]: + if options.remote_cmd and opt: + parser.print_help() + sys.exit(1) + for opt in [options.src_file, options.dst_path]: + if options.local_cmd and opt: + parser.print_help() + sys.exit(1) + if options.src_file and not options.dst_path or options.dst_path and not options.src_file: + parser.print_help() + sys.exit(1) + if not options.remote_cmd and not options.src_file and not options.local_cmd: + parser.print_help() + sys.exit(1) + return + +def main(): + get_options() + initial() + start_process_pool() + print_process_result() + return 0 + +if '__main__' == __name__: + main() diff --git a/常用脚本/ipflow b/常用脚本/ipflow new file mode 100755 index 0000000..bae184f --- /dev/null +++ b/常用脚本/ipflow @@ -0,0 +1,61 @@ +#!/bin/bash + +type function > /dev/null 2>&1 +[ 0 -ne $? ] && echo 'Run with bash.' && exit 3 +[ 1 -lt $# ] && echo "Usage: $0 [seconds]" && exit 1 +[[ ! "$2" =~ ^[0-9]*$ ]] && "Usage: $0 [seconds]" && exit 2 + +CONF='/tmp/ipflow.conf' + +function deal_forward { + for ip in $(cat $CONF); do + iptables -$1 FORWARD -s $ip -j COLBEN_UPLOAD + iptables -$1 FORWARD -d $ip -j COLBEN_DOWNLOAD + done +} + +function insert_forward { + cat /proc/net/arp | grep '^10' | grep -v '00:00:00:00:00:00' | awk '{print $1}' > $CONF + deal_forward I +} + +function clean_forward { + [ ! -f "$CONF" ] && return 0 + deal_forward D + rm -f $CONF +} + +function show_result { + clear + echo 'Download:' + iptables -nvxL FORWARD | grep COLBEN_DOWNLOAD | awk "{printf(\"%-4dKB/s:%-10s \n\",\$2/1024/$1,\$9)}" | sort -t: -r + echo -e '\033[s\033[1;25HUpload:' + line_num=1 + iptables -nvxL FORWARD | grep COLBEN_UPLOAD | awk "{printf(\"%-4dKB/s:%-10s\n\",\$2/1024/$1,\$8)}" | sort -t: -r | while read line; do + let "line_num=1+$line_num" + echo -e "\033[$line_num;25H$line" + done + echo -e '\033[u' + sleep $1 +} + +function quit { + clean_forward + iptables -X COLBEN_UPLOAD + iptables -X COLBEN_DOWNLOAD + exit 0 +} + +iptables -N COLBEN_UPLOAD +iptables -N COLBEN_DOWNLOAD + +trap "quit" 2 3 15 + +while :; do + insert_forward + iptables -Z FORWARD + show_result ${1:-2} + clean_forward + sleep 1 +done + diff --git a/常用脚本/oracle/oracle_mul.py b/常用脚本/oracle/oracle_mul.py new file mode 100755 index 0000000..a334441 --- /dev/null +++ b/常用脚本/oracle/oracle_mul.py @@ -0,0 +1,232 @@ +#!/nmsmw/python/bin/python +# -*- encoding: gbk -*- +#========================================= +# Filename : oracle_mul.py +# Filetype : Python +# Author : Colben +# Create : 2014-12-19 10:40:30 +#========================================= + +import os, sys, re, cx_Oracle, signal +from multiprocessing import Pool, cpu_count +os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.ZHS16GBK' +#os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.AL32UTF8' + +remote_ora = {}#<>FOLD>> + +def close_dbs():#<>FOLD>> + +def handle_one_db(ora):#<>FOLD>> + +def runsqls_on_alldbs():#<>FOLD>> + +def get_fp(filename):#<>FOLD>> + +def get_sqls(sql):#<>FOLD>> + +def input_sqls():#<> ') + if re.match(r'exit.*', sql.lower()) or re.match(r'quit.*', sql.lower()): + close_dbs() + try: + sql, filename = re.split(r';', sql, 1) + except: + print 'Wrong, missing ";" in the end.' + continue + if not get_sqls(sql.strip()): + continue + get_fp(filename.strip()) + runsqls_on_alldbs() + return +#>>FOLD>> + +def access_db(ora):#<>FOLD>> + +def check_dbs():#<>FOLD>> + +def signal_quit(signum, frame):#<>FOLD>> + +def main():#<>FOLD>> + +if '__main__' == __name__: + signal.signal(2, signal_quit) + #signal.signal(3, signal_quit) + #signal.signal(15, signal_quit) + main() + diff --git a/常用脚本/oracle/partition_day.py b/常用脚本/oracle/partition_day.py new file mode 100755 index 0000000..c9393e1 --- /dev/null +++ b/常用脚本/oracle/partition_day.py @@ -0,0 +1,305 @@ +#!/nmsmw/python/bin/python + +import os +import sys +import re +import time +import datetime +import cx_Oracle +from multiprocessing import Pool + +remote_ora = {}#<>FOLD>> + +remote_rac = {}#<>FOLD>> + +mtx_tables = {}#<>FOLD>> + +dns_tables = {}#<>FOLD>> + +dnspod_tables = {}#<>FOLD>> + +vds_tables = {}#<>FOLD>> + +ntars_tables = {}#<>FOLD>> + +topn_tables = {}#<>FOLD>> + +extra_tables = {} +extra_tables['ERROR_PKT'] = 'DOMAIN_DATA_SPACE' +extra_tables['MTXRPT_EVENT_M'] = 'DOMAIN_DATA_SPACE' +extra_tables['DOMAIN_IMSI_TOPN'] = 'DOMAIN_DATA_SPACE' +extra_tables['ABNORMAL_BASE_DNS'] = 'DOMAIN_DATA_SPACE' +extra_tables['ABNORMAL_SERVER_QA'] = 'DOMAIN_DATA_SPACE' +extra_tables['ABNORMAL_SPECIAL_QUEST'] = 'DOMAIN_DATA_SPACE' +extra_tables['DNSPOD_PCI_COUNT'] = 'DOMAIN_DATA_SPACE' +extra_tables['DNSPOD_TOP100_DOMAIN'] = 'DOMAIN_DATA_SPACE' +extra_tables['DNSPOD_TOP_DOMAIN'] = 'DOMAIN_DATA_SPACE' +extra_tables['DNSPOD_IP_COUNT'] = 'DOMAIN_DATA_SPACE' +extra_tables['DNSPOD_LOCATION_COUNT'] = 'DOMAIN_DATA_SPACE' +extra_tables['DNSHJK'] = 'DOMAIN_DATA_SPACE' + +def StringToTime(strtime):#<>FOLD>> + +def gen_sqls(operate, date):#<>FOLD>> + +def ora_init(ora):#<', ora, '<------' + try: + db = cx_Oracle.connect(remote_ora[ora]) + db.autocommit = True + #print 'Connect to oracle server successfully ...' + except: + if ora in remote_rac.keys(): + #print 'Time out, now try to connect the rac ...' + try: + db = cx_Oracle.connect(remote_rac[ora]) + db.autocommit = True + #print 'Connect to oracle server successfully ...' + except: + #print 'Error, Failed to connect oracle', ora + return + else: + #print 'Error, Failed to connect oracle', ora + return + else: + #print 'Error, Wrong oracle', ora + return + return db +#>>FOLD>> + +def operate_partitions(ora):#<>FOLD>> + +def main():#<>FOLD>> + +if __name__ == '__main__': + if 2 < len(sys.argv) and sys.argv[2].isdigit(): + main() + else: + print 'Usage: %s {add|drop} 201603 [pc1, pc2 ...]'%sys.argv[0] + diff --git a/常用脚本/oracle/partition_month.py b/常用脚本/oracle/partition_month.py new file mode 100755 index 0000000..58e75de --- /dev/null +++ b/常用脚本/oracle/partition_month.py @@ -0,0 +1,187 @@ +#!/nmsmw/python/bin/python + +import os +import sys +import re +import time +import datetime +import cx_Oracle +from multiprocessing import Pool + +remote_ora = {}#<>FOLD>> + +app_tables = {}#<>FOLD>> + +def StringToTime(strtime):#<>FOLD>> + +def gen_sqls(operate, date):#<>FOLD>> + +def ora_init(ora):#<', ora, '<------' + try: + db = cx_Oracle.connect(remote_ora[ora]) + db.autocommit = True + #print 'Connect to oracle server successfully ...' + except: + if ora in remote_rac.keys(): + #print 'Time out, now try to connect the rac ...' + try: + db = cx_Oracle.connect(remote_rac[ora]) + db.autocommit = True + #print 'Connect to oracle server successfully ...' + except: + #print 'Error, Failed to connect oracle', ora + return + else: + #print 'Error, Failed to connect oracle', ora + return + else: + #print 'Error, Wrong oracle', ora + return + return db +#>>FOLD>> + +def operate_partitions(ora):#<>FOLD>> + +def main():#<>FOLD>> + +if __name__ == '__main__': + if 2 < len(sys.argv) and sys.argv[2].isdigit(): + main() + else: + print 'Usage: %s {add|drop} 2016 [pc1, pc2 ...]'%sys.argv[0] + diff --git a/常用脚本/oracle/partition_year.py b/常用脚本/oracle/partition_year.py new file mode 100755 index 0000000..cf0a220 --- /dev/null +++ b/常用脚本/oracle/partition_year.py @@ -0,0 +1,188 @@ +#!/nmsmw/python/bin/python + +import os +import sys +import re +import time +import datetime +import cx_Oracle +from multiprocessing import Pool + +remote_ora = {}#<>FOLD>> + +vds_tables = {}#<>FOLD>> + +def StringToTime(strtime):#<>FOLD>> + +def gen_sqls(operate, date):#<>FOLD>> + +def ora_init(ora):#<', ora, '<------' + try: + db = cx_Oracle.connect(remote_ora[ora]) + db.autocommit = True + #print 'Connect to oracle server successfully ...' + except: + if ora in remote_rac.keys(): + #print 'Time out, now try to connect the rac ...' + try: + db = cx_Oracle.connect(remote_rac[ora]) + db.autocommit = True + #print 'Connect to oracle server successfully ...' + except: + #print 'Error, Failed to connect oracle', ora + return + else: + #print 'Error, Failed to connect oracle', ora + return + else: + #print 'Error, Wrong oracle', ora + return + return db +#>>FOLD>> + +def operate_partitions(ora):#<>FOLD>> + +def main():#<>FOLD>> + +if __name__ == '__main__': + if 2 < len(sys.argv) and sys.argv[2].isdigit(): + main() + else: + print 'Usage: %s {add|drop} 2017 [pc1, pc2 ...]'%sys.argv[0] + diff --git a/常用脚本/oracle/table_partition.cfg b/常用脚本/oracle/table_partition.cfg new file mode 100644 index 0000000..30b13c7 --- /dev/null +++ b/常用脚本/oracle/table_partition.cfg @@ -0,0 +1,65 @@ +[day-180-2] +MONITOR_FAULT = COLLECTOR_STATE_SPACE +MT_COLLECTOR_STATE = COLLECTOR_STATE_SPACE +MT_COLLECTOR_DIR = COLLECTOR_STATE_SPACE +MTX_PERF_NET = MTX_PERF_NET +MTXRPT_EVENT_M = EVENT_COUNT_SPACE +MTXRPT_DEVICE_M = EVENT_COUNT_SPACE +MTXRPT_EVENTMOBILE_M = EVENT_COUNT_SPACE +RPT_MTXMOBILE_DEVICE_M = EVENT_COUNT_SPACE +RPT_MTXMOBILE_EVENT_M = EVENT_COUNT_SPACE +RPT_MTXMOBILE_IMEI_M = EVENT_COUNT_SPACE +RPT_MTXMOBILE_INOUT_H = EVENT_COUNT_SPACE +RPT_MTXMOBILE_PROVINCE_H = EVENT_COUNT_SPACE +RPT_MTXMOBILE_PROVINCE_M = EVENT_COUNT_SPACE +MTX_EVENT_REALTIME = EVENT_COUNT_SPACE +VDSRPT_DEVICE_M = EVENT_COUNT_SPACE +VDSRPT_EVENT_M = EVENT_COUNT_SPACE + +[day-90-2] +DOMAIN_AA = DOMAIN_DATA_SPACE +DOMAIN_CLIENT_COUNT = DOMAIN_DATA_SPACE +DOMAIN_COUNT = DOMAIN_DATA_SPACE +DOMAIN_DNAME_LENGTH = DOMAIN_DATA_SPACE +DOMAIN_FLUX = DOMAIN_DATA_SPACE +DOMAIN_OPCODE_COUNT = DOMAIN_DATA_SPACE +DOMAIN_QUERY_PACKET_LENGTH = DOMAIN_DATA_SPACE +DOMAIN_IMSI_TOPN = DOMAIN_DATA_SPACE +DOMAIN_IMSI_TOP100 = DOMAIN_DATA_SPACE +DOMAIN_RA = DOMAIN_DATA_SPACE +DOMAIN_RCODE = DOMAIN_DATA_SPACE +DOMAIN_RD = DOMAIN_DATA_SPACE +DOMAIN_RESPONSE_PACKET_LENGTH = DOMAIN_DATA_SPACE +DOMAIN_TC = DOMAIN_DATA_SPACE +DOMAIN_TTL_LENGTH = DOMAIN_DATA_SPACE +DOMAIN_TYPE_COUNT = DOMAIN_DATA_SPACE +ERROR_PKT = DOMAIN_DATA_SPACE +DNSHJK = DOMAIN_DATA_SPACE +ABNORMAL_BASE_DNS = DOMAIN_DATA_SPACE +ABNORMAL_SPECIAL_QUEST = DOMAIN_DATA_SPACE +ABNORMAL_SERVER_QA = DOMAIN_DATA_SPACE +DNSPOD_IP_COUNT = DOMAIN_DATA_SPACE +DNSPOD_IP_FLUX = DOMAIN_DATA_SPACE +DNSPOD_LOCATION_COUNT = DOMAIN_DATA_SPACE +DNSPOD_LOCATION_DOMAIN = DOMAIN_DATA_SPACE +DNSPOD_PCI_COUNT = DOMAIN_DATA_SPACE +DNSPOD_TOP100_DOMAIN = DOMAIN_DATA_SPACE +DNSPOD_TOP_DOMAIN = DOMAIN_DATA_SPACE + +[day-30-2] +TOPN_CLIENT_BYTE = DOMAIN_DATA_SPACE +TOPN_CLIENT_PACKET = DOMAIN_DATA_SPACE +TOPN_DOMAIN_NAME = DOMAIN_DATA_SPACE +TOPN_NXDOMAIN = DOMAIN_DATA_SPACE +TOPN_TLD = DOMAIN_DATA_SPACE + +[month-1-2] +APPRPT_APPSTORE_D = APPRPT_SPACE +APPRPT_DOWNLOAD_D = APPRPT_SPACE +APPRPT_APP_USING_D = APPRPT_SPACE +APPRPT_DEVICE_BAND_D = APPRPT_SPACE +APPRPT_DEVICE_BAND_M = APPRPT_SPACE +APPRPT_DEVICE_TYPE_D = APPRPT_SPACE +APPRPT_DEVICE_TYPE_M = APPRPT_SPACE +APPRPT_SPECIAL_USING_D = APPRPT_SPACE + diff --git a/常用脚本/oracle/table_partition.py b/常用脚本/oracle/table_partition.py new file mode 100755 index 0000000..b243dce --- /dev/null +++ b/常用脚本/oracle/table_partition.py @@ -0,0 +1,177 @@ +#!/usr/bin/python2 + +import os +import re +import sys +import cx_Oracle +import ConfigParser +from time import sleep + +HOST_CONF = 'host.conf' +TABLE_CONF = 'table_partition.cfg' + +SQL = {} +SQL_HEAD = '''-- <>FOLD>> +SQL['day'] = '''-- <>FOLD>> +SQL['month'] = '''-- <>FOLD>> +SQL['year'] = '''-- <>FOLD>> +SQL_FOOT = '''# <>FOLD>> + +def generate_plsql(config):# <>FOLD>> + +def operate_plsql(db, plsql):# <>FOLD>> + +def connect_db():# <>FOLD>> + +def main():# <>FOLD>> + +if __name__ == '__main__': + main() + diff --git a/常用脚本/python/msg_log.ini b/常用脚本/python/msg_log.ini new file mode 100644 index 0000000..99711f4 --- /dev/null +++ b/常用脚本/python/msg_log.ini @@ -0,0 +1,18 @@ +[_msg_log_] +level=info +file=/path/to/default.log +stderr=1 +syslog=0 +center=1 +sysID=019 +subsysID=13 +file_size=300 +file_counter=3 + +[table_partition] +file=/path/to/table_partition.log +stderr=1 +level=info +file_size=100 +file_counter=6 + diff --git a/常用脚本/python/rising_log.py b/常用脚本/python/rising_log.py new file mode 100755 index 0000000..7e1fc85 --- /dev/null +++ b/常用脚本/python/rising_log.py @@ -0,0 +1,206 @@ +#!/usr/bin/env python +#-*- encoding: gbk -*- +# + +import ConfigParser +import logging +import time, os +from logging.handlers import RotatingFileHandler +import platform + +#global +log_msg_root = '_msg_log_' + +#log_stderr_format = '$RESET$COLOR<%(levelname)-5s><%(name)s:%(process)d:%(threadName)s><%(filename)s:%(lineno)d>%(message)s' +log_stderr_format = '$COLOR$BOLD<%(levelname)-5s><%(name)s:%(process)d:%(threadName)s>$RESET$COLOR<%(filename)s:%(lineno)d>%(message)s' +#log_stderr_format = "$COLOR%(levelname)s $RESET %(asctime)s $BOLD$COLOR%(name)s$RESET %(message)s" + +if platform.system() == 'Windows': + log_file_format = '<%(levelname)s><%(name)s:%(process)d>%(message)s' +else: + log_file_format = '%(asctime)s <%(levelname)-5s><%(name)s:%(process)d:%(threadName)s><%(filename)s:%(lineno)d>%(message)s' + + +# for colorful stderr output, copy from http://stackoverflow.com/questions/384076/how-can-i-make-the-python-logging-output-to-be-colored +# by rrt + +BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) +RESET_SEQ = "\033[0m" +#COLOR_SEQ = "\033[1;%dm" # color & bold +COLOR_SEQ = "\033[0;%dm" # color only +BOLD_SEQ = "\033[1m" + +COLORS={ + 'WARNING':WHITE, + 'INFO':YELLOW, + 'DEBUG':GREEN, + 'CRITICAL':YELLOW, + 'ERROR':RED, + 'RED':RED, + 'GREEN':GREEN, + 'YELLOW':YELLOW, + 'BLUE':BLUE, + 'MAGENTA':MAGENTA, + 'CYAN':CYAN, + 'WHITE':WHITE,} +""" +COLORS = { + 'INFO': YELLOW, + 'DEBUG': GREEN, + 'ERROR': RED } + """ + +class ColoredFormatter(logging.Formatter): + def __init__(self, *args, **kwargs): + logging.Formatter.__init__(self, *args, **kwargs) + + def format(self, record): + levelname = record.levelname + color = COLOR_SEQ % (30 + COLORS[levelname]) + message = logging.Formatter.format(self, record) + #print "1--" + repr(message) + message = message.replace("$RESET", RESET_SEQ)\ + .replace("$BOLD", BOLD_SEQ)\ + .replace("$COLOR", color) + #print "2--" + repr(message) + #for k,v in COLORS.items(): + # message = message.replace("$" + k, COLOR_SEQ % (v+30))\ + # .replace("$BG" + k, COLOR_SEQ % (v+40))\ + # .replace("$BG-" + k, COLOR_SEQ % (v+40)) + #print "3--" + repr(message) + return message + RESET_SEQ + + + +#This class copy form liup's blog http://hi.baidu.com/dalier/blog/item/68419d64b98604faf63654e4.html +#by rrt on 2010-12-3 + +class DateRotatingFileHandler(RotatingFileHandler): + def __init__(self , filename , mode='a' , maxBytes=0, backupCount=0, encoding=None): + self.current = time.strftime("%Y%m%d" , time.localtime(time.time())) + self.path = os.path.dirname(filename) + self.filename = os.path.basename(filename) + newdir = os.path.join(self.path , self.current) + softlink = os.path.join(self.path, 'current') + if not os.access(newdir , os.X_OK): + os.mkdir(newdir) + try: + os.symlink(newdir ,softlink) + except: + os.system("rm -f " + softlink) + os.symlink(newdir ,softlink) + newfile = os.path.join(newdir , self.filename) + RotatingFileHandler.__init__(self, newfile , mode, maxBytes , backupCount , encoding) + + def doRollover(self): + #print "doRollover , current=%s , filename=%s"%(self.current , self.baseFilename) + self.stream.close() + self.current = time.strftime("%Y%m%d" , time.localtime(time.time())) + + #Modified by rrt on 2010-12-4 for a log path bug: /'20101204' + #repr() is not needed , time.strftime() return a string not a integer + #newdir = os.path.join(self.path , repr(self.current)) + newdir = os.path.join(self.path , self.current) + if not os.access(newdir , os.X_OK): + os.mkdir(newdir) + self.baseFilename = os.path.join(newdir , self.filename) + + if self.encoding: + self.stream = codecs.open(self.baseFilename, 'w', self.encoding) + else: + self.stream = open(self.baseFilename, 'w') + + def shouldRollover(self, record): + if RotatingFileHandler.shouldRollover(self , record): + RotatingFileHandler.doRollover(self) + + t = time.strftime("%Y%m%d" , time.localtime(time.time())) + if (cmp(self.current , t) < 0) : + return 1 + + return 0 + + +def init_log(prefix, cfg_file, type,level): + global log_msg_root, log_file_format, log_stderr_format + + cf = ConfigParser.ConfigParser() + cf.read(cfg_file) + config = {} + + # we can use + # = cf.get(prefix, 'level').split('#')[0].strip() + # to enable "#" to comment behind a value string. + + try: + config['level'] = cf.get(prefix, 'level') + except: + config['level'] = cf.get(log_msg_root, 'level') + + try: + config['file'] = cf.get(prefix, 'file') + except: + path = cf.get(log_msg_root, 'file') + path = os.path.dirname(path) + config['file'] = os.path.join(path, prefix+'.log') + + try: + config['stderr'] = cf.getint(prefix, 'stderr') + except: + config['stderr'] = cf.getint(log_msg_root, 'stderr') + + try: + config['syslog'] = cf.getint(prefix, 'syslog') + except: + config['syslog'] = cf.getint(log_msg_root, 'syslog') + + try: + config['file_size'] = cf.getint(prefix, 'file_size') + except: + config['file_size'] = cf.getint(log_msg_root, 'file_size') + + try: + config['file_cnt'] = cf.getint(prefix, 'file_counter') + except: + config['file_cnt'] = cf.getint(log_msg_root, 'file_counter') + + print config + + #new a root logger + logger = logging.getLogger(prefix) + #set root logger level + if config['level'] == 'debug': + logger.setLevel(logging.DEBUG) + elif config['level'] == 'info': + logger.setLevel(logging.INFO) + else: + logger.setLevel(logging.ERROR) + #new a log file handle + log_handler = DateRotatingFileHandler(config['file'], mode="a", maxBytes = config['file_size']*1024*1024, backupCount=config['file_cnt']) + #set log file handle format + formatter = logging.Formatter(log_file_format, datefmt='%Y-%m-%d %H:%M:%S')# '%F %T') jython not work + log_handler.setFormatter(formatter) + #add to root logger + logger.addHandler(log_handler) + #new a stderr logger if need + if not config['stderr']: + return logger + else: + + formatter = ColoredFormatter(log_stderr_format) + #formatter = logging.Formatter(log_stderr_format) + log_handler = logging.StreamHandler() + log_handler.setFormatter(formatter) + logger.addHandler(log_handler) + return logger + + + +if __name__ == '__main__': + global logger + + logger = init_log('test_log_lib', 'msg_log.ini', 0, 0) + logger.debug('debug rrrrrrrrrrrrrrrrrrrrrrrrrrrt') + logger.info('info rrrrrrrrrrrrrrrrrrrrrrrrrrrt') + logger.error('error rrrrrrrrrrrrrrrrrrrrrrrrrrrt') + diff --git a/常用脚本/python/rollback_log.cfg b/常用脚本/python/rollback_log.cfg new file mode 100644 index 0000000..97e63b0 --- /dev/null +++ b/常用脚本/python/rollback_log.cfg @@ -0,0 +1,5 @@ +[conf] +interval=43200 +day=7 +used=1024 +log_dir=/log/ diff --git a/常用脚本/python/rollback_log.py b/常用脚本/python/rollback_log.py new file mode 100755 index 0000000..2de7c13 --- /dev/null +++ b/常用脚本/python/rollback_log.py @@ -0,0 +1,131 @@ +#!/usr/bin/python2 + +from socket import * +import time +import sys +import os +import re +import signal +import ConfigParser +import struct +import subprocess +import shutil +from subprocess import Popen + +#sys.path.append('/lib/') +import rising_log + +ROLLBACK_CONF = 'rollback_log.cfg' + +### init log ### +global logger +logger = rising_log.init_log('rollback_log', 'msg_log.ini', 0, 0) + +def _sig_INT_handle(signum, frame): + logger.error("SIGINT recieve, exit()") + sys.exit() + +def dir_status(log_dir,used): + + syscmd = 'du -s %s'%(log_dir) + + output = Popen(syscmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) + + output_err = output.stderr.readlines() + output_out = output.stdout.readlines() + + if len(output_err) > 0: + for line in output_err: + logger.error("%s",line) + logger.error("syscmd:%s failed",syscmd) + return 0 + + if len(output_out) > 0: + for line in output_out: + if log_dir in line: + dir_used = int(line.split("\t")[0])/1024 + + logger.info("dir used:%d, max:%d",dir_used,used) + + if dir_used > used: + logger.info("disk used:%d to max:%d",dir_used,used) + return -1 + return 0 + +def check_dir(data_dir): + if not os.path.exists(data_dir): + logger.error("no dir:%s,then create dir",data_dir) + os.makedirs(data_dir) + +def init_rollback_config(config_file): + rollback_config = {} + try: + config = ConfigParser.ConfigParser() + config.read(config_file) + + rollback_config['interval'] = config.get('conf', 'interval') + rollback_config['day'] = config.get('conf', 'day') + rollback_config['used'] = config.get('conf', 'used') + rollback_config['log_dir'] = config.get('conf', 'log_dir') + + except Exception,msg: + logger.error(str(msg).strip()) + sys.exit(1) + + return rollback_config + + +def rollback_log(log_dir,day,used): + + file_list = [] + logdir_list =[] + + file_list = os.listdir(log_dir) + + if len(file_list) <= 0: + logger.debug("no log data in dir:%s",log_dir) + return 0 + + file_list.sort(reverse=True) + dir_num = 0 + for i in file_list: + logdir_name = os.path.join(log_dir, i) + if os.path.isdir(logdir_name): + dir_num = dir_num + 1 + if dir_num > day: + logger.info("dir_num:%d, maxnum:%d",dir_num,day) + logger.info("delete log dir:%s",logdir_name) + shutil.rmtree(logdir_name) + + else: + logdir_list.append(logdir_name) + + logdir_list.sort() + del logdir_list[-1] + + for i in logdir_list: + if dir_status(log_dir,used) < 0 : + logger.info("delete log dir:%s",i) + shutil.rmtree(i) + else: + break + + return 1 + +def main(): + signal.signal(signal.SIGINT, _sig_INT_handle) + + while(1): + rollback_config = init_rollback_config(ROLLBACK_CONF) + + sleep_interval = int(rollback_config['interval']) + log_dir = rollback_config['log_dir'] + day = int(rollback_config['day']) + used = int(rollback_config['used']) + + rollback_log(log_dir,day,used) + time.sleep(sleep_interval) + +if __name__ == '__main__': + main() + diff --git a/常用脚本/shell/check_net.sh b/常用脚本/shell/check_net.sh new file mode 100755 index 0000000..02651de --- /dev/null +++ b/常用脚本/shell/check_net.sh @@ -0,0 +1,67 @@ +#!/bin/bash +#========================================= +# Filename : check_net.sh +# Author : Colben +# Create : 2017-12-04 11:04 +#========================================= + +PROCS=() + +function Quit { + [ -n "$1" ] && echo -e "\033[31;1mERROR: $1 !\033[0m" + exit 1 +} + +function StopPing { + for pid in ${!PROCS[@]}; do + kill $pid + done + Quit +} + +function PingAddr { + local oldState= + local newState= + local alterTime= + while :; do + ping -w4 -c2 -q $1 > /dev/null 2>&1 + newState=$? + [ "$oldState" = "$newState" ] || alterTime="$(date +'%H:%M')" + oldState=$newState + if [ '0' = "$newState" ]; then + echo "\033[32;1m connected\033[0m on $alterTime." > $1 + sleep 8 + else + echo "\033[31;1m lost\033[0m on $alterTime!" > $1 + sleep 4 + fi + done +} + +# start +[ 0 -eq $# ] && Quit "No hosts found" +mkdir -p /tmp/check_net || Quit "create dir failed" +cd /tmp/check_net || Quit "change dir failed" +trap 2 3 15 "StopPing" + +for addr in $@; do + PingAddr $addr & + PROCS[$!]="$addr" +done + +while :; do + for pid in ${!PROCS[@]}; do + if [ ! -f /proc/$pid/stat ]; then + PingAddr ${PROCS[$pid]} & + PROC[$!]=PROC[$pid] + unset PROC[$pid] + fi + done + clear + for f in $(ls); do + echo -e "$f:$(cat $f)" + done + sleep 4 +done + + diff --git a/常用脚本/shell/install.sh b/常用脚本/shell/install.sh new file mode 100755 index 0000000..30f70db --- /dev/null +++ b/常用脚本/shell/install.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +# usage +USAGE="Usage: $0" + +# installation processes +PROCESSES=' +CheckFun1 +CheckFun2 +InitFun1 +InitFun2 +' + +# report error and quit +function Quit { + [ -n "$1" ] && echo "$1!" > /dev/stderr + echo -e "\033[31;1mInstallaion failed!\033[0m\n" + exit 1 +} + +function CheckFun1 { + echo '' +} + +function CheckFun2 { + echo '' +} + +function InitFun1 { + echo '' +} + +function InitFun2 { + echo '' +} + +# execute every function in PROCESSES +function Main { + for process in $PROCESSES; do + echo -e "\n\033[33;1m- $func ...\033[0m" + $process + done + echo -e "\033[32;1mInstall successfully!\033[0m\n" +} + +# start here +# check root privilege +[ 0 -ne $UID ] && Quit "Can't run without ROOT" +# check arguments +[ 0 -ne $# ] && Quit "$USAGE" +# cd to script dir +cd $(dirname $0) || Quit +# install +Main + diff --git a/常用脚本/shell/processes b/常用脚本/shell/processes new file mode 100644 index 0000000..4b86d55 --- /dev/null +++ b/常用脚本/shell/processes @@ -0,0 +1,19 @@ +#!/bin/bash + +SERVICES=( + 'rabbitmq-server' + 'redis-server' + 'mongod' + 'mysql' + 'tomcat7' + 'nginx' +) + +DAEMONS=( + '/a/b/c -f -g' + 'd -e iiii' + '/j/k' + 'llll' + '/mm/nn -a -b -c' +) + diff --git a/常用脚本/shell/rc.all b/常用脚本/shell/rc.all new file mode 100755 index 0000000..ac49f55 --- /dev/null +++ b/常用脚本/shell/rc.all @@ -0,0 +1,180 @@ +#!/bin/bash + +function Quit { + [ -n "$1" ] && echo -e "\n\033[31;1mERROR: $1\033[0m!\n" + exit 3 +} + +function Spreadout { + local i= + local service= + local daemon= + echo "System ${ROOT_DIR##*/} processes ..." + for service in ${SERVICES[@]}; do + echo "Service: \"$service\"" + done + for i in ${!DAEMONS[@]}; do + daemon="${DAEMONS[i]}" + echo "Daemon: \"$daemon\"" + done + exit 0 +} + +function ShowState { + local name=$1 + local err=$2 + local total=$3 + local style=$4 + if [ '0' = "$total" ]; then + echo -e "$name \033[32${style}mnot found\033[0m ..." + return 254 + elif [ '0' = "$err" ]; then + echo -e "$name \033[32${style}mrunning\033[0m ..." + return 0 + elif [ -z "$total" -o "$total" = "$err" ]; then + echo -e "$name \033[33${style}mstopped\033[0m!" + return 1 + else + echo -e "$name \033[31${style}merror\033[0m!!" + return 255 + fi +} + +function HandleServices { + local service= + for service in ${SERVICES[@]}; do + echo "===> ${1}ing \"$service\" ..." + systemctl $1 $service + sleep 0.4 + done +} + +function HandleDaemons { + local i= + local daemon= + for i in ${!DAEMONS[@]}; do + daemon="${DAEMONS[i]}" + echo "===> ${1}ing \"$daemon\" ..." + $WATCH_PROC $1 $daemon + sleep 0.4 + done +} + +function CheckServices { + local err=0 + local service= + for service in ${SERVICES[@]}; do + systemctl status $service > /dev/null 2>/dev/null + ShowState "Service: \"$service\"" $? || let "err=1+$err" + done + ShowState Services $err ${#SERVICES[@]} ';1;3' + return $? +} + +function CheckDaemons { + local err=0 + local daemon= + local daemon_name= + for i in ${!DAEMONS[@]}; do + daemon="${DAEMONS[i]}" + daemon_name="$(basename ${daemon%% *})" + pgrep -x ${daemon_name:0:15} > /dev/null 2>/dev/null + ShowState "Daemon: \"$daemon\"" $? || let "err=1+$err" + done + ShowState Daemons $err ${#DAEMONS[@]} ';1;3' + return $? +} + +function CheckSystem { + local i= + local err=0 + local ret=0 + local output= + local items=2 + for i in CheckServices CheckDaemons; do + output=$($i) + ret=$? + if [ 254 -eq $ret ]; then + let "items=${items}-1" + elif [ 0 -lt $ret ]; then + let "err=1+$err" + fi + if [ -z "$1" ]; then + echo -e "$output" | tail -1 + else + echo -e "$output" + fi + done + ShowState "System \"${ROOT_DIR##*/}\"" $err $items ';1' + exit $? +} + +# start here +type pgrep > /dev/null || exit 1 +cd $(dirname $0) +. processes || Quit 'File "processes" not found' +[ -x rc.pwatch ] || Quit 'Executalbe process not found' +WATCH_PROC="$(pwd)/rc.pwatch" +cd .. && ROOT_DIR=$(pwd) || Quit 'Change dir failed' + +case $* in + '') + CheckSystem + ;; + status) + CheckSystem detail + ;; + start) + for check in CheckServices CheckDaemons; do + $check > /dev/null 2>/dev/null + check_ret=$? + [ 254 -eq $check_ret ] && continue + if [ 0 -ne $check_ret ]; then + Handle${check#Check} start + output=$($check) + if [ 0 -ne $? ]; then + echo -e "$output" + Quit "${check#Check} start failed" + fi + fi + done + CheckSystem + ;; + stop) + for check in CheckDaemons CheckServices; do + $check > /dev/null 2>/dev/null + check_ret=$? + [ 254 -eq $check_ret ] && continue + [ 1 -ne $check_ret ] && Handle${check#Check} stop + done + CheckSystem + ;; + startservice) + CheckServices > /dev/null 2>/dev/null + check_ret=$? + if [ 254 -eq $check_ret ]; then + CheckSystem + elif [ 0 -ne $check_ret ]; then + HandleServices start + CheckSystem + fi + ;; + stopdaemon) + CheckDaemons > /dev/null 2>/dev/null + check_ret=$? + if [ 254 -eq $check_ret ]; then + CheckSystem + elif [ 1 -ne $check_ret ]; then + HandleDaemons stop + CheckSystem + fi + ;; + list) + Spreadout + ;; + *) + echo "Usage: $0 [status|start[service]|stop[daemon]|list]" + exit 3 + ;; +esac + diff --git a/常用脚本/shell/rc.all_mul b/常用脚本/shell/rc.all_mul new file mode 100755 index 0000000..91901e0 --- /dev/null +++ b/常用脚本/shell/rc.all_mul @@ -0,0 +1,184 @@ +#!/bin/bash + +function Quit { + [ -n "$1" ] && echo -e "\n\033[31;1mERROR: $1\033[0m!\n" + exit 3 +} + +function Spreadout { + local i= + local service= + local daemon= + echo "System ${ROOT_DIR##*/} processes ..." + for service in ${SERVICES[@]}; do + echo "Service: \"$service\"" + done + for i in ${!DAEMONS[@]}; do + daemon="${DAEMONS[i]}" + echo "Daemon: \"$daemon\"" + done + exit 0 +} + +function ShowState { + local name=$1 + local err=$2 + local total=$3 + local style=$4 + if [ '0' = "$total" ]; then + echo -e "$name \033[32${style}mnot found\033[0m ..." + return 254 + elif [ '0' = "$err" ]; then + echo -e "$name \033[32${style}mrunning\033[0m ..." + return 0 + elif [ -z "$total" -o "$total" = "$err" ]; then + echo -e "$name \033[33${style}mstopped\033[0m!" + return 1 + else + echo -e "$name \033[31${style}merror\033[0m!!" + return 255 + fi +} + +function HandleServices { + local service= + for service in ${SERVICES[@]}; do + echo "===> ${1}ing \"$service\" ..." + systemctl $1 $service + sleep 0.4 + done +} + +function HandleDaemons { + local i= + local daemon= + for i in ${!DAEMONS[@]}; do + daemon="${DAEMONS[i]}" + echo "===> ${1}ing \"$daemon\" ..." + $WATCH_PROC $1 $daemon + sleep 0.4 + done +} + +function CheckServices { + local err=0 + local service= + for service in ${SERVICES[@]}; do + systemctl status $service > /dev/null 2>/dev/null + ShowState "Service: \"$service\"" $? || let "err=1+$err" + done + ShowState Services $err ${#SERVICES[@]} ';1;3' + return $? +} + +function CheckDaemons { + local err=0 + local daemon= + local daemon_cmd= + local output= + local output_watch= + for i in ${!DAEMONS[@]}; do + daemon="${DAEMONS[i]}" + daemon_cmd="${daemon#$(dirname ${daemon%% *})/}" + output=$(pgrep -f "$daemon_cmd$") + output_watch=(pgrep -f "$(basename $WATCH_PROC) +start +[^ ]*\<$daemon_cmd$") + [ -n "$output" -a "$output" != "$output_watch" ] + ShowState "Daemon: \"$daemon\"" $? || let "err=1+$err" + done + ShowState Daemons $err ${#DAEMONS[@]} ';1;3' + return $? +} + +function CheckSystem { + local i= + local err=0 + local ret=0 + local output= + local items=2 + for i in CheckServices CheckDaemons; do + output=$($i) + ret=$? + if [ 254 -eq $ret ]; then + let "items=${items}-1" + elif [ 0 -lt $ret ]; then + let "err=1+$err" + fi + if [ -z "$1" ]; then + echo -e "$output" | tail -1 + else + echo -e "$output" + fi + done + ShowState "System \"${ROOT_DIR##*/}\"" $err $items ';1' + exit $? +} + +# start here +type pgrep > /dev/null || exit 1 +cd $(dirname $0) +. processes || Quit 'File "processes" not found' +[ -x rc.pwatch ] || Quit 'Executalbe process not found' +WATCH_PROC="$(pwd)/rc.pwatch" +cd .. && ROOT_DIR=$(pwd) || Quit 'Change dir failed' + +case $* in + '') + CheckSystem + ;; + status) + CheckSystem detail + ;; + start) + for check in CheckServices CheckDaemons; do + $check > /dev/null 2>/dev/null + check_ret=$? + [ 254 -eq $check_ret ] && continue + if [ 0 -ne $check_ret ]; then + Handle${check#Check} start + output=$($check) + if [ 0 -ne $? ]; then + echo -e "$output" + Quit "${check#Check} start failed" + fi + fi + done + CheckSystem + ;; + stop) + for check in CheckDaemons CheckServices; do + $check > /dev/null 2>/dev/null + check_ret=$? + [ 254 -eq $check_ret ] && continue + [ 1 -ne $check_ret ] && Handle${check#Check} stop + done + CheckSystem + ;; + startservice) + CheckServices > /dev/null 2>/dev/null + check_ret=$? + if [ 254 -eq $check_ret ]; then + CheckSystem + elif [ 0 -ne $check_ret ]; then + HandleServices start + CheckSystem + fi + ;; + stopdaemon) + CheckDaemons > /dev/null 2>/dev/null + check_ret=$? + if [ 254 -eq $check_ret ]; then + CheckSystem + elif [ 1 -ne $check_ret ]; then + HandleDaemons stop + CheckSystem + fi + ;; + list) + Spreadout + ;; + *) + echo "Usage: $0 [status|start[service]|stop[daemon]|list]" + exit 3 + ;; +esac + diff --git a/常用脚本/shell/rc.pwatch b/常用脚本/shell/rc.pwatch new file mode 100755 index 0000000..9681b08 --- /dev/null +++ b/常用脚本/shell/rc.pwatch @@ -0,0 +1,50 @@ +#!/bin/bash + +type pgrep > /dev/null || exit 1 +[ 2 -gt $# ] && echo -e "\tUsage:$0 {start|stop} {cmd}\n" && exit 1 + +cd $(dirname $0)/../ +WATCH_LOG=/var/log/watch_proc.log +WATCH_NAME=$(basename $0) +OPERATION=$1 +shift +PROC_CMD="$*" +PROC_NAME=$(basename ${PROC_CMD%% *}) + +function StopProc { + local cpids=$(pgrep -P $1) + local cpid= + printf "%${2}s|-$1\n" + [ -f /proc/$1/stat ] && kill $1 + local n=$(expr 2 + $2) + for cpid in $cpids; do + StopProc "$cpid" $n + done +} + +case $OPERATION in + start) + pid=$(pgrep -f "$WATCH_NAME +start +[^ ]*\<$PROC_NAME\>") + pid=$(echo -e "$pid"|grep -v "^$$$") + [ -n "$pid" ] && echo "WATCH on \"$PROC_CMD\" is runing with PID:$pid" && exit 2 + while :; do + $PROC_CMD > /dev/null 2>/dev/null & + pid=$! + while sleep 4; do [ -f /proc/$pid/stat ] || break; done + echo "$(date +'%F %T') \"$PROC_CMD\" quit exceptionally!" >> $WATCH_LOG + StopProc "$pid" 0 >> $WATCH_LOG + echo "$(date +'%F %T') \"$PROC_CMD\" restart." >> $WATCH_LOG + done > /dev/null 2>/dev/null & ;; + stop) + ppid=$(pgrep -f "$WATCH_NAME +start +[^ ]*\<$PROC_NAME\>") + [ -z "$ppid" ] && echo "No WATCH on \"$PROC_CMD\" !" && exit 1 + pid=$(pgrep -lP $ppid|grep -v '^[0-9]\+ \+sleep$'|awk '{print $1}') + [ -z "$pid" ] && echo "No process: \"$PROC_CMD\"" && kill -9 $ppid && exit 0 + kill -9 $ppid + echo "$(date +'%F %T') \"$PROC_CMD\" quit manually." >> $WATCH_LOG + StopProc "$pid" 0 + exit 0 ;; + *) + echo -e "\tUsage:$0 start|stop cmd argv ...\n" ;; +esac + diff --git a/常用脚本/shell/rc.pwatch_mul b/常用脚本/shell/rc.pwatch_mul new file mode 100755 index 0000000..e97beae --- /dev/null +++ b/常用脚本/shell/rc.pwatch_mul @@ -0,0 +1,51 @@ +#!/bin/bash + +type pgrep > /dev/null || exit 1 +[ 2 -gt $# ] && echo -e "\tUsage:$0 {start|stop} {cmd}\n" && exit 1 + +cd $(dirname $0)/../ +WATCH_LOG=/var/log/watch_proc.log +WATCH_NAME=$(basename $0) +OPERATION=$1 +shift +PROC_CMD="$*" +PROC_NAME=$(basename ${PROC_CMD%% *}) +PROC_ARGS="${PROC_CMD#*$PROC_NAME}" + +function StopProc { + local cpids=$(pgrep -P $1) + local cpid= + printf "%${2}s|-$1\n" + [ -f /proc/$1/stat ] && kill $1 + local n=$(expr 2 + $2) + for cpid in $cpids; do + StopProc "$cpid" $n + done +} + +case $OPERATION in + start) + pid=$(pgrep -f "$WATCH_NAME +start +[^ ]*\<$PROC_NAME\>$PROC_ARGS$") + pid=$(echo -e "$pid"|grep -v "^$$$") + [ -n "$pid" ] && echo "WATCH on \"$PROC_CMD\" is runing with PID:$pid" && exit 2 + while :; do + $PROC_CMD > /dev/null 2>/dev/null & + pid=$! + while sleep 4; do [ -f /proc/$pid/stat ] || break; done + echo "$(date +'%F %T') \"$PROC_CMD\" quit exceptionally!" >> $WATCH_LOG + StopProc "$pid" 0 >> $WATCH_LOG + echo "$(date +'%F %T') \"$PROC_CMD\" restart." >> $WATCH_LOG + done > /dev/null 2>/dev/null & ;; + stop) + ppid=$(pgrep -f "$WATCH_NAME +start +[^ ]*\<$PROC_NAME\>$PROC_ARGS$") + [ -z "$ppid" ] && echo "No WATCH on \"$PROC_CMD\" !" && exit 1 + pid=$(pgrep -lP $ppid|grep -v '^[0-9]\+ \+sleep$'|awk '{print $1}') + [ -z "$pid" ] && echo "No process: \"$PROC_CMD\"" && kill -9 $ppid && exit 0 + kill -9 $ppid + echo "$(date +'%F %T') \"$PROC_CMD\" quit manually." >> $WATCH_LOG + StopProc "$pid" 0 + exit 0 ;; + *) + echo -e "\tUsage:$0 start|stop cmd argv ...\n" ;; +esac + diff --git a/常用脚本/transfer b/常用脚本/transfer new file mode 100755 index 0000000..d456d25 --- /dev/null +++ b/常用脚本/transfer @@ -0,0 +1,351 @@ +#!/usr/bin/python2 +# -*- coding:utf-8 -*- +#========================================= +# Filename : transfer.py +# Author : Colben +# Create : 2017-05-11 12:27 +#========================================= + +import os, sys, platform +import shutil +import re +import time +import zipfile +import BaseHTTPServer, HTMLParser +import requests, mimetypes, base64 +from SocketServer import ThreadingMixIn +from threading import Thread + +reload(sys) +sys.setdefaultencoding("utf-8") + +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO + + +KEY = base64.b64encode('lijc:lijc') +AUTH = ('lijc', 'lijc') +URLS = [] +THREAD_RESULT = {} + +def sizeof_fmt(num):# <>FOLD>> + +def modification_date(filename): + return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(os.path.getmtime(filename))) + +def handle_attachment(filename, user_agent):# <>FOLD>> + +def sync_file(url, filename):# <>FOLD>> + +class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):# <>FOLD>> + + def do_GET(self):# <>FOLD>> + + def do_HEAD(self):# <>FOLD>> + + def do_AUTHHEAD(self):# <>FOLD>> + + def do_POST(self):# <') + f.write('\nUpload Result\n') + f.write('\n') + f.write('\n

Upload Result

\n') + f.write('\n
返回上级  返回首页') + f.write('
\n') + if r: + f.write('Success:') + else: + f.write('Failed:') + f.write(info) + self.send_footer(f) + length = f.tell() + f.seek(0) + self.send_response(200) + self.send_header("Content-type", "text/html") + self.send_header("Content-Length", str(length)) + if self.headers['user-agent'] == 'upload/sync': + self.send_header("Sync-Result", info) + self.end_headers() + if f: + self.copyfile(f, self.wfile) + f.close()# >>FOLD>> + + def deal_post_data(self):# < 0: + line = self.rfile.readline() + remainbytes -= len(line) + if boundary in line: + preline = preline[0:-1] + if preline.endswith('\r'): + preline = preline[0:-1] + out.write(preline) + out.close() + if os.path.dirname(fn).endswith('/attachment'): + return handle_attachment(fn, self.headers['user-agent']) + else: + return (True, "File '%s' upload success!" % os.path.basename(fn)) + else: + out.write(preline) + preline = line + return (False, "Unexpect Ends of data.")# >>FOLD>> + + def send_head(self):# <>FOLD>> + + def list_directory(self, path):# <') + f.write('\nDirectory %s\n' % displaypath) + f.write('\n') + f.write('') + f.write('\n\n\n

当前位置: %s

\n' % displaypath) + if '/' != self.path: + f.write('\n返回上级  返回首页') + f.write('
\n
') + f.write('') + f.write('') + f.write('\n
\n
\n\n') + if not list: + f.write('空目录\n') + else: + for name in list: + fullname = os.path.join(path, name) + colorName = displayname = linkname = name + # Append / for directories or @ for symbolic links + if os.path.isdir(fullname): + #colorName = '' + name + '/' + colorName = name + '/' + displayname = name + linkname = name + "/" + if os.path.isfile(fullname): + colorName = '' + name + '' + displayname = name + if os.path.islink(fullname): + colorName = '' + name + '@' + displayname = name + # Note: a link to a directory displays with @ and links with / + filename = os.getcwd() + '/' + displaypath + displayname + f.write( + '\n' + % (requests.utils.quote(linkname), colorName, + sizeof_fmt(os.path.getsize(filename)), modification_date(filename))) + f.write('
%s%s%s
') + self.send_footer(f) + length = f.tell() + f.seek(0) + self.send_response(200) + self.send_header("Content-type", "text/html") + self.send_header("Content-Length", str(length)) + self.end_headers() + return f# >>FOLD>> + + def send_footer(self, f):# <同步状态:') + for sync_result in THREAD_RESULT.values(): + f.write(sync_result) + f.write('\n
\n注意事项:\n
    \n') + f.write('
  • 上传同名文件时,会覆盖已存在的旧文件
  • \n') + f.write('
') + f.write('\n
\n站外链接:\n
    \n') + f.write('
  • 百度
  • \n') + f.write('

\n\n\n')# >>FOLD>> + + def translate_path(self, path):# <>FOLD>> + + def copyfile(self, source, outputfile): + shutil.copyfileobj(source, outputfile) + + def guess_type(self, path):# <>FOLD>> + + if not mimetypes.inited: + mimetypes.init() # try to read system mime.types + extensions_map = mimetypes.types_map.copy() + extensions_map.update({ + '': 'application/octet-stream', # Default + '.py': 'text/plain', + '.c': 'text/plain', + '.h': 'text/plain', + })# >>FOLD>> + + +class ThreadingServer(ThreadingMixIn, BaseHTTPServer.HTTPServer): + pass + + +if __name__ == '__main__': + # test() + + # 单线程 + # srvr = BaseHTTPServer.HTTPServer(('', 12306), SimpleHTTPRequestHandler) + + # 多线程 + srvr = ThreadingServer(('', 12306), SimpleHTTPRequestHandler) + print 'Listening ', srvr.server_address ,'...' + srvr.serve_forever() +