一些方便系统诊断的bash函数

原文地址:一些方便系统诊断的bash函数

  1 一些方便系统诊断的bash函数:http://hongjiang.info/common-bash-functions/
  2   3 这段脚本包含100多个bash函数,是我几年前方便自己调试和诊断问题写的。贴出来给有需要的人,因为比较懒怎么使用这些函数就不写说明了。其中以下划线开头的是表示私有函数,以cf_开头的表示公共函数,可当做命令使用。
  4 # check current os is linux
  5 function cf_is_linux() {
  6   [[ "$OSTYPE" = *linux* ]] && echo "true" && return 0
  7   echo "false" && return 1
  8 }
  9 
 10 # check current os is mac/darwin
 11 function cf_is_darwin() {
 12   [[ "$OSTYPE" = *darwin* ]] && echo "true" && return 0
 13   echo "false" && return 1
 14 }
 15 
 16 # check current os is windows/cygwin
 17 function cf_is_cygwin() {
 18   [[ "$OSTYPE" = *cygwin* ]] && echo "true" && return 0
 19   echo "false" && return 1
 20 }
 21 
 22 function cf_is_gnu_date() {
 23   date --version >/dev/null 2>&1 && echo "true" && return 0
 24   echo "false" && return 1
 25 }
 26 
 27 function cf_is_gnu_sed() {
 28   sed --version >/dev/null 2>&1 && echo "true" && return 0
 29   echo "false" && return 1
 30 }
 31 
 32 function cf_is_gnu_awk() {
 33   awk --version | grep GNU >/dev/null && echo "true" && return 0
 34   echo "false" && return 1
 35 }
 36 
 37 function cf_is_gnu_grep() {
 38   grep --version | grep GNU >/dev/null && echo "true" && return 0
 39   echo "false" && return 1
 40 }
 41 
 42 # java style startsWith
 43 function cf_starts_with() {
 44   local str=$1
 45   local pre=$2
 46   [[ "$str" ==  ${pre}* ]]
 47 }
 48 
 49 # java style substring
 50 function cf_substring() {
 51   local str=$1
 52   local begin=$2
 53   local end=$3
 54   if [ -z "$end" ]; then
 55     echo ${str:$begin} 
 56   else
 57     local len=`expr $end - $begin`
 58     echo ${str:$begin:$len}
 59   fi
 60 }
 61 
 62 # get current shell name
 63 function cf_shell_name() {
 64   local name=$( ps -ocommand= -p $$ | awk '{print $1}')
 65   if cf_starts_with $name "-"; then
 66     cf_substring $name 1
 67   else
 68     echo $name
 69   fi
 70 }
 71 
 72 # check current shell is bash
 73 function cf_is_bash() {
 74   [[ `cf_shell_name` = "-bash" || `basename $(cf_shell_name)` = "bash" ]] && echo "true" && return 0
 75   echo "false" && return 1
 76 }
 77 
 78 # check current shell is zsh
 79 function cf_is_zsh() {
 80   [[ `cf_shell_name` = "-zsh" || `basename $(cf_shell_name)` = "zsh" ]] && echo "true" && return 0
 81   echo "false" && return 1
 82 }
 83 
 84 function _script_dir() {
 85   if cf_is_bash >/dev/null; then
 86     cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd -P 
 87   elif cf_is_zsh >/dev/null; then
 88     cd "$( dirname "${(%):-%N}" )" && pwd -P 
 89   else
 90     echo "unsupported shell" && return 1
 91   fi
 92 }
 93 
 94 function _script_file() {
 95   if cf_is_bash >/dev/null; then
 96     basename "${BASH_SOURCE[0]}" 
 97   elif cf_is_zsh >/dev/null; then
 98     basename "${(%):-%N}" 
 99   else
100     echo "unsupported shell" && return 1
101   fi
102 }
103 
104 # colorful grep. private function
105 function _get_colorful_grep() {
106   cf_is_gnu_grep >/dev/null && echo "grep --color" && return 0
107   export GREP_OPTIONS='--color=always'
108   export GREP_COLOR='1;35;40'
109   echo "grep" 
110 }
111 
112 # list all common functions
113 function cf_functions() {
114   if cf_is_bash >/dev/null; then
115     declare -F | awk '{print $NF}' | grep "cf_" | sort
116   elif cf_is_zsh >/dev/null; then
117     print -l ${(ok)functions} | grep "cf_" | sort
118   else
119     echo "unsupported shell" && return 1
120   fi
121 }
122 
123 # get total memory (MB)
124 function cf_mem_total() {
125   if cf_is_linux >/dev/null; then
126     free -m | awk '/^Mem/{print $2"M"}'
127   elif cf_is_darwin >/dev/null; then
128     sysctl hw.memsize | awk '{print $2/1024/1024"M"}'
129   else
130     echo "unsupported os" && return 1
131   fi 
132 }
133 
134 # decimal to hexadecimal
135 function cf_dec2Hex() {
136   printf "%x" $1
137 }
138 
139 # decimal to octal 
140 function cf_dec2Oct() {
141   printf "%o" $1
142 }
143 
144 # decimal to binary
145 function cf_dec2Bin() {
146   echo "obase=2; $1" | bc
147 }
148 
149 # hexadecimal to decimal 
150 function cf_hex2Dec() {
151   echo $((16#$1))
152 }
153 
154 # octal to decimal 
155 function cf_oct2Dec() {
156   echo $((8#$1))
157 }
158 
159 # binary to decimal 
160 function cf_bin2Dec() {
161   echo $((2#$1))
162 }
163 
164 function cf_calc() {
165   local exp="$1"
166   echo "$exp" | bc -l | awk '{printf "%.2f", $0}'
167 }
168 
169 # warning and exit, not for interactive shell
170 function cf_die() {
171   local msg="$1"
172   local code=${2:-1}
173   echo "$msg" && exit $code
174 }
175 
176 # highlight key words from file or pipeline
177 function cf_highlight() {
178   local keyword="$1"
179   local cgrep="$(_get_colorful_grep)"
180   if [ -p /dev/stdin ]; then
181     # from pipeline
182     while IFS='' read line; do
183       echo $line | eval "$cgrep -E \"${keyword}|$\""
184     done
185   else
186     local file="$2"
187     eval "$cgrep -E \"${keyword}|$\"" "$file"
188   fi
189 }
190 
191 function cf_ps_env() {
192   local pid=$1
193   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
194 
195   if cf_is_linux >/dev/null; then
196     xargs --null --max-args=1 < /proc/$pid/environ
197   elif cf_is_darwin >/dev/null; then
198     ps -wwE -p $pid
199   else
200     echo "unsupported os" && return 1
201   fi
202 }
203 
204 # get bash(current shell) major version
205 function cf_bash_major_ver() {
206   echo ${BASH_VERSINFO[0]}
207 }
208 
209 # get bash(current shell) minor version
210 function cf_bash_minor_ver() {
211   echo ${BASH_VERSINFO[1]}
212 }
213 
214 # get kernel version
215 function cf_kernel_ver() {
216   if cf_is_linux >/dev/null; then
217     uname -r | cut -d'-' -f1
218   elif cf_is_darwin >/dev/null; then
219     uname -r | cut -d'-' -f1
220   else
221     echo "unsupported os" && return 1
222   fi
223 }
224 
225 # get kernel major version
226 function cf_kernel_major_ver() {
227   if cf_is_linux >/dev/null; then
228     uname -r | awk -F'.' '{print $1"."$2}' 
229   elif cf_is_darwin >/dev/null; then
230     uname -r | awk -F'.' '{print $1"."$2}' 
231   else
232     echo "unsupported os" && return 1
233   fi
234 }
235 
236 # get kernel minor version
237 function cf_kernel_minor_ver() {
238   if cf_is_linux >/dev/null; then
239     uname -r | awk -F'.' '{print $3}'
240   elif cf_is_darwin >/dev/null; then
241     uname -r | awk -F'.' '{print $3}'
242   else
243     echo "unsupported os" && return 1
244   fi
245 }
246 
247 # get value from config file such as app.properties
248 function cf_get_property() {
249   local file="$1"
250   local key="$2"
251   grep "^${key}=" "$file" | tr -d '\r' | cut -d'=' -f2 | cf_trim
252 }
253 
254 # get command path, eg: `cf_command_path ls` output /usr/bin/ls
255 function cf_command_path() {
256   local cmd=$1
257   cf_is_bash && builtin type -P $cmd && return $?
258 
259   if [ -x /usr/bin/which ]; then
260     local p=$( /usr/bin/which $1 | head -1 )
261     [ ! -z "$p" ] && echo $p && return 0
262     return 1
263   else
264     local p=$( which $1 | grep "^/" | head -1 )
265     [ ! -z "$p" ] && echo $p && return 0
266     return 1
267   fi
268 }
269 
270 # get all ip addresses
271 function cf_ip_list() {
272   if [ -x /sbin/ip ]; then
273     local list=$(/sbin/ip -o -4 addr list | awk '{print $4}' | cut -d'/' -f1 | tr '\n' ',')
274   else
275     local list=$(/sbin/ifconfig | grep "inet " | awk '{print $2}' | sed 's/addr://' | tr '\n' ',')
276   fi
277   echo ${list%,}
278 }
279 
280 function cf_stdio() {
281   local pid=$1
282   /usr/sbin/lsof -a -p $pid -d 0,1,2
283 }
284 
285 function cf_stdout() {
286   local pid=$1
287   if cf_is_linux >/dev/null; then
288     readlink -f /proc/$pid/fd/1
289   elif cf_is_darwin >/dev/null; then
290     /usr/sbin/lsof -a -p $pid -d 1 | awk 'NR>1{print $NF}'
291   else
292     echo "unsupported os" && return 1
293   fi
294 }
295 
296 # get file last modification time
297 function cf_last_modification() {
298   local file="$1"
299   if [[ $OSTYPE == *linux* ]];then
300     date +%Y%m%d%H%M%S -r $file
301   elif [[ $OSTYPE == *darwin* ]];then
302     stat -f "%Sm" -t "%Y%m%d%H%M%S" $file
303   fi
304 }
305 
306 # check current user is root 
307 function cf_is_root() {
308   [ `whoami` = "root" ] && echo "true" && return 0
309   echo "false" && return 1
310 }
311 
312 # check current shell is interactive
313 function cf_is_interactive_shell() {
314   if cf_is_bash >/dev/null; then
315     [[ "$-" = *i* ]] && echo "true" && return 0
316   elif cf_is_zsh >/dev/null; then
317     [[ -o interactive ]] && echo "true" && return 0
318   else
319     echo "unsupported shell" && return 1
320   fi
321   echo "false" && return 1
322 }
323 
324 # check current shell is login shell
325 function cf_is_login_shell() {
326   if cf_is_bash >/dev/null; then
327     shopt -q login_shell && echo "true" && return 0
328   elif cf_is_zsh >/dev/null; then
329     [[ -o login ]] && echo "true" && return 0
330   else
331     echo "unsupported shell" && return 1
332   fi
333   echo "false" && return 1
334 }
335 
336 # check command is exists
337 function cf_is_command_exists() {
338   local cmd=$1
339   if [ -x /usr/bin/which ]; then
340     /usr/bin/which $cmd >/dev/null 2>&1 && echo "true" && return 0
341   else
342     which $cmd >/dev/null 2>&1 && echo "true" && return 0 
343   fi
344   echo "false" && return 1
345 }
346 
347 # check file name globbing flag
348 function cf_is_glob_enabled() {
349   if cf_is_bash >/dev/null; then 
350     [[ $- != *f* ]] && echo "true" && return 0
351   elif cf_is_zsh >/dev/null; then
352     [[ -o glob ]] && echo "true" && return 0
353   else
354     echo "unsupported shell" && return 1
355   fi
356   echo "false" && return 1
357 }
358 
359 # enable file name globbing
360 function cf_enable_glob() {
361   cf_is_bash >/dev/null && set +f && return 0
362   cf_is_zsh >/dev/null && set -o glob && return 0
363   echo "unsupported shell" && return 1
364 }
365 
366 # disable file name globbing
367 function cf_disable_glob() {
368   cf_is_bash >/dev/null && set -f && return 0
369   cf_is_zsh >/dev/null && set -o noglob && return 0
370   echo "unsupported shell" && return 1
371 }
372 
373 # check extglob flag
374 function cf_is_extglob_enabled() {
375   if cf_is_bash >/dev/null; then 
376     shopt -q extglob && echo "true" && return 0
377   elif cf_is_zsh >/dev/null; then
378     [[ -o kshglob ]] && echo "true" && return 0
379   else
380     echo "unsupported shell" && return 1
381   fi
382   echo "false" && return 1
383 }
384 
385 # enable extglob 
386 function cf_enable_extglob() {
387   cf_is_bash >/dev/null && shopt -s extglob && return 0
388   cf_is_zsh >/dev/null && set -o kshglob && return 0
389   echo "unsupported shell" && return 1
390 }
391 
392 # disable extglob 
393 function cf_disable_extglob() {
394   cf_is_bash >/dev/null && shopt -u extglob && return 0
395   cf_is_zsh >/dev/null && unsetopt kshglob && return 0
396   echo "unsupported shell" && return 1
397 }
398 
399 # check pid is exists
400 function cf_is_pid_exists() {
401   local pid=$1
402   [ -z "$pid" ] && echo "false" && return 1
403   kill -0 $pid >/dev/null 2>&1 && echo "true" && return 0
404   echo "false" && return 1
405 }
406 
407 function cf_is_java() {
408   local pid=$1
409   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
410   ps -ocommand= -p$pid | awk '$1~/java$/' > /dev/null && echo "true" && return 0
411   echo "false" && return 1
412 }
413 
414 function cf_is_available_port() {
415   local port=$1
416   if [[ "$OSTYPE" = *linux* ]];then
417     local r=$( netstat -ant | awk '$6=="LISTEN" && $4~":'$port'$"' )
418   elif [[ "$OSTYPE" = *darwin* ]];then
419     local r=$( netstat -ant | awk '$6=="LISTEN"' | grep "\.$port " )
420   else
421     echo "unknown system" && return 1
422   fi
423 
424   [ -z "$r" ] && echo "true" && return 0;
425   echo "false" && return 1 # port has been used
426 }
427 
428 function cf_defined() {
429   if cf_is_bash >/dev/null; then
430     [[ ${!1-X} == ${!1-Y} ]]
431   elif cf_is_zsh >/dev/null; then
432     [[ ${(P)1-X} == ${(P)1-Y} ]]
433   else
434     echo "unsupported shell" && return 1
435   fi
436 }
437 
438 function cf_has_value() {
439     cf_defined $1 || return 1
440     if cf_is_bash >/dev/null; then
441       [[ -n ${!1} ]] && return 0
442     elif cf_is_zsh >/dev/null; then
443       [[ -n ${(P)1} ]] && return 0
444     fi
445     return 1
446 }
447 
448 function cf_has_sudo_privilege() {
449   # do not need password
450   sudo -n echo >/dev/null 2>&1
451 }
452 
453 function cf_timestamp() {
454   date +%F-%T | tr ':-' '_' #2015_12_01_22_15_22
455 }
456 
457 function cf_length() {
458   echo ${#1}
459 }
460 
461 # trim string
462 function cf_trim() {
463   if [ -p /dev/stdin ]; then
464     while IFS='' read line; do
465       _trim "$line"
466     done
467   else
468     _trim "$1"
469   fi
470 }
471 
472 # private function
473 function _trim() {
474   local str="$1"
475   local extglob=$(cf_is_extglob_enabled)
476   if cf_is_bash >/dev/null || cf_is_zsh >/dev/null; then
477     [ $extglob = "false" ] && cf_enable_extglob
478     str="${str##*( )}"
479     str="${str%%*( )}"
480     [ $extglob = "false" ] && cf_disable_extglob
481   else
482     echo "unsupported shell" && return 1
483   fi
484   echo $str
485 }
486 
487 function cf_lower() {
488   echo "$1" | tr '[:upper:]' '[:lower:]'
489 }
490 
491 function cf_upper() {
492   echo "$1" | tr '[:lower:]' '[:upper:]'
493 }
494 
495 function cf_ps_name() {
496   local pid=$1
497   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
498   if cf_is_java $pid >/dev/null; then
499     local main=$(cf_ps_java_main $pid)
500     echo "java($main)"
501   else
502     ps -ocommand= -p $pid | awk '{print $1}'
503   fi
504 }
505 
506 function cf_ppid() {
507   local pid=$1
508   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
509   ps -oppid= -p $pid
510 }
511 
512 function cf_ps_java_main() {
513   local pid=$1
514   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
515   ps -ocommand= -p $pid | tr ' ' '\n' | awk '/-classpath|-cp/{getline;next};/^-/{next}1' | awk 'NR==2'
516 }
517 
518 function cf_ps_time() {
519   local pid=$1
520   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
521 
522   local elapsed="$(ps -oetime= -p $pid | cf_trim)"
523   local started="$(ps -olstart= -p $pid | cf_trim)"
524   if [ `cf_is_gnu_date` = "true" ]; then
525     started=$(date +'%Y-%m-%d %H:%M:%S' -d "$started")
526   fi
527   local cpu_time=$(ps -otime= -p $pid | cf_trim)
528   echo "started from: $started, elapsed: $elapsed, cumulative cpu time: $cpu_time"
529 }
530 
531 function cf_ps_zombies() {
532   ps -opid,state,command -e | awk 'NR==1 || $2=="Z"'
533 }
534 
535 function cf_connection_topology() {
536   local pid=$1
537   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
538 
539   /usr/sbin/lsof -Pan -iTCP -p $pid > /tmp/.$pid.lsof
540   grep -o "[0-9.:]*->[0-9.:]*" /tmp/.$pid.lsof > /tmp/.$pid.conns
541   grep "LISTEN" /tmp/.$pid.lsof | awk '$9~/*/{print substr($9,3)}' > /tmp/.$pid.ports
542 
543   echo "-------------- downstream -------------"
544   for port in $(cat /tmp/.$pid.ports); do
545     cf_connection_list_by_port $port | awk '$6=="ESTABLISHED" {print $5}' | cut -d':' -f1 | sort | uniq -c | awk '{print $2"-->localhost:"'$port'" ("$1")"}'
546   done
547 
548   echo "-------------- upstream ---------------"
549   local portsExpr=$(cat /tmp/.$pid.ports | sed -e 's/^/:/' -e 's/$/->/' | xargs | sed 's/ /|/g')
550   grep -Ev "$portsExpr" /tmp/.$pid.conns > /tmp/.$pid.out
551   awk -F'->' '{print $2}' /tmp/.$pid.out | sort | uniq -c | sort -nrk1 | awk '{print "localhost-->"$2" ("$1")"}'
552   rm -f /tmp/.$pid.lsof /tmp/.$pid.conns /tmp/.$pid.ports
553 }
554 
555 function cf_connection_list_by_pid() {
556   local pid=$1
557   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
558   /usr/sbin/lsof -Pan -iTCP -p $pid
559 }
560 
561 function cf_connection_list_by_port() {
562   local port=$1
563   netstat -ant| awk '$4~/[:.]'"$port"'$/'
564 }
565 
566 function cf_connection_stat_by_pid() {
567   local pid=$1
568   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
569   local interval=${2:-1}
570   /usr/sbin/lsof -Pan -iTCP -p $pid -r $interval
571 }
572 
573 function cf_connection_stat_by_port() {
574   local port=$1
575   netstat -ant -c| awk '$1=="Proto"{print "\n"$0};$4~/[:.]'"$port"'$/'
576 }
577 
578 function cf_listening_sockets() {
579   #lsof -Pnl -i4TCP -sTCP:LISTEN #low version unsupported -sTCP params
580   if cf_is_linux >/dev/null || cf_is_darwin >/dev/null; then
581     if cf_has_sudo_privilege; then
582       sudo /usr/sbin/lsof -Pnl -i4TCP | grep LISTEN
583     else
584       /usr/sbin/lsof -Pnl -i4TCP | grep LISTEN
585     fi
586   else
587     netstat -plnt 2>/dev/null | grep -v tcp6
588   fi
589 }
590 
591 function cf_traffic_by_eth() {
592   local eth=${1:-"eth0"}
593   if cf_is_linux >/dev/null; then
594     [ ! -d /sys/class/net/$eth ] && echo "network interface not exists." && return 1
595     while true; do
596       local r1=`cat /sys/class/net/$eth/statistics/rx_bytes`
597       local t1=`cat /sys/class/net/$eth/statistics/tx_bytes`
598       sleep 1
599       local r2=`cat /sys/class/net/$eth/statistics/rx_bytes`
600       local t2=`cat /sys/class/net/$eth/statistics/tx_bytes`
601       local rkbps=`cf_calc "( $r2 - $r1 ) / 1024"`
602       local tkbps=`cf_calc "( $t2 - $t1 ) / 1024"`
603       echo "$eth: RX $rkbps kB/s TX $tkbps kB/s"
604     done
605   elif cf_is_darwin >/dev/null; then
606     # `netstat -I eth0 -w 1` or `nettop -n -m tcp`
607     declare -a tuple
608     local _i1=0
609     cf_is_zsh >/dev/null && _i1=1
610     local _i2=1
611     cf_is_zsh >/dev/null && _i1=2
612     while true; do
613       tuple=( $(netstat -nbi -I $eth | tail -1 | awk '{print $7,$10}') )
614       local r1=${tuple[$_i1]}
615       local t1=${tuple[$_i2]}
616       sleep 1
617       tuple=( $(netstat -nbi -I $eth | tail -1 | awk '{print $7,$10}') )
618       local r2=${tuple[$_i1]}
619       local t2=${tuple[$_i2]}
620       local rkbps=`cf_calc "( $r2 - $r1 ) / 1024"`
621       local tkbps=`cf_calc "( $t2 - $t1 ) / 1024"`
622       echo "$eth: RX $rkbps kB/s TX $tkbps kB/s"
623     done
624   else
625     echo "unsupported os" && return 1
626   fi
627 }
628 
629 function cf_traffic_by_pid() {
630   ! cf_is_linux >/dev/null && echo "only works in linux" && return 1
631   local pid=$1
632   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
633 
634   # kernel 2.6.18 not support, must 2.6.32 or later?
635   local pf="/proc/$pid/net/netstat"
636   [ ! -f $pf ] && echo "$pf not found!" && return 1
637 
638   declare -a tuple
639   local _i1=0
640   cf_is_zsh >/dev/null && _i1=1
641   local _i2=1
642   cf_is_zsh >/dev/null && _i1=2
643   local pname="$(cf_ps_name $pid)"
644   while true; do
645     tuple=( $(grep "IpExt: " $pf | awk 'NR==2{print $8,$9}') )
646     local r1=${tuple[$_i1]}
647     local t1=${tuple[$_i2]}
648     sleep 1
649     tuple=( $(grep "IpExt: " $pf | awk 'NR==2{print $8,$9}') )
650     local r2=${tuple[$_i1]}
651     local t2=${tuple[$_i2]}
652     local rkbps=`cf_calc "( $r2 - $r1 ) / 1024"`
653     local tkbps=`cf_calc "( $t2 - $t1 ) / 1024"`
654     echo "$pname: IN $rkbps kB/s OUT $tkbps kB/s"
655   done
656 }
657 
658 function cf_iotop() {
659   sudo iotop -bod1
660 }
661 
662 function cf_check_sum() {
663   local dir=${1:-$PWD}
664   local dirsum=0
665   for sum  in $(find ${dir} -type f -print0 | xargs -0 cksum | awk '{print $1}')
666   do
667     dirsum=$(( ${sum} + ${dirsum} ))
668   done
669   echo ${dirsum}
670 }
671 
672 function cf_java_classpath_check() {
673   [ $# -eq 0 ] && echo "please enter classpath dir" && return 1
674   [ ! -d "$1" ] && echo "not a directory" && return 1
675 
676   local tmpfile="/tmp/.cp$(date +%s)"
677   local tmphash="/tmp/.hash$(date +%s)"
678   local verbose="/tmp/cp-verbose.log"
679 
680   if cf_is_zsh >/dev/null;then
681     local -a files
682     local begin=1
683   elif cf_is_bash >/dev/null;then
684     declare -a files
685     local begin=0
686   else 
687     echo "unsupported shell" && return 1
688   fi
689   files=(`find "$1" -name "*.jar"`)
690 
691   for f in $files; do
692     jarName=`basename $f`
693     list=`unzip -l $f | awk -v fn=$jarName '/\.class$/{print $NF,fn}'`
694     size=`echo "$list" | wc -l`
695     echo $jarName $size >> $tmphash
696     echo "$list"
697   done | sort | awk 'NF{ a[$1]++;m[$1]=m[$1]","$2}END{for(i in a) if(a[i] > 1) print i,substr(m[i],2)}' > $tmpfile
698 
699   awk '{print $2}' $tmpfile | awk -F',' '{i=1;for(;i<=NF;i++) for(j=i+1;j<=NF;j++) print $i,$j}' | sort | uniq -c | sort -nrk1 | 
700   while read line; do
701     local dup=${line%% *}
702     local jars=${line#* }
703     local jar1=${jars% *}
704     local jar2=${jars#* }
705     local len_jar1=`grep -F "$jar1" $tmphash | grep ^"$jar1" | awk '{print $2}'`
706     local len_jar2=`grep -F "$jar2" $tmphash | grep ^"$jar2" | awk '{print $2}'`
707     local len=$(($len_jar1 > $len_jar2 ? $len_jar1 : $len_jar2))
708     local per=$(echo "scale=2; $dup/$len" | bc -l)
709     echo ${per/./} $dup $jar1 $jar2
710   done | sort -nr -k1 -k2 | awk 'NR==1{print "Similarity DuplicateClasses File1 File2"}{print "%"$0}'| column -t
711 
712   sort $tmpfile | awk '{print $1,"\n\t\t",$2}' > $verbose
713   echo "See $verbose for more details."
714 
715   rm -f $tmpfile
716   rm -f $tmphash
717 }
718 
719 function cf_java_class_find() {
720   local libdir=$1
721   local name=$2
722   local glob=$(cf_is_glob_enabled)
723   [ $glob = "false" ] && cf_enable_glob
724   builtin pushd $libdir >/dev/null
725   for j in *.jar; do
726     unzip -l $j | grep $name && echo $j;
727   done
728   builtin popd >/dev/null
729   [ $glob = "false" ] && cf_disable_glob
730 }
731 
732 function cf_java_pids() {
733   ps x | grep "jav[a]" | awk '{print $1}'
734 }
735 
736 function cf_java_infos() {
737   for p in `cf_java_pids`; do
738     echo "java pid: $p"
739     info=`ps -opid=,command= -p $p | tr ' ' '\n' | awk '/-classpath|-cp/{getline;next};/-Xmx|-Dcatalina.base/{print};/^-/{next};1' | xargs`
740     echo "  $info"
741     time=`cf_ps_time $p`
742     echo "  $time"
743   done
744 }
745 
746 function cf_java_threads() {
747   local pid=$1
748   local vm_threads="GC task|VM |CompilerThread|Finalizer|Reference Handler|Signal Dispatcher"
749   "$JAVA_HOME"/bin/jstack $pid | grep "^\"" | grep -Ev "$vm_threads"
750 }
751 
752 function cf_java_sysprops() {
753   local pid=$1
754   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
755   "$JAVA_HOME"/bin/jinfo -sysprops $pid
756 }
757 
758 function cf_jstack_series() {
759   local pid=$1
760   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
761   local count=${2:-5}  # defaults 5 times
762   local delay=${3:-0.5} # defaults 0.5 seconds
763 
764   local logdir=${LOG_DIR:-"/tmp"}
765   while [ $count -gt 0 ]; do
766     if cf_is_gnu_date >/dev/null; then 
767       local suffix=$(date +%H%M%S.%N)
768     else
769       local suffix=$(date +%H%M%S)"."$count
770     fi
771     "$JAVA_HOME"/bin/jstack $pid > $logdir/jstack.$pid.$suffix
772     sleep $delay
773     let count--
774     echo -n "."
775   done
776 }
777 
778 function cf_dmesg() {
779   ! cf_is_linux >/dev/null && echo "only works in linux" && return 1
780 
781   dmesg -T "$@" 2>/dev/null
782   [ $? -eq 0 ] && return 0
783 
784   dmesg "$@" | perl -w -e 'use strict;
785   my ($uptime) = do { local @ARGV="/proc/uptime";<>}; ($uptime) = ($uptime =~ /^(\d+)\./);
786   foreach my $line (<>) {
787     printf( ($line=~/^\[\s*(\d+)\.\d+\](.+)/) ? ( "[%s]%s\n", scalar localtime(time - $uptime + $1), $2 ) : $line )
788   }'
789 }
790 
791 function cf_trace_http_request() {
792   ! cf_is_linux >/dev/null && echo "only works in linux" && return 1
793   local pid=$1
794   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
795   strace -e read -s 2000 -qftp $pid 2>&1 | grep " HTTP/1[.][01][\]r[\]n" 
796 }
797 
798 function cf_trace_http_response() {
799   ! cf_is_linux >/dev/null && echo "only works in linux" && return 1
800   local pid=$1
801   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
802   strace -e write -s 2000 -qftp $pid 2>&1 | grep "HTTP/1[.][01] " 
803 }
804 
805 function cf_trace_http_req_header() {
806   ! cf_is_linux >/dev/null && echo "only works in linux" && return 1
807   local pid=$1
808   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
809   strace -e read -s 2000 -qftp $pid 2>&1 | grep " HTTP/1[.][01][\]r[\]n" | sed  's/\\r\\n/\n/g'
810 }
811 
812 function cf_trace_http_resp_header() {
813   ! cf_is_linux >/dev/null && echo "only works in linux" && return 1
814   local pid=$1
815   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
816   strace -e write -s 2000 -qftp $pid 2>&1 | grep "HTTP/1[.][01] " | sed 's/\\r\\n/\n/g'
817 }
818 
819 function cf_trace_http_invoke() {
820   ! cf_is_linux >/dev/null && echo "only works in linux" && return 1
821   local pid=$1
822   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
823   strace -e sendto -s 2000 -qftp $pid 2>&1 | grep " HTTP/1[.][01][\]r[\]n" 
824 }
825 
826 function cf_trace_connect() {
827   ! cf_is_linux >/dev/null && echo "only works in linux" && return 1
828   local pid=$1
829   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
830   strace -e connect -s 2000 -qftp $pid 2>&1 | grep "port"
831 }
832 
833 function cf_trace_socket() {
834   ! cf_is_linux >/dev/null && echo "only works in linux" && return 1
835   local pid=$1
836   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
837   strace -e connect,socket,close -s 2000 -qftp $pid 2>&1 | grep "port"
838 }
839 
840 function cf_trace_sql_select() {
841   ! cf_is_linux >/dev/null && echo "only works in linux" && return 1
842   local pid=$1
843   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
844   strace -e sendto,write -s 2000 -qftp $pid 2>&1 | grep -i "[\]3select"
845 }
846 
847 function cf_trace_sql_update() {
848   ! cf_is_linux >/dev/null && echo "only works in linux" && return 1
849   local pid=$1
850   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
851   strace -e sendto,write -s 2000 -qftp $pid 2>&1 | grep -i "[\]3update"
852 }
853 
854 function cf_trace_sql_insert() {
855   ! cf_is_linux >/dev/null && echo "only works in linux" && return 1
856   local pid=$1
857   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
858   strace -e sendto,write -s 2000 -qftp $pid 2>&1 | grep -i "[\]3insert"
859 }
860 
861 function cf_trace_redis_command() {
862   ! cf_is_linux >/dev/null && echo "only works in linux" && return 1
863   local pid=$1
864   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
865   local cmd=$2
866   strace -e sendto,write -s 2000 -qftp $pid 2>&1 | grep -i "$cmd[\]r[\]n"
867 }
868 
869 function cf_trace_dubbo_request() {
870   ! cf_is_linux >/dev/null && echo "only works in linux" && return 1
871   local pid=$1
872   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
873   strace -e read -s 2000 -qftp $pid 2>&1 | grep -i "[\]tinterface"
874 }
875 
876 function cf_trace_dubbo_invoke() {
877   ! cf_is_linux >/dev/null && echo "only works in linux" && return 1
878   local pid=$1
879   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
880   strace -e write -s 2000 -qftp $pid 2>&1 | grep -i "[\]tinterface"
881 }
882 
883 function cf_trace_system_call() {
884   ! cf_is_linux >/dev/null && echo "only works in linux" && return 1
885   local pid=$1
886   ! cf_is_pid_exists >/dev/null $pid && echo "pid:$pid not exists" && return 1
887   local time=${2:-5}
888 
889   local outfile="/tmp/.sys-call.$pid"
890   strace -cqftp $pid -o $outfile & 
891   local spid=$!
892   while [ $time -gt 0 ]; do
893     sleep 1
894     let time--
895     echo -n "."
896   done
897   echo ""
898   kill $spid && echo "ok"
899   # if strace process still exists
900   cf_is_pid_exists $spid >/dev/null 2>&1 && kill -9 $spid
901   cat $outfile && rm -f $outfile
902 }
903 
904 function cf_random_entropy_stat() {
905   ! cf_is_linux >/dev/null && echo "only works in linux" && return 1
906   while true; do
907     echo "entropy available:" `cat /proc/sys/kernel/random/entropy_avail`
908     sleep 1
909   done
910 }
911 
912 function cf_json_fmt() {
913   python -mjson.tool
914 }
915 
916 function cf_http_server() {
917   local port=${1:-8000}
918   python -mSimpleHTTPServer $port 2>/dev/null
919 }

 

posted @ 2018-03-07 16:44  苏轶然  阅读(1172)  评论(0编辑  收藏  举报