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.

187 lines
5.0 KiB

  1. #!/usr/bin/env bash
  2. . /etc/log2ram.conf
  3. if [ -z "$PATH_DISK" ]; then
  4. PATH_DISK='/var/log'
  5. fi
  6. LOG_NAME='log2ram.log'
  7. NO_RSYNC=${USE_RSYNC#true}
  8. NOTIFICATION_COMMAND=${NOTIFICATION_COMMAND:=mail -s "Log2Ram Error on $HOSTNAME" root}
  9. NOTIFICATION=${NOTIFICATION:=true}
  10. ## @fn is_safe()
  11. ## @brief Check if hdd log exists
  12. is_safe() {
  13. [ -d "$HDD_LOG" ] || echo "ERROR: $HDD_LOG/ doesn't exist! Can't sync."
  14. [ -d "$HDD_LOG" ] || exit 1
  15. }
  16. ## @fn journald_logrotate()
  17. ## @brief Logrotate the journal if the current RAM_LOG path is part of the journald directory
  18. journald_logrotate() {
  19. if ! [ -x "$(command -v journalctl)" ] || ! [ "$JOURNALD_AWARE" = true ]; then
  20. return 1
  21. fi
  22. if journalctl --header | grep "File path" | grep "$RAM_LOG" >/dev/null 2>&1; then
  23. journalctl --rotate
  24. return 0
  25. else
  26. return 1
  27. fi
  28. }
  29. ## @fn sync_to_disk()
  30. ## @brief Sync memory back to hard disk
  31. sync_to_disk() {
  32. is_safe
  33. optional_params=()
  34. if journald_logrotate; then
  35. optional_params+=("--include=journal/*/*@*.journal")
  36. optional_params+=("--exclude=journal/*/*")
  37. fi
  38. if [ -z "${NO_RSYNC}" ] && [ -x "$(command -v rsync)" ]; then
  39. rsync -aXv --inplace --no-whole-file --delete-after "${optional_params[@]}" "$RAM_LOG"/ "$HDD_LOG"/ 2>&1 |
  40. tee -a "$LOG2RAM_LOG"
  41. else
  42. cp -rfup "$RAM_LOG"/ -T "$HDD_LOG"/ 2>&1 | tee -a "$LOG2RAM_LOG"
  43. fi
  44. }
  45. ## @fn sync_from_disk()
  46. ## @brief Sync hard disk to memory
  47. sync_from_disk() {
  48. is_safe
  49. TP_SIZE=$SIZE
  50. if [ "$ZL2R" = true ]; then
  51. TP_SIZE=$LOG_DISK_SIZE
  52. fi
  53. if [ -n "$(du -sh -t "$TP_SIZE" "$HDD_LOG"/ | cut -f1)" ]; then
  54. echo "ERROR: RAM disk for \"$HDD_LOG/\" too small. Can't sync."
  55. echo -e "File(s) causing issues\n: $(du -sh -t "$TP_SIZE" "$HDD_LOG"/*)"
  56. umount -l "$RAM_LOG"/
  57. umount -l "$HDD_LOG"/
  58. if [ "$NOTIFICATION" = true ]; then
  59. echo "LOG2RAM : No place on RAM for \"$HDD_LOG/\" anymore, fallback on the disk" | $NOTIFICATION_COMMAND
  60. fi
  61. exit 1
  62. fi
  63. if [ -z "${NO_RSYNC}" ] && [ -x "$(command -v rsync)" ]; then
  64. rsync -aXv --inplace --no-whole-file --delete-after "$HDD_LOG"/ "$RAM_LOG"/ 2>&1 | tee -a "$LOG2RAM_LOG"
  65. else
  66. cp -rfup "$HDD_LOG"/ -T "$RAM_LOG"/ 2>&1 | tee -a "$LOG2RAM_LOG"
  67. fi
  68. }
  69. ## @fn wait_for()
  70. ## @brief Wait for directory and create test file to make sure the directory exists
  71. ## @param param1 path to the directory
  72. wait_for() {
  73. WAIT_PATH="$1"
  74. while ! findmnt "$WAIT_PATH" >/dev/null; do
  75. sleep 0.1
  76. done
  77. while [ ! -f "$WAIT_PATH/log2ram.test" ]; do
  78. touch "$WAIT_PATH/log2ram.test"
  79. sleep 0.1
  80. done
  81. rm "$WAIT_PATH/log2ram.test"
  82. }
  83. ## @fn create_zram_log_drive()
  84. ## @brief Create zram log device
  85. create_zram_log_drive() {
  86. # Check Zram Class created
  87. if [ ! -d "/sys/class/zram-control" ]; then
  88. modprobe zram
  89. RAM_DEV='0'
  90. else
  91. RAM_DEV=$(cat /sys/class/zram-control/hot_add)
  92. fi
  93. echo "$COMP_ALG" >"/sys/block/zram${RAM_DEV}/comp_algorithm"
  94. echo "$LOG_DISK_SIZE" >"/sys/block/zram${RAM_DEV}/disksize"
  95. echo "$SIZE" >"/sys/block/zram${RAM_DEV}/mem_limit"
  96. mke2fs -t ext4 "/dev/zram${RAM_DEV}"
  97. }
  98. case "$1" in
  99. start)
  100. IFS=';'
  101. for i in $PATH_DISK; do
  102. # Skip the path if the folder doesn't exist
  103. [ ! -d "$i" ] && continue
  104. PATH_FIRST_PART="${i%/*}"
  105. PATH_LAST_PART="${i##/*/}"
  106. RAM_LOG="$i"
  107. HDD_LOG="${PATH_FIRST_PART}/hdd.${PATH_LAST_PART}"
  108. LOG2RAM_LOG="${RAM_LOG}/${LOG_NAME}"
  109. [ -d "$HDD_LOG" ] || mkdir "$HDD_LOG"
  110. mount --bind "$RAM_LOG"/ "$HDD_LOG"/
  111. mount --make-private "$HDD_LOG"/
  112. wait_for "$HDD_LOG"
  113. if [ "$ZL2R" = true ]; then
  114. create_zram_log_drive
  115. mount -t ext4 -o nosuid,noexec,noatime,nodev,user=log2ram "/dev/zram${RAM_DEV}" "$RAM_LOG"/
  116. else
  117. mount -t tmpfs -o "nosuid,noexec,noatime,nodev,mode=0755,size=${SIZE}" log2ram "$RAM_LOG"/
  118. fi
  119. wait_for "$RAM_LOG"
  120. sync_from_disk
  121. done
  122. exit 0
  123. ;;
  124. stop)
  125. IFS=';'
  126. for i in $PATH_DISK; do
  127. PATH_FIRST_PART="${i%/*}"
  128. PATH_LAST_PART="${i##/*/}"
  129. RAM_LOG="$i"
  130. HDD_LOG="${PATH_FIRST_PART}/hdd.${PATH_LAST_PART}"
  131. LOG2RAM_LOG="${RAM_LOG}/${LOG_NAME}"
  132. sync_to_disk
  133. #ZRAM_LOG=$(awk '$2 == "/var/log" {print $1}' /proc/mounts)
  134. #ZRAM_LOG=$(echo ${ZRAM_LOG} | grep -o -E '[0-9]+')
  135. umount -l "$RAM_LOG"/
  136. umount -l "$HDD_LOG"/
  137. # Unsure as even with Root permision denied
  138. #echo ${ZRAM_LOG} > /sys/class/zram-control/hot_remove
  139. done
  140. exit 0
  141. ;;
  142. write)
  143. IFS=';'
  144. for i in $PATH_DISK; do
  145. PATH_FIRST_PART="${i%/*}"
  146. PATH_LAST_PART="${i##/*/}"
  147. RAM_LOG="$i"
  148. HDD_LOG="${PATH_FIRST_PART}/hdd.${PATH_LAST_PART}"
  149. LOG2RAM_LOG="${RAM_LOG}/${LOG_NAME}"
  150. sync_to_disk
  151. done
  152. exit 0
  153. ;;
  154. *)
  155. echo 'Usage: log2ram {start|stop|write}' >&2
  156. exit 1
  157. ;;
  158. esac