├── LICENSE ├── README.md ├── ansible_playbook └── install_log2ram.yml ├── build-packages.sh ├── debian ├── conffiles ├── control ├── postinst ├── preinst └── prerm ├── install.sh ├── log2ram ├── log2ram-daily.service ├── log2ram-daily.timer ├── log2ram.conf ├── log2ram.logrotate ├── log2ram.service └── uninstall.sh /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2023, Azlux 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Log2Ram 2 | Log2Ram works just like ramlog for systemd (on Debian 8 Jessie for example). 3 | 4 | Useful for **RaspberryPi** for not writing on the SD card all the time. You need it because your SD card doesn't want to suffer anymore! 5 | 6 | Explanations: The script creates a `/var/log` mount point in RAM. So any writing of the log to the `/var/log` folder will not actually be written to disk (in this case to the SD card on a Raspberry Pi) but directly to RAM. By default, every day the CRON will synchronize the contents in RAM with the folder located on the physical disk. The script will also make this copy of RAM to disk in case of machine shutdowns (but, of course, it still won't do it in case of power failures). This way you can avoid excessive writing on the SD card and extend its life. 7 | 8 | [Log2Ram](https://github.com/azlux/log2ram)'s script works on every Linux system. If you don't have Systemd, you can still use Log2Ram with your own daemon manager. 9 | 10 | Log2Ram is based on transient /var/log for Systemd. For more information, check [here](https://www.debian-administration.org/article/661/A_transient_/var/log). 11 | 12 | _____ 13 | ## Table of Contents 14 | 1. [Installation](#installation) 15 | 2. [Is it working?](#is-it-working) 16 | 3. [Upgrading](#upgrading) 17 | 4. [Customization](#customization) 18 | 5. [Troubleshooting](#troubleshooting) 19 | 6. [Uninstallation](#uninstallation-) 20 | 21 | ## Installation 22 | ### Via APT (recommended) 23 | 24 | ```bash 25 | echo "deb [signed-by=/usr/share/keyrings/azlux-archive-keyring.gpg] http://packages.azlux.fr/debian/ bookworm main" | sudo tee /etc/apt/sources.list.d/azlux.list 26 | sudo wget -O /usr/share/keyrings/azlux-archive-keyring.gpg https://azlux.fr/repo.gpg 27 | sudo apt update 28 | sudo apt install log2ram 29 | ``` 30 | ### Manually 31 | 32 | ```bash 33 | curl -L https://github.com/azlux/log2ram/archive/master.tar.gz | tar zxf - 34 | cd log2ram-master 35 | chmod +x install.sh && sudo ./install.sh 36 | cd .. 37 | rm -r log2ram-master 38 | ``` 39 | 40 | For better performances, `RSYNC` is a recommended package. 41 | 42 | **REBOOT** before installing anything else (for example `apache2`) 43 | 44 | ## Is it working? 45 | After installing and rebooting, use systemctl to check if Log2Ram started successfully: 46 | 47 | ```bash 48 | systemctl status log2ram 49 | ``` 50 | 51 | This will show a color-coded status (green: active/red: failed), as well as the last few log lines. To show the full log (scrolled to the end), run: 52 | 53 | ```bash 54 | journalctl -u log2ram -e 55 | ``` 56 | 57 | The log is also written to `/var/log/log2ram.log`. 58 | 59 | You can also inspect the mount folder in RAM with: 60 | 61 | ```bash 62 | df -hT | grep log2ram | awk '{print " Name: " $1 "\nMount: " $7 "\n Type: " $2 "\nUsage: " $6 "\n Size: " $3 "\n Used: " $4 "\n Free: " $5}' 63 | ``` 64 | Returns: 65 | ```bash 66 | Name: log2ram 67 | Mount: /var/log 68 | Type: tmpfs 69 | Usage: 72% 70 | Size: 128M 71 | Used: 93M 72 | Free: 36M 73 | ``` 74 | 75 | Or also: 76 | 77 | ```bash 78 | mount | grep log2ram | awk -F'[ ()]+' '{print " Name: " $1 "\n Mount: " $3 "\n Type: " $5 "\nOptions: " $6}' 79 | ``` 80 | Returns: 81 | ```bash 82 | Name: log2ram 83 | Mount: /var/log 84 | Type: tmpfs 85 | Options: rw,nosuid,nodev,noexec,noatime,size=131072k,mode=755,uid=100000,gid=100000,inode64 86 | ``` 87 | 88 | If you do not get any line as response of these commands, something is not working. Refer to [this section](#is-it-working). 89 | 90 | ## Upgrading 91 | 92 | You need to stop Log2Ram (`systemctl stop log2ram`) and execute the [installation](#installation) process. If you used APT, this will be done automatically. 93 | 94 | ## Customization 95 | 96 | #### Variables 97 | In the file `/etc/log2ram.conf`, there are nine variables: 98 | 99 | - `SIZE`: defines the size the log folder will reserve into the RAM (default is `128M`). 100 | - `USE_RSYNC`: (commented out by default = `true`) use `cp` instead of `rsync` (if set to `false`). 101 | - `NOTIFICATION`: disables the notification system mail if there is not enough place in RAM (if set to `false`). 102 | - `NOTIFICATION_COMMAND`: Specify the command for sending error notifications (By default, it uses the `mail` command). 103 | - `PATH_DISK`: activate log2ram for other path than default one. Paths should be separated with a `;`. 104 | - `JOURNALD_AWARE`: enable log rotation for journald logs before syncing. (default is `true`). Check the comment in the config file or the [Troubleshooting](#Troubleshooting) section below for journald SystemMaxUse recommendations. 105 | - `ZL2R`: enable zram compatibility (`false` by default). Check the comment in the config file. See https://github.com/StuartIanNaylor/zram-swap-config to configure a zram space on your raspberry before enabling this option. 106 | - `COMP_ALG`: choose a compression algorithm from those listed in /proc/crypto. (default is `lz4`). See [Compressor](#Compressor) section below for options. 107 | - `LOG_DISK_SIZE`: specifies the uncompressed zram disk size 108 | 109 | #### Refresh time 110 | 111 | By default, Log2Ram writes to disk every day. If you think this is too much, you can run `systemctl edit log2ram-daily.timer` and for example add: 112 | 113 | ```ini 114 | [Timer] 115 | OnCalendar= 116 | OnCalendar=Mon *-*-* 23:55:00 117 | ``` 118 | 119 | Note: 120 | The ``OnCalendar=`` is important because it disables all existing times (e.g. the default one) for log2ram. 121 | 122 | ... Or even disable it altogether with `systemctl disable log2ram-daily.timer`, if you instead prefer Log2Ram to be writing logs only on system stops/reboots. 123 | 124 | #### Compressor 125 | Compressor for ZRAM. Useful for the `COMP_ALG` of ZRAM in the config file. 126 | 127 | | Compressor name | Ratio | Compression | Decompress. | 128 | |------------------------|----------|-------------|-------------| 129 | |zstd 1.3.4 -1 | 2.877 | 470 MB/s | 1380 MB/s | 130 | |zlib 1.2.11 -1 | 2.743 | 110 MB/s | 400 MB/s | 131 | |brotli 1.0.2 -0 | 2.701 | 410 MB/s | 430 MB/s | 132 | |quicklz 1.5.0 -1 | 2.238 | 550 MB/s | 710 MB/s | 133 | |lzo1x 2.09 -1 | 2.108 | 650 MB/s | 830 MB/s | 134 | |lz4 1.8.1 | 2.101 | 750 MB/s | 3700 MB/s | 135 | |snappy 1.1.4 | 2.091 | 530 MB/s | 1800 MB/s | 136 | |lzf 3.6 -1 | 2.077 | 400 MB/s | 860 MB/s | 137 | 138 | ###### Now, muffins for everyone! 139 | 140 | ## Troubleshooting 141 | 142 | ### Existing content in `/var/log` too large for RAM 143 | 144 | One thing that stops Log2Ram from functioning is if `/var/log` is too large before starting Log2Ram the first time. This can happen if logs had been collected for a long time before installing Log2Ram itself. Find the largest directories in `/var/log` (this example command only shows the 3 largest): 145 | 146 | ```bash 147 | sudo du -hs /var/log/* | sort -h | tail -n 3 148 | ``` 149 | 150 | If the `/var/log/journal` is very large, then there are a lot of system logs. Deletion of old "archived" logs can be fixed by adjusting a setting. Edit the `/etc/systemd/journald.conf` file and add the following option: 151 | 152 | ```bash 153 | SystemMaxUse=20M 154 | ``` 155 | 156 | **Or** the more radical version of directly flushing the journal to a size that matches log2ram size imediately _(Be aware that this flish flush the systemd journal logs imediately to the given size!)_ 157 | 158 | ```bash 159 | journalctl --vacuum-size=32M 160 | ``` 161 | 162 | This should be set to a value smaller than the size of the RAM volume; for example, half of it could be fine. Then, apply the new setting: 163 | 164 | ```bash 165 | sudo systemctl restart systemd-journald 166 | ``` 167 | 168 | This should shrink the size of "archived" logs to be below the newly imposed limit. Reboot and check that Log2Ram now works properly: 169 | 170 | ```bash 171 | sudo reboot 172 | ``` 173 | 174 | Wait until system reboots... 175 | 176 | ```bash 177 | systemctl status log2ram 178 | ``` 179 | 180 | ## Uninstallation :( 181 | 182 | (Because sometimes we need it) 183 | 184 | ### Via APT 185 | 186 | ```bash 187 | sudo apt remove log2ram 188 | ``` 189 | 190 | You can add the `--purge` argument to remove Log2Ram config files as well. 191 | 192 | ### Manually 193 | 194 | ```bash 195 | chmod +x /usr/local/bin/uninstall-log2ram.sh && sudo /usr/local/bin/uninstall-log2ram.sh 196 | ``` 197 | -------------------------------------------------------------------------------- /ansible_playbook/install_log2ram.yml: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ansible-playbook 2 | --- 3 | # Configure Raspberry Pi to log to RAM, with occasional SD card sync 4 | # to reduce SD card writes 5 | # Usage: ansible-playbook -e 'log2ram_size=80M' install_log2ram.yml 6 | 7 | - hosts: all 8 | gather_facts: true 9 | gather_subset: min 10 | become: true 11 | 12 | 13 | vars: 14 | log2ram_repo_url: http://packages.azlux.fr 15 | log2ram_gpg: https://azlux.fr/repo.gpg 16 | log2ram_keyring: /usr/share/keyrings/azlux-archive-keyring.gpg 17 | log2ram_apt_repository: "deb [signed-by={{ log2ram_keyring }}] {{ log2ram_repo_url }}/{{ ansible_distribution | lower }} {{ ansible_distribution_release }} main" 18 | 19 | log2ram_size: 128M 20 | log2ram_use_rsync: true 21 | log2ram_notification: true 22 | log2ram_notification_command: 'mail -s "Log2Ram Error on $HOSTNAME"' 23 | log2ram_path_disk: /var/log 24 | log2ram_use_z2lr: false 25 | log2ram_comp_alg: lz4 26 | log2ram_log_disk_size: 256M 27 | 28 | 29 | tasks: 30 | - name: Add rsync as pre-requisite 31 | apt: 32 | name: rsync 33 | when: log2ram_use_rsync 34 | 35 | - name: Install GnuPG 36 | apt: 37 | name: gnupg 38 | 39 | - name: Add gpg key 40 | shell: 41 | cmd: > 42 | curl -fsSL {{ log2ram_gpg }} | gpg --dearmor --yes -o {{ log2ram_keyring }} 43 | creates: "{{ log2ram_keyring }}" 44 | 45 | - name: Add apt repository 46 | apt_repository: 47 | repo: "{{ log2ram_apt_repository }}" 48 | filename: log2ram 49 | register: log2ram_apt_repo 50 | 51 | - name: Update apt cache 52 | apt: 53 | update_cache: true 54 | when: log2ram_apt_repo is changed 55 | 56 | - name: Install log2ram 57 | apt: 58 | name: log2ram 59 | notify: Restart log2ram 60 | 61 | - name: Set config options 62 | lineinfile: 63 | path: /etc/log2ram.conf 64 | regexp: "{{ item.regexp }}" 65 | line: "{{ item.line }}" 66 | backrefs: true 67 | loop: 68 | - {regexp: '^SIZE=(.*)$', line: 'SIZE={{ log2ram_size }}'} 69 | - {regexp: 'USE_RSYNC=(.*)$', line: 'USE_RSYNC={{ log2ram_use_rsync }}'} 70 | - {regexp: '^NOTIFICATION=(.*)$', line: 'NOTIFICATION={{ log2ram_notification }}'} 71 | - {regexp: '^NOTIFICATION_COMMAND=(.*)$', line: 'NOTIFICATION_COMMAND={{ log2ram_notification_command }}'} 72 | - {regexp: '^PATH_DISK=(.*)$', line: 'PATH_DISK="{{ log2ram_path_disk }}"'} 73 | - {regexp: '^ZL2R=(.*)$', line: 'ZL2R={{ log2ram_use_z2lr|lower }}'} 74 | - {regexp: '^COMP_ALG=(.*)$', line: 'COMP_ALG={{ log2ram_comp_alg }}'} 75 | - {regexp: '^LOG_DISK_SIZE=(.*)$', line: 'LOG_DISK_SIZE={{ log2ram_log_disk_size }}'} 76 | notify: Restart log2ram 77 | 78 | 79 | handlers: 80 | - name: Restart log2ram 81 | systemd: 82 | name: log2ram 83 | state: restarted 84 | -------------------------------------------------------------------------------- /build-packages.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Exit the script if any of the commands fail 4 | set -e 5 | set -u 6 | set -o pipefail 7 | 8 | # Set working directory to the location of this script 9 | cd "$(dirname "${BASH_SOURCE[0]}")" 10 | 11 | STARTDIR="$(pwd)" 12 | DESTDIR="$STARTDIR/pkg" 13 | OUTDIR="$STARTDIR/deb" 14 | # get version 15 | repo="azlux/log2ram" 16 | api=$(curl --silent "https://api.github.com/repos/$repo/releases" | jq ".[0]") 17 | new=$(echo $api | grep -Po '"tag_name": "\K.*?(?=")') 18 | 19 | # Remove potential leftovers from a previous build 20 | rm -rf "$DESTDIR" "$OUTDIR" 21 | 22 | ## log2ram 23 | # Create directory 24 | install -Dm 644 "$STARTDIR/log2ram.service" "$DESTDIR/etc/systemd/system/log2ram.service" 25 | install -Dm 644 "$STARTDIR/log2ram-daily.service" "$DESTDIR/etc/systemd/system/log2ram-daily.service" 26 | install -Dm 644 "$STARTDIR/log2ram-daily.timer" "$DESTDIR/etc/systemd/system/log2ram-daily.timer" 27 | install -Dm 755 "$STARTDIR/log2ram" "$DESTDIR/usr/local/bin/log2ram" 28 | install -Dm 644 "$STARTDIR/log2ram.conf" "$DESTDIR/etc/log2ram.conf" 29 | install -Dm 644 "$STARTDIR/uninstall.sh" "$DESTDIR/usr/local/bin/uninstall-log2ram.sh" 30 | 31 | # logrotate 32 | install -Dm 644 "$STARTDIR/log2ram.logrotate" "$DESTDIR/etc/logrotate.d/log2ram" 33 | 34 | # Build .deb 35 | mkdir "$DESTDIR/DEBIAN" "$OUTDIR" 36 | cp "$STARTDIR/debian/"* "$DESTDIR/DEBIAN/" 37 | 38 | # Set version 39 | sed -i "s/VERSION-TO-REPLACE/$new/" "$DESTDIR/DEBIAN/control" 40 | 41 | dpkg-deb --build "$DESTDIR" "$OUTDIR" 42 | -------------------------------------------------------------------------------- /debian/conffiles: -------------------------------------------------------------------------------- 1 | /etc/log2ram.conf 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Package: log2ram 2 | Version: VERSION-TO-REPLACE 3 | Depends: bash (>= 4.3) 4 | Section: net 5 | Priority: optional 6 | Architecture: all 7 | Maintainer: Azlux 8 | Description: ramlog like for systemd (Put log into a ram folder) 9 | Homepage: https://github.com/azlux/log2ram 10 | Bugs: https://github.com/azlux/log2ram/issues 11 | Recommends: rsync 12 | -------------------------------------------------------------------------------- /debian/postinst: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | systemctl daemon-reload 5 | systemctl enable log2ram.service log2ram-daily.timer 6 | 7 | 8 | rm -f /etc/cron.daily/log2ram 9 | rm -f /etc/cron.hourly/log2ram 10 | 11 | if [ "$1" == "configure" ]; then 12 | echo "##### Reboot to activate log2ram #####" 13 | echo "##### edit /etc/log2ram.conf to configure options ####" 14 | fi 15 | 16 | exit 0 17 | -------------------------------------------------------------------------------- /debian/preinst: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | systemctl -q is-active log2ram.service && systemctl stop log2ram.service 3 | systemctl -q is-active log2ram-daily.timer && systemctl stop log2ram-daily.timer 4 | rm -rf /var/hdd.log 5 | 6 | exit 0 7 | -------------------------------------------------------------------------------- /debian/prerm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | case "$1" in 3 | upgrade) 4 | [ -d /run/systemd/system/ ] && systemctl stop log2ram.service log2ram-daily.timer 5 | exit 0 6 | ;; 7 | *) 8 | [ -d /run/systemd/system/ ] && systemctl stop log2ram.service log2ram-daily.timer 9 | [ -d /run/systemd/system/ ] && systemctl disable log2ram.service log2ram-daily.timer 10 | exit 0 11 | ;; 12 | esac 13 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | systemctl -q is-active log2ram && { 4 | echo "ERROR: log2ram service is still running. Please run \"sudo systemctl stop log2ram\" to stop it." 5 | exit 1 6 | } 7 | [ "$(id -u)" -eq 0 ] || { 8 | echo "You need to be ROOT (sudo can be used)" 9 | exit 1 10 | } 11 | 12 | # log2ram 13 | mkdir -p /usr/local/bin/ 14 | install -m 644 log2ram.service /etc/systemd/system/log2ram.service 15 | install -m 644 log2ram-daily.service /etc/systemd/system/log2ram-daily.service 16 | install -m 644 log2ram-daily.timer /etc/systemd/system/log2ram-daily.timer 17 | install -m 755 log2ram /usr/local/bin/log2ram 18 | if [ ! -f /etc/log2ram.conf ]; then 19 | install -m 644 log2ram.conf /etc/log2ram.conf 20 | fi 21 | install -m 644 uninstall.sh /usr/local/bin/uninstall-log2ram.sh 22 | systemctl enable log2ram.service log2ram-daily.timer 23 | 24 | # logrotate 25 | if [ -d /etc/logrotate.d ]; then 26 | install -m 644 log2ram.logrotate /etc/logrotate.d/log2ram 27 | else 28 | echo "##### Directory /etc/logrotate.d does not exist. #####" 29 | echo "##### Skipping log2ram.logrotate installation. #####" 30 | fi 31 | 32 | # Remove a previous log2ram version 33 | rm -rf /var/log.hdd 34 | 35 | # Make sure we start clean 36 | rm -rf /var/hdd.log 37 | 38 | echo "##### Reboot to activate log2ram #####" 39 | echo "##### edit /etc/log2ram.conf to configure options ####" 40 | -------------------------------------------------------------------------------- /log2ram: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | . /etc/log2ram.conf 4 | 5 | if [ -z "$PATH_DISK" ]; then 6 | PATH_DISK='/var/log' 7 | fi 8 | 9 | LOG_NAME='log2ram.log' 10 | NO_RSYNC=${USE_RSYNC#true} 11 | NOTIFICATION_COMMAND=${NOTIFICATION_COMMAND:=mail -s "Log2Ram Error on $HOSTNAME" root} 12 | NOTIFICATION=${NOTIFICATION:=true} 13 | 14 | ## @fn is_safe() 15 | ## @brief Check if hdd log exists 16 | is_safe() { 17 | [ -d "$HDD_LOG" ] || echo "ERROR: $HDD_LOG/ doesn't exist! Can't sync." 18 | [ -d "$HDD_LOG" ] || exit 1 19 | } 20 | 21 | ## @fn journald_logrotate() 22 | ## @brief Logrotate the journal if the current RAM_LOG path is part of the journald directory 23 | journald_logrotate() { 24 | if ! [ -x "$(command -v journalctl)" ] || ! [ "$JOURNALD_AWARE" = true ]; then 25 | return 1 26 | fi 27 | 28 | if journalctl --header | grep "File path" | grep "$RAM_LOG" >/dev/null 2>&1; then 29 | journalctl --rotate 30 | return 0 31 | else 32 | return 1 33 | fi 34 | } 35 | 36 | ## @fn sync_to_disk() 37 | ## @brief Sync memory back to hard disk 38 | sync_to_disk() { 39 | is_safe 40 | 41 | optional_params=() 42 | 43 | if journald_logrotate; then 44 | optional_params+=("--include=journal/*/*@*.journal") 45 | optional_params+=("--exclude=journal/*/*") 46 | fi 47 | 48 | if [ -z "${NO_RSYNC}" ] && [ -x "$(command -v rsync)" ]; then 49 | rsync -aAXv --sparse --inplace --no-whole-file --delete-after "${optional_params[@]}" "$RAM_LOG"/ "$HDD_LOG"/ 2>&1 | 50 | tee -a "$LOG2RAM_LOG" 51 | else 52 | cp -rfup --sparse=always "$RAM_LOG"/ -T "$HDD_LOG"/ 2>&1 | tee -a "$LOG2RAM_LOG" 53 | fi 54 | } 55 | 56 | ## @fn sync_from_disk() 57 | ## @brief Sync hard disk to memory 58 | sync_from_disk() { 59 | is_safe 60 | 61 | TP_SIZE=$SIZE 62 | if [ "$ZL2R" = true ]; then 63 | TP_SIZE=$LOG_DISK_SIZE 64 | fi 65 | 66 | if [ -n "$(du -sh -t "$TP_SIZE" "$HDD_LOG"/ | cut -f1)" ]; then 67 | echo "ERROR: RAM disk for \"$HDD_LOG/\" too small. Can't sync." 68 | echo -e "File(s) causing issues\n: $(du -sh -t "$TP_SIZE" "$HDD_LOG"/*)" 69 | umount -l "$RAM_LOG"/ 70 | umount -l "$HDD_LOG"/ 71 | if [ "$NOTIFICATION" = true ]; then 72 | echo "LOG2RAM : No place on RAM for \"$HDD_LOG/\" anymore, fallback on the disk" | $NOTIFICATION_COMMAND 73 | fi 74 | exit 1 75 | fi 76 | 77 | if [ -z "${NO_RSYNC}" ] && [ -x "$(command -v rsync)" ]; then 78 | rsync -aAXv --sparse --inplace --no-whole-file --delete-after "$HDD_LOG"/ "$RAM_LOG"/ 2>&1 | tee -a "$LOG2RAM_LOG" 79 | else 80 | cp -rfup --sparse=always "$HDD_LOG"/ -T "$RAM_LOG"/ 2>&1 | tee -a "$LOG2RAM_LOG" 81 | fi 82 | 83 | } 84 | 85 | ## @fn wait_for() 86 | ## @brief Wait for directory and create test file to make sure the directory exists 87 | ## @param param1 path to the directory 88 | wait_for() { 89 | WAIT_PATH="$1" 90 | while ! findmnt "$WAIT_PATH" >/dev/null; do 91 | sleep 0.1 92 | done 93 | 94 | while [ ! -f "$WAIT_PATH/log2ram.test" ]; do 95 | touch "$WAIT_PATH/log2ram.test" 96 | sleep 0.1 97 | done 98 | rm "$WAIT_PATH/log2ram.test" 99 | } 100 | 101 | ## @fn create_zram_log_drive() 102 | ## @brief Create zram log device 103 | create_zram_log_drive() { 104 | # Check Zram Class created 105 | if [ ! -d "/sys/class/zram-control" ]; then 106 | modprobe zram 107 | RAM_DEV='0' 108 | else 109 | RAM_DEV=$(cat /sys/class/zram-control/hot_add) 110 | fi 111 | echo "$COMP_ALG" >"/sys/block/zram${RAM_DEV}/comp_algorithm" 112 | echo "$LOG_DISK_SIZE" >"/sys/block/zram${RAM_DEV}/disksize" 113 | echo "$SIZE" >"/sys/block/zram${RAM_DEV}/mem_limit" 114 | mke2fs -t ext4 "/dev/zram${RAM_DEV}" 115 | } 116 | 117 | case "$1" in 118 | start) 119 | IFS=';' 120 | for i in $PATH_DISK; do 121 | # Skip the path if the folder doesn't exist 122 | [ ! -d "$i" ] && continue 123 | 124 | PATH_FIRST_PART="${i%/*}" 125 | PATH_LAST_PART="${i##/*/}" 126 | RAM_LOG="$i" 127 | HDD_LOG="${PATH_FIRST_PART}/hdd.${PATH_LAST_PART}" 128 | LOG2RAM_LOG="${RAM_LOG}/${LOG_NAME}" 129 | 130 | [ -d "$HDD_LOG" ] || mkdir "$HDD_LOG" 131 | 132 | mount --bind "$RAM_LOG"/ "$HDD_LOG"/ 133 | mount --make-private "$HDD_LOG"/ 134 | wait_for "$HDD_LOG" 135 | 136 | if [ "$ZL2R" = true ]; then 137 | create_zram_log_drive 138 | mount -t ext4 -o nosuid,noexec,noatime,nodev,user=log2ram "/dev/zram${RAM_DEV}" "$RAM_LOG"/ 139 | else 140 | mount -t tmpfs -o "nosuid,noexec,noatime,nodev,mode=0755,size=${SIZE}" log2ram "$RAM_LOG"/ 141 | fi 142 | wait_for "$RAM_LOG" 143 | sync_from_disk 144 | done 145 | exit 0 146 | ;; 147 | 148 | stop) 149 | IFS=';' 150 | for i in $PATH_DISK; do 151 | PATH_FIRST_PART="${i%/*}" 152 | PATH_LAST_PART="${i##/*/}" 153 | RAM_LOG="$i" 154 | HDD_LOG="${PATH_FIRST_PART}/hdd.${PATH_LAST_PART}" 155 | LOG2RAM_LOG="${RAM_LOG}/${LOG_NAME}" 156 | 157 | sync_to_disk 158 | #ZRAM_LOG=$(awk '$2 == "/var/log" {print $1}' /proc/mounts) 159 | #ZRAM_LOG=$(echo ${ZRAM_LOG} | grep -o -E '[0-9]+') 160 | umount -l "$RAM_LOG"/ 161 | umount -l "$HDD_LOG"/ 162 | # Unsure as even with Root permision denied 163 | #echo ${ZRAM_LOG} > /sys/class/zram-control/hot_remove 164 | done 165 | exit 0 166 | ;; 167 | 168 | write) 169 | IFS=';' 170 | for i in $PATH_DISK; do 171 | PATH_FIRST_PART="${i%/*}" 172 | PATH_LAST_PART="${i##/*/}" 173 | RAM_LOG="$i" 174 | HDD_LOG="${PATH_FIRST_PART}/hdd.${PATH_LAST_PART}" 175 | LOG2RAM_LOG="${RAM_LOG}/${LOG_NAME}" 176 | 177 | sync_to_disk 178 | done 179 | exit 0 180 | ;; 181 | 182 | *) 183 | echo 'Usage: log2ram {start|stop|write}' >&2 184 | exit 1 185 | ;; 186 | esac 187 | -------------------------------------------------------------------------------- /log2ram-daily.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Daily Log2Ram writing activities 3 | After=log2ram.service 4 | Documentation=https://github.com/azlux/log2ram 5 | 6 | [Service] 7 | ExecStart=/bin/systemctl reload log2ram.service 8 | -------------------------------------------------------------------------------- /log2ram-daily.timer: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Daily Log2Ram writing activities 3 | 4 | [Timer] 5 | OnCalendar=*-*-* 23:55:00 6 | Persistent=true 7 | 8 | [Install] 9 | WantedBy=timers.target 10 | -------------------------------------------------------------------------------- /log2ram.conf: -------------------------------------------------------------------------------- 1 | # Configuration file for Log2Ram (https://github.com/azlux/log2ram) under MIT license. 2 | # This configuration file is read by the log2ram service 3 | 4 | # Specify the amount of RAM reserved for storing logs. This setting determines the maximum size of the RAM folder. 5 | # Ensure 'SIZE=' is set larger than the current size of your /var/log directory to prevent startup failures. 6 | # Also, configure logrotate to manage log growth and prevent the /var/log directory from exceeding this reserved size. 7 | # The default setting of 128M suffices for many typical applications, but you may need to increase it for 8 | # servers or systems that generate extensive logging. 9 | SIZE=128M 10 | 11 | # Select the log syncing method between disk and RAM: 12 | # - 'rsync' is the default unless 'USE_RSYNC' is set to 'false'. 13 | # - If 'rsync' is unavailable, 'cp' is automatically used as a fallback. 14 | # - Set 'USE_RSYNC' to 'false' to explicitly use 'cp'. 15 | #USE_RSYNC=false 16 | 17 | # By default, if there is insufficient RAM space, a system notification email is sent. 18 | # Set this to 'false' to disable email notifications. (The error will still be logged locally). 19 | #NOTIFICATION=true 20 | 21 | # Specify the command for sending error notifications. 22 | # By default, it uses the `mail` command to send an email, with the message body provided via stdin. 23 | # You can replace this with any command (such as 'shoutrrr') or a custom script for handling notifications. 24 | #NOTIFICATION_COMMAND=mail -s "Log2Ram Error on $HOSTNAME" 25 | 26 | # Specify the directories to be stored in RAM. List each directory using its absolute path, e.g., `/path/folder`. 27 | # Corresponding directories on the HDD, named `/path/hdd.folder`, will be automatically created for each listed path. 28 | # Separate multiple paths with a semicolon `;` and do not include a trailing slash at the end of the paths. 29 | # Example: PATH_DISK="/var/log;/home/test/FolderInRam" 30 | PATH_DISK="/var/log" 31 | 32 | # Set to 'true' to enable log rotation for journald logs before syncing. 33 | # Note: 'rsync' must be used for this feature to work. 34 | # Ensure 'SystemMaxUse' is configured in '/etc/systemd/journald.conf' (to limit journald’s disk usage) 35 | # Note: Its value must be smaller than log2ram's RAM allocation defined by the SIZE variable above. 36 | JOURNALD_AWARE=true 37 | 38 | 39 | # **************** Zram backing conf **************** 40 | 41 | # Set ZL2R=true to enable zram, providing compressed RAM storage for log2ram. 42 | # Set ZL2R=false to use tmpfs, which provides uncompressed memory-only storage. 43 | ZL2R=false 44 | 45 | # Choose a compression algorithm from those listed in /proc/crypto. 46 | # 'lz4' is the fastest, offering the lightest CPU load but lower compression ratios. 47 | # 'deflate' (zlib) and 'Zstandard' (zstd) provide higher compression ratios but use more CPU. 48 | # 'lzo' is similar to 'lz4' but may perform better with certain binaries due to optimizations. 49 | # Set COMP_ALG to 'lz4' for speed, 'zstd' for better compression, or 'lzo' or 'zlib' if optimizations or availability are concerns. 50 | COMP_ALG=lz4 51 | 52 | # LOG_DISK_SIZE specifies the uncompressed zram disk size. 53 | # (Sets the size of the zram disk that will be presented to the operating system). 54 | # To estimate amount of RAM this will consume, divide LOG_DISK_SIZE by your chosen compression algorithm's ratio: 55 | # - lzo/lz4 typically compresses at a ratio of 2.1:1 56 | # - zlib compresses at about 2.7:1 57 | # - zstandard (zstd) achieves around 2.9:1 58 | # Example calculation using lz4: 59 | # Given LOG_DISK_SIZE = 256M (which represents 256 Megabytes of uncompressed log data), 60 | # the estimated zram RAM usage = 256 MB / 2.1 ≈ 122 MB of RAM. 61 | LOG_DISK_SIZE=256M 62 | -------------------------------------------------------------------------------- /log2ram.logrotate: -------------------------------------------------------------------------------- 1 | /var/log/log2ram.log 2 | { 3 | rotate 7 4 | daily 5 | missingok 6 | notifempty 7 | delaycompress 8 | compress 9 | } 10 | 11 | -------------------------------------------------------------------------------- /log2ram.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Log2Ram 3 | DefaultDependencies=no 4 | Before=basic.target rsyslog.service syslog-ng.service syslog.target systemd-journald.service sysinit.target shutdown.target zram-swap-conf.service apache2.service lighttpd.service 5 | After=local-fs.target 6 | Conflicts=shutdown.target reboot.target halt.target 7 | RequiresMountsFor=/var/log /var/hdd.log 8 | IgnoreOnIsolate=yes 9 | Documentation=https://github.com/azlux/log2ram 10 | 11 | [Service] 12 | Type=oneshot 13 | ExecStart=/usr/local/bin/log2ram start 14 | ExecStop=/usr/local/bin/log2ram stop 15 | ExecReload=/usr/local/bin/log2ram write 16 | TimeoutStartSec=120 17 | RemainAfterExit=yes 18 | 19 | [Install] 20 | WantedBy=sysinit.target 21 | -------------------------------------------------------------------------------- /uninstall.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if dpkg -l log2ram 2>/dev/null; then 4 | echo "Please run : apt remove log2ram" 5 | exit 1 6 | fi 7 | 8 | if [ "$(id -u)" -eq 0 ]; then 9 | echo "Not apt installed. Remove will continue with this script..." 10 | systemctl stop log2ram.service log2ram-daily.timer 11 | systemctl disable log2ram.service log2ram-daily.timer 12 | rm -rf /etc/systemd/system/log2ram* 13 | rm /usr/local/bin/log2ram 14 | rm /etc/log2ram.conf 15 | rm -f /etc/logrotate.d/log2ram 16 | 17 | if [ -d /var/hdd.log ]; then 18 | rm -r /var/hdd.log 19 | fi 20 | echo "Log2Ram is uninstalled, removing the uninstaller in progress" 21 | rm /usr/local/bin/uninstall-log2ram.sh 22 | echo "##### Reboot isn't needed #####" 23 | else 24 | echo "You need to be ROOT (sudo can be used)" 25 | fi 26 | --------------------------------------------------------------------------------