random bash scripts
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

180 lines
4.4 KiB

  1. #!/bin/bash
  2. # kill the processes with given name which use to much resources
  3. shopt -s extglob
  4. signal=('' 'SIGHUP' 'SIGINT' 'SIGQUIT' 'SIGILL' 'SIGTRAP' 'SIGABRT' 'SIGBUS' 'SIGFPE' 'SIGKILL' 'SIGUSR1' 'SIGSEGV' 'SIGUSR2' 'SIGPIPE' 'SIGALRM' 'SIGTERM' 'SIGSTKFLT' 'SIGCHLD' 'SIGCONT' 'SIGSTOP' 'SIGTSTP' 'SIGTTIN' 'SIGTTOU' 'SIGURG' 'SIGXCPU' 'SIGXFSZ' 'SIGVTALRM' 'SIGPROF' 'SIGWINCH' 'SIGIO' 'SIGPWR' 'SIGSYS')
  5. sect=('')
  6. comm=()
  7. user=()
  8. uown=()
  9. mcpu=()
  10. mmem=()
  11. sign=()
  12. inte=()
  13. sec=''
  14. nr=0
  15. verb=0
  16. echo 'killrenegade version 1.2 august 2008 written by Feherke'
  17. while (($#)); do
  18. case "$1" in
  19. '-i')
  20. shift
  21. inifile="$1"
  22. ;;
  23. '--ini='*) inifile="${1#*=}" ;;
  24. '-V' | '--verbose') ((verb++)) ;;
  25. '-v' | '--version') exit ;;
  26. '-h' | '--help' | '-?')
  27. cat <<ENDOFSYNTAX
  28. kill the processes with given name which use to much resources
  29. Syntax :
  30. killrenegade.sh [-i inifile] [-V]
  31. Parameters :
  32. -i inifile | --ini=inifile - settings file to be read ( killrenegade.ini )
  33. -V | --verbose - verbose mode, use twice for more verbose ( no )
  34. ENDOFSYNTAX
  35. exit
  36. ;;
  37. esac
  38. shift
  39. done
  40. selfdir="${0%/*}"
  41. : "${inifile=${0%.sh}.ini}"
  42. [[ -f "$inifile" ]] || {
  43. echo 'killrenegade: error no settings'
  44. exit 1
  45. }
  46. echo -n 'reading settings... '
  47. while read -r str; do
  48. [[ "$str" ]] || continue
  49. [[ "${str:0:1}" == '#' ]] && continue
  50. [[ "$str" == "[*]" ]] && {
  51. sec="${str:1:$((${#str} - 2))}"
  52. if [[ "$sec" == 'default' ]]; then
  53. nr=0
  54. else
  55. [[ "$sec" != 'general' ]] && {
  56. nr=${#sect[@]}
  57. sect[nr]="$sec"
  58. }
  59. fi
  60. continue
  61. }
  62. [[ "$sec" ]] || continue
  63. [[ "${str#?*=}" != "$str" ]] && {
  64. IFS='=' read -r key val <<<"$str"
  65. if [[ "$sec" == 'general' ]]; then
  66. eval "$key=$val"
  67. else
  68. case "$key" in
  69. 'command') comm[nr]="$val" ;;
  70. 'user') user[nr]="$val" ;;
  71. 'belong') uown[nr]="$val" ;;
  72. 'processor') mcpu[nr]="$val" ;;
  73. 'memory') mmem[nr]="$val" ;;
  74. 'signal') sign[nr]="$val" ;;
  75. 'interval') inte[nr]="$val" ;;
  76. esac
  77. fi
  78. }
  79. done <"$inifile"
  80. ((nrsec = ${#sect[@]} - 1))
  81. echo "ok, $nrsec sections found"
  82. echo -n 'verifying settings... '
  83. err=0
  84. for ((i = 1; i <= nrsec; i++)); do
  85. comm[i]="${comm[i]:-comm[0]}"
  86. user[i]="${user[i]:-${user[0]:-root}}"
  87. uown[i]="${uown[i]:-${uown[0]:-no}}"
  88. mcpu[i]="${mcpu[i]:-${mcpu[0]:-10}}"
  89. mmem[i]="${mmem[i]:-${mmem[0]:-25}}"
  90. sign[i]="${sign[i]:-${sign[0]:-SIGTERM}}"
  91. inte[i]="${inte[i]:-${inte[0]:-60}}"
  92. last[i]=0
  93. [[ "${sign[$i]}" == @([[:alpha:]])* ]] || sign[i]="${signal[sign[i]]}"
  94. [[ "${comm[i]}" ]] || ((err++))
  95. done
  96. ((err)) && {
  97. echo "killrenegade: $err error(s) in settings"
  98. exit 2
  99. }
  100. last[0]="$(date +'%s')"
  101. [[ "$logfile" && ! -e "$logfile" ]] && touch "$logfile"
  102. [[ "$logfile" && -x "$selfdir/killstatistic.awk" ]] || htmldir=''
  103. [[ "$htmldir" && ! -e "$htmldir" ]] && mkdir -p "$htmldir"
  104. echo 'ok, defaults used where needed'
  105. [[ "$USER" != 'root' ]] && {
  106. echo "running as $USER, restrictions applied"
  107. for ((i = 1; i <= nrsec; i++)); do
  108. user[i]="$USER"
  109. uown[i]='yes'
  110. done
  111. }
  112. for ((i = 0; i <= nrsec; i++)); do
  113. echo -e "$i\\t${sect[i]}\\t${comm[i]}\\t${user[i]}\\t${uown[i]}\\t${mcpu[i]}\\t${mmem[i]}\\t${sign[i]}\\t${inte[i]}"
  114. done
  115. ((verb)) && echo 'verbose mode on, will announce kills'
  116. echo "started on $(date), Ctrl-C to stop..."
  117. while :; do
  118. ((verb > 1)) && date
  119. now=$(date +'%s')
  120. for ((i = 1; i <= nrsec; i++)); do
  121. if ((last[i] + inte[i] <= now)); then
  122. ((verb > 1)) && echo " - ${sect[i]}"
  123. ps h -C "${comm[i]}" -o 'pid user=twentycharacterswide %cpu %mem' |
  124. while read -r pid user cpu mem; do
  125. [[ "${user[i]}" != '-' ]] && { grep -q -w "$(sed -n '/no/i-v' <<<"${uown[i]}")" "$user" <<<"${user[i]}" || continue; }
  126. cpui="${cpu%.*}"
  127. memi="${mem%.*}"
  128. ((cpui > mcpu[i] || memi > mmem[i])) && {
  129. ((verb)) && echo -n "kill ${comm[i]} ( $pid ) "
  130. for sig in "${sign[i]}"; do
  131. ((verb)) && echo -n "$sig... "
  132. kill -"$sig" "$pid" && break
  133. done
  134. ((verb)) && echo 'done'
  135. [[ "$logfile" ]] && echo -e "$user\\t$(date +'%Y-%m-%d %H:%M:%S')\\t$cpu\\t$mem\\t${comm[$i]}\\t$sig" >>"$logfile"
  136. }
  137. done
  138. last[i]="$now"
  139. fi
  140. done
  141. [[ "$htmldir" ]] && ((last[0] + build <= now)) && {
  142. ((verb)) && echo 'build'
  143. "$selfdir/killstatistic.awk" -v htmldir="$htmldir" "$logfile" &
  144. last[0]="$now"
  145. }
  146. next=0
  147. for ((i = 1; i <= nrsec; i++)); do
  148. temp=$((last[i] + inte[i]))
  149. ((next == 0 || next > temp)) && next=$temp
  150. done
  151. now=$(date +'%s')
  152. ((next > now)) && sleep $((next - now))
  153. done