原文地址:一些方便系统诊断的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 }