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.

193 lines
4.7 KiB

  1. #!/bin/bash
  2. #:-
  3. . /etc/shlib
  4. #:-
  5. include common
  6. include parse
  7. include process
  8. depends shyaml lock
  9. [ "$UID" != "0" ] && echo "You must be root." && exit 1
  10. CHECK_DEFAULT_SOURCE=/etc/default/alerting
  11. [ -f "$CHECK_DEFAULT_SOURCE" ] && . "$CHECK_DEFAULT_SOURCE"
  12. if [ "${#MAIL_DESTS[@]}" == 0 ]; then
  13. echo "You must set at least one recipient destination for mails." >&2
  14. echo " You can do that in '$CHECK_DEFAULT_SOURCE', using the variable" >&2
  15. echo " '\$MAIL_DESTS'. Note this is a bash array variable." >&2
  16. exit 1
  17. fi
  18. usage="usage: $exname -d DEST1 [-d DEST2 [...]] [DIR1 [DIR2 ...]]
  19. Checks that mirror-dir did it's job. Will send an email if not.
  20. Options:
  21. DIR1 ... DIRn
  22. Local directories that should be mirrored on destination(s).
  23. examples: /etc /home /var/backups
  24. If no directories are provided, the config file root
  25. entries will be used all as destination to copy.
  26. -d DESTn
  27. Can be repeated. Specifies host destination towards which
  28. files will be send. Note that you can specify port number after
  29. a colon and a bandwidth limit for rsync after a '/'.
  30. examples: -d liszt.musicalta:10022 -d 10.8.0.19/200
  31. -n TIME_SPEC
  32. Give a full english time spec about how old the last full
  33. run of rsync should be at most. Defaults to '12 hours'.
  34. examples: -n '12 hours'
  35. "
  36. dests=()
  37. source_dirs=()
  38. time_spec='12 hours'
  39. while [ "$#" != 0 ]; do
  40. case "$1" in
  41. "-d")
  42. dests+=("$2")
  43. shift
  44. ;;
  45. "-n")
  46. time_spec="$2"
  47. shift
  48. ;;
  49. *)
  50. source_dirs+=("$1")
  51. ;;
  52. esac
  53. shift
  54. done
  55. config_file="/etc/mirror-dir/config.yml"
  56. if [ "${#source_dirs[@]}" == 0 ]; then
  57. if [ -e "$config_file" ]; then
  58. source_dirs=($(eval echo $(shyaml get-values default.sources < "$config_file")))
  59. fi >&2
  60. if [ "${#source_dirs[@]}" == 0 ]; then
  61. err "You must specify at least one source directory to mirror" \
  62. "on command line (or in a config file)."
  63. print_usage
  64. exit 1
  65. fi
  66. fi
  67. if [ "${#dests[@]}" == 0 ]; then
  68. err "You must specify at least a destination."
  69. print_usage
  70. exit 1
  71. fi
  72. state_dir=/var/run/mirror-dir
  73. get_ids() {
  74. local session_id id_done
  75. declare -A id_done
  76. for file in "$state_dir"/*{-fail,-success}; do
  77. session_id=${file%-*}
  78. [ "${id_done["$session_id"]}" ] && continue
  79. id_done["$session_id"]=1
  80. echo "${session_id##*/}"
  81. done
  82. }
  83. dir_max_len=0
  84. for d in "${source_dirs[@]}"; do
  85. [ "$dir_max_len" -lt "${#d}" ] &&
  86. dir_max_len="${#d}"
  87. done
  88. declare -A sessions=()
  89. bad_sessions=()
  90. for dest in "${dests[@]}"; do
  91. if [[ "$dest" == *"/"* ]]; then
  92. current_rsync_options+=("--bwlimit" "${dest##*/}")
  93. dest="${dest%/*}"
  94. fi
  95. msg=()
  96. for d in "${source_dirs[@]}"; do
  97. session_id="$(echo "$dest$d" | md5_compat)"
  98. session_id="${session_id:1:8}"
  99. sessions["$session_id"]="$dest $d"
  100. f=$(find "$state_dir" \
  101. -maxdepth 1 -newermt "-$time_spec" \
  102. -type f -name "${session_id}-success")
  103. if [ -z "$f" ]; then
  104. if [ -e "$state_dir/${session_id}-success" ]; then
  105. msg+=("$(printf "%s %-${dir_max_len}s last full sync %s" \
  106. "$dest" \
  107. "$d" \
  108. "$(stat -c %y "$state_dir/${session_id}-success" |
  109. sed -r 's/\.[0-9]{9,9} / /g')")")
  110. else
  111. msg+=("$(printf "%s %-${dir_max_len}s never finished yet" \
  112. "$dest" \
  113. "$d")")
  114. fi
  115. bad_sessions+=("$session_id")
  116. fi
  117. done
  118. done
  119. if [ "${#msg[@]}" != 0 ]; then
  120. cat <<EOF | mail -s "[$(hostname)] mirror backup failing" "${MAIL_DESTS[@]}"
  121. Hi,
  122. Some configured mirroring targets have not finished gracefully in
  123. the last $time_spec. Please see for yourself:
  124. $(
  125. for m in "${msg[@]}"; do
  126. echo " $m"
  127. done
  128. )
  129. You might want to find these following information of some use:
  130. $(
  131. for m in "${bad_sessions[@]}"; do
  132. if [ -e "${state_dir}"/$m-fail ]; then
  133. echo " ${sessions[$m]}:"
  134. tail -n 5 "${state_dir}"/$m-fail | cut -f 1,2,5- -d " " | sed -r "s/^/ /g"
  135. echo
  136. else
  137. echo " ${sessions[$m]}: no fail log available"
  138. fi
  139. done
  140. )
  141. Hoping all this will help you sort out the issue...
  142. Yours sincerly,
  143. --
  144. mirror-dir-check
  145. PS: You received this email because your email is listed in
  146. \$MAIL_DESTS of '$CHECK_DEFAULT_SOURCE' of '$(hostname)'
  147. (also known as $(cat /etc/mailname)).
  148. EOF
  149. fi