Repository: foundObjects/zram-swap
Branch: master
Commit: 205ea1ec5b16
Files: 7
Total size: 13.8 KB
Directory structure:
gitextract_qcf21njh/
├── .gitignore
├── LICENSE
├── README.md
├── install.sh
├── service/
│ ├── zram-swap.config
│ └── zram-swap.service
└── zram-swap.sh
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
zram-swap/
src/
pkg/
*.pkg.tar.*
*.log.*
*.log
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2019 Scott B
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# zram-swap
A simple zram swap script for modern systemd Linux
https://github.com/foundObjects/zram-swap
### Why?
I wrote zram-swap because I couldn't find a simple modern replacement for the Ubuntu
`zram-config` package that included basic error handling, didn't make device sizing
mistakes and kept user-facing configuration straightforward and easy to understand.
### Installation and Usage
*Arch Linux:*
Install from the AUR: `paru -S zram-swap-git`
or directly from GitHub:
```sh
mkdir zram-swap-git && cd zram-swap-git
wget https://raw.githubusercontent.com/foundObjects/zram-swap/arch-packaging/PKGBUILD
makepkg -Cci
```
You'll need to start and enable `zram-swap.service` after installation on Arch.
Make any configuration changes to `/etc/default/zram-swap` first if desired, see below for details.
*Others:*
```sh
git clone https://github.com/foundObjects/zram-swap.git
cd zram-swap && sudo ./install.sh
```
The install script starts the zram-swap.service automatically after installation
and enables the systemd service during boot. The default allocation creates an lz4
zram device that should use around half of physical memory when completely full.
I chose lz4 as the default to give low spec machines (systems that often see
the greatest benefit from swap on zram) every performance edge I could.
While lzo-rle is quite fast on modern high-performance hardware a machine like a
Raspberry Pi or a low spec laptop appreciates every speed advantage I can give it.
### Configuration
Edit `/etc/default/zram-swap` if you'd like to change the compression algorithm or
swap allocation and then restart zram-swap with `systemctl restart zram-swap.service`.
The configuration file is heavily commented and self-documenting.
A very simple configuration that's expected to use roughly 2GB RAM might look
something like:
```sh
# override fractional calculations and specify a fixed swap size
_zram_fixedsize="6G"
# compression algorithm to employ (lzo, lz4, zstd, lzo-rle)
_zram_algorithm="lzo-rle"
```
Remember that the ZRAM device size references uncompressed data, real memory
utilization should be ~2-3x smaller than the zram device size due to compression.
#### A quick note RE: compression algorithms:
The default configuration using lz4 should work well for most people. lzo may
provide slightly better RAM utilization at a cost of slightly more expensive
decompression. zstd should provide better compression than lz\* and still be
moderately fast on most machines. On very modern kernels and reasonably fast
hardware the most balanced choice is probably lzo-rle. On low spec machines
(ARM SBCs, ARM laptops, thin clients, etc) you'll probably want to stick with
lz4.
### Debugging
To view a script debug trace either start zram-swap.sh with `zram-swap.sh -x (start|stop)`
or uncomment the debug flag in `/etc/default/zram-swap`:
```sh
# setting _zram_swap_debugging to any non-zero value enables debugging
# default: undefined
_zram_swap_debugging="beep boop"
```
### Compatibility
Tested on Linux 4.4 through Linux 5.14.
Requirements are minimal; Underneath the systemd service wrapper the swap setup
script needs only a posix shell, `modprobe`, `zramctl` and very basic `awk` and
`grep` support to function. It should work in pretty much any modern Linux
environment.
================================================
FILE: install.sh
================================================
#!/bin/sh
# source: https://github.com/foundObjects/zram-swap
# shellcheck disable=SC2039,SC2162
#[ "$(id -u)" -eq '0' ] || { echo "This script requires root." && exit 1; }
case "$(readlink /proc/$$/exe)" in */bash) set -euo pipefail ;; *) set -eu ;; esac
# ensure a predictable environment
export PATH=/usr/sbin:/usr/bin:/sbin:/bin
\unalias -a
# installer main body:
_main() {
# ensure $1 exists so 'set -u' doesn't error out
{ [ "$#" -eq "0" ] && set -- ""; } > /dev/null 2>&1
case "$1" in
"--uninstall")
# uninstall, requires root
assert_root
_uninstall
;;
"--install" | "")
# install dpkg hooks, requires root
assert_root
_install "$@"
;;
*)
# unknown flags, print usage and exit
_usage
;;
esac
exit 0
}
_install() {
configdiff=''
newconfig=''
if systemctl -q is-active zram-swap.service; then
echo "Stopping zram-swap service"
systemctl stop zram-swap.service
fi
echo "Installing script and service ..."
install -o root zram-swap.sh /usr/local/sbin/zram-swap.sh
install -o root -m 0644 service/zram-swap.service /etc/systemd/system/zram-swap.service
# rename & cleanup old version config file
if [ -f /etc/default/zram-swap-service ]; then
mv -f /etc/default/zram-swap-service /etc/default/zram-swap
chown root:root /etc/default/zram-swap
chmod 0644 /etc/default/zram-swap
fi
if [ -f /etc/default/zram-swap ]; then
{
set +e
configdiff=$(diff -y /etc/default/zram-swap service/zram-swap.config)
set -e
} > /dev/null 2>&1
if [ -n "$configdiff" ]; then
yn=''
echo "Local configuration differs from packaged version"
echo
echo "Install package default configuration? Local config will be saved as /etc/default/zram-swap.oldconfig"
while true; do
echo "(I)nstall package default / (K)eep local configuration / View (D)iff"
printf "[i/k/d]: "
read yn
case "$yn" in
[Ii]*)
echo "Installing package default ..."
install -o root -m 0644 --backup --suffix=".oldconfig" service/zram-swap.config /etc/default/zram-swap
newconfig='y'
break
;;
[Kk]*) break ;;
[Dd]*) printf "%s\n\n" "$configdiff" ;;
esac
done
fi
else
install -o root -m 0644 -b service/zram-swap.config /etc/default/zram-swap
fi
echo "Reloading systemd unit files and enabling boot-time service ..."
systemctl daemon-reload
systemctl enable zram-swap.service
if [ -n "$newconfig" ]; then
cat <<- HEREDOC
Configuration file updated; old config saved as /etc/default/zram-swap.oldconfig
Please review changes between configurations and then start the service with
systemctl start zram-swap.service
HEREDOC
else
echo "Starting zram-swap service ..."
systemctl start zram-swap.service
fi
echo
echo "zram-swap service installed successfully!"
echo
}
_uninstall() {
if systemctl -q is-active zram-swap.service; then
echo "Stopping zram-swap service"
systemctl stop zram-swap.service
fi
echo "Uninstalling script and systemd service."
if [ -f /etc/systemd/system/zram-swap.service ]; then
systemctl disable zram-swap.service || true
rm -f /etc/systemd/system/zram-swap.service
fi
if [ -f /usr/local/sbin/zram-swap.sh ]; then
rm -f /usr/local/sbin/zram-swap.sh
fi
echo "Reloading systemd unit files"
systemctl daemon-reload
echo "zram-swap service uninstalled; remove configuration /etc/default/zram-swap if desired"
}
assert_root() { [ "$(id -u)" -eq '0' ] || { echo "This action requires root." && exit 1; }; }
_usage() { echo "Usage: $(basename "$0") (--install|--uninstall)"; }
_main "$@"
================================================
FILE: service/zram-swap.config
================================================
# compression algorithm to employ (lzo, lz4, zstd, lzo-rle)
# default: lz4
_zram_algorithm="lz4"
# portion of system ram to use as zram swap (expression: "1/2", "2/3", "0.5", etc)
# default: "1/2"
_zram_fraction="1/2"
# setting _zram_swap_debugging to any non-zero value enables debugging
# default: undefined
#_zram_swap_debugging="beep boop"
# expected compression factor; set this by hand if your compression results are
# drastically different from the estimates below
#
# Note: These are the defaults coded into /usr/local/sbin/zram-swap.sh; don't alter
# these values, use the override variable '_comp_factor' below.
#
# defaults if otherwise unset:
# lzo*|zstd) _comp_factor="3" ;; # expect 3:1 compression from lzo*, zstd
# lz4) _comp_factor="2.5" ;; # expect 2.5:1 compression from lz4
# *) _comp_factor="2" ;; # default to 2:1 for everything else
#
#_comp_factor="2.5"
# if set skip device size calculation and create a fixed-size swap device
# (size, in MiB/GiB, eg: "250M" "500M" "1.5G" "2G" "6G" etc.)
#
# Note: this is the swap device size before compression, real memory use will
# depend on compression results, a 2-3x reduction is typical
#
#_zram_fixedsize="2G"
# vim:ft=sh:ts=2:sts=2:sw=2:et:
================================================
FILE: service/zram-swap.service
================================================
[Unit]
Description=zram swap service
Requires=systemd-modules-load.service
Before=shutdown.target
#After=
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/zram-swap.sh start
ExecStop=/usr/local/sbin/zram-swap.sh stop
RemainAfterExit=true
[Install]
WantedBy=sysinit.target
#RequiredBy=
# vim:ft=systemd
================================================
FILE: zram-swap.sh
================================================
#!/bin/sh
# source: https://github.com/foundObjects/zram-swap
# shellcheck disable=SC2013,SC2039,SC2064
[ "$(id -u)" -eq '0' ] || { echo "This script requires root." && exit 1; }
case "$(readlink /proc/$$/exe)" in */bash) set -euo pipefail ;; *) set -eu ;; esac
# ensure a predictable environment
export PATH=/usr/sbin:/usr/bin:/sbin:/bin
\unalias -a
# parse debug flag early so we can trace user configuration
[ "$#" -gt "0" ] && [ "$1" = "-x" ] && shift && set -x
# set sane defaults, see /etc/default/zram-swap for explanations
_zram_fraction="1/2"
_zram_algorithm="lz4"
_comp_factor=''
_zram_fixedsize=''
_zram_swap_debug=''
# load user config
[ -f /etc/default/zram-swap ] &&
. /etc/default/zram-swap
# support a debugging flag in the config file so people don't have to edit the systemd service
# to enable debugging
[ -n "$_zram_swap_debug" ] && set -x
# set expected compression ratio based on algorithm -- we'll use this to
# calculate how much uncompressed swap data we expect to fit into our
# target ram allocation. skip if already set in user config
if [ -z "$_comp_factor" ]; then
case $_zram_algorithm in
lzo* | zstd) _comp_factor="3" ;;
lz4) _comp_factor="2.5" ;;
*) _comp_factor="2" ;;
esac
fi
# main script:
_main() {
if ! modprobe zram; then
err "main: Failed to load zram module, exiting"
return 1
fi
# make sure `set -u` doesn't cause 'case "$1"' to throw errors below
{ [ "$#" -eq "0" ] && set -- ""; } > /dev/null 2>&1
case "$1" in
"init" | "start")
if grep -q zram /proc/swaps; then
err "main: zram swap already in use, exiting"
return 1
fi
_init
;;
"end" | "stop")
if ! grep -q zram /proc/swaps; then
err "main: no zram swaps to cleanup, exiting"
return 1
fi
_end
;;
"restart")
# TODO: stub for restart support
echo "not supported yet"
_usage
exit 1
;;
*)
_usage
exit 1
;;
esac
}
# initialize swap
_init() {
if [ -n "$_zram_fixedsize" ]; then
if ! _regex_match "$_zram_fixedsize" '^[[:digit:]]+(\.[[:digit:]]+)?(G|M)$'; then
err "init: Invalid size '$_zram_fixedsize'. Format sizes like: 100M 250M 1.5G 2G etc."
exit 1
fi
# Use user supplied zram size
mem="$_zram_fixedsize"
else
# Calculate memory to use for zram
totalmem=$(awk '/MemTotal/{print $2}' /proc/meminfo)
mem=$(calc "$totalmem * $_comp_factor * $_zram_fraction * 1024")
fi
# NOTE: zramctl sometimes fails if we don't wait for the module to settle after loading
# we'll retry a couple of times with slightly increasing delays before giving up
_device=''
for i in $(seq 3); do
# sleep for "0.1 * $i" seconds rounded to 2 digits
sleep "$(calc 2 "0.1 * $i")"
_device=$(zramctl -f -s "$mem" -a "$_zram_algorithm") || true
[ -b "$_device" ] && break
done
if [ -b "$_device" ]; then
# cleanup the device if swap setup fails
trap "_rem_zdev $_device" EXIT
mkswap "$_device"
swapon -d -p 15 "$_device"
trap - EXIT
return 0
else
err "init: Failed to initialize zram device"
return 1
fi
}
# end swapping and cleanup
_end() {
ret="0"
for dev in $(awk '/zram/ {print $1}' /proc/swaps); do
swapoff "$dev"
if ! _rem_zdev "$dev"; then
err "end: Failed to remove zram device $dev"
ret=1
fi
done
return "$ret"
}
# Remove zram device with retry
_rem_zdev() {
if [ ! -b "$1" ]; then
err "rem_zdev: No zram device '$1' to remove"
return 1
fi
for i in $(seq 3); do
# sleep for "0.1 * $i" seconds rounded to 2 digits
sleep "$(calc 2 "0.1 * $i")"
zramctl -r "$1" || true
[ -b "$1" ] || break
done
if [ -b "$1" ]; then
err "rem_zdev: Couldn't remove zram device '$1' after 3 attempts"
return 1
fi
return 0
}
# posix substitute for bash pattern matching [[ $foo =~ bar-pattern ]]
# usage: _regex_match "$foo" "bar-pattern"
_regex_match() { echo "$1" | grep -Eq -- "$2" > /dev/null 2>&1; }
# calculate with variable precision
# usage: calc (int; precision := 0) (str; expr to evaluate)
calc() {
_regex_match "$1" '^[[:digit:]]+$' && { n="$1" && shift; } || n=0
LC_NUMERIC=C awk "BEGIN{printf \"%.${n}f\", $*}"
}
err() { echo "Err $*" >&2; }
_usage() { echo "Usage: $(basename "$0") (start|stop)"; }
_main "$@"
gitextract_qcf21njh/ ├── .gitignore ├── LICENSE ├── README.md ├── install.sh ├── service/ │ ├── zram-swap.config │ └── zram-swap.service └── zram-swap.sh
Condensed preview — 7 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (15K chars).
[
{
"path": ".gitignore",
"chars": 47,
"preview": "zram-swap/\nsrc/\npkg/\n*.pkg.tar.*\n*.log.*\n*.log\n"
},
{
"path": "LICENSE",
"chars": 1064,
"preview": "MIT License\n\nCopyright (c) 2019 Scott B\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof"
},
{
"path": "README.md",
"chars": 3309,
"preview": "# zram-swap\nA simple zram swap script for modern systemd Linux\n\nhttps://github.com/foundObjects/zram-swap\n\n### Why?\n\nI w"
},
{
"path": "install.sh",
"chars": 3776,
"preview": "#!/bin/sh\n# source: https://github.com/foundObjects/zram-swap\n# shellcheck disable=SC2039,SC2162\n\n#[ \"$(id -u)\" -eq '0' "
},
{
"path": "service/zram-swap.config",
"chars": 1250,
"preview": "# compression algorithm to employ (lzo, lz4, zstd, lzo-rle)\n# default: lz4\n_zram_algorithm=\"lz4\"\n\n# portion of system ra"
},
{
"path": "service/zram-swap.service",
"chars": 305,
"preview": "[Unit]\nDescription=zram swap service\nRequires=systemd-modules-load.service\nBefore=shutdown.target\n#After=\n\n[Service]\nTyp"
},
{
"path": "zram-swap.sh",
"chars": 4371,
"preview": "#!/bin/sh\n# source: https://github.com/foundObjects/zram-swap\n# shellcheck disable=SC2013,SC2039,SC2064\n\n[ \"$(id -u)\" -e"
}
]
About this extraction
This page contains the full source code of the foundObjects/zram-swap GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 7 files (13.8 KB), approximately 4.2k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.