Skip to content

Instantly share code, notes, and snippets.

@VolMi
Last active December 15, 2015 03:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save VolMi/5191787 to your computer and use it in GitHub Desktop.
Save VolMi/5191787 to your computer and use it in GitHub Desktop.
cache the files *you* consider important in RAM
#!/bin/bash
#
# cachefill -- warm up the file cache and buffer of the Linux kernel
#
# *****
# ONLY IF YOU HAVE A LOT OF MEMORY!
# I think, something like at least 8 GB for a regular Desktop
# *****
#
#
# A simple but powerful attempt to letting the kernel cache the binaries (or any files)
# I consider most important for having a great (speed / occupiedRAM)-ratio.
# This should be run once at login time or so.
#
# If you use it, skim over the code a bit and change it to your needs.
# There's a large table of folders to put in cache. Insert yours there,
# delete (or uncomment) mine, and also change the max size of files
# which you allow to read in the cache.
#
#
# A mechanical HDD will be tortured witch plenty of file seeks,
# which is actually the motivation to do that once *here*, and not have to
# wait for the damn PC when we interact with it.
#
# The technique is known as "the poor man's way to cache data in RAM" or so. :-)
#
# It simply does this:
#
# $ cat /path/to/file/we/want/to/cache &> /dev/null
#
# The real caching is done by the Linux kernel, of course.
# By reading a file we tell the kernel, that the file is of importance
# and it is therefore cached in memory.
#
# For building a list of the files to cache, I ended up using find, due to its
# many mighty options (recurse depth, min/max file size, delimiter, ...)
#
#
# To cache all file's inodes in RAM (the kernel's "buffers"), we do this:
# ls -lAR /!(proc|lost*) &> /dev/null
#
#
# The script pauses if the PC runs on battery.
#
#
# === Related ===
#
# * Put these in your /etc/sysctl.conf:
# vm.swappiness=10 # only swap in urgent circumstances
# vm.vfs_cache_pressure=50 # prefer to keep caches in RAM longer (default: 100)
#
#
# Michael Völker, 2013
# mi.voelker __at__ gmail {dot] kom, you know...
# ======================================================================
# Set options here.
#
# Leave at least that many MiB RAM free, so there is enough room
# for the kernel to make use of the memory for whatever it needs it.
#
minFreeMB=512 # recommendation: 512 or so
# We create a (really long) list of files-to-read-into-cache and save it in /tmp
# to be able to reuse it.
# Files come and go, so we should renew this list from time to time.
# This is the age in hours which we allow for that list:
#
Nhours=12 # recommendation: something like 1...48
# Here we define RegEx-patterns for files to ignore completely.
# If you use more patterns than the fixed number specified here,
# you have to change the code, below!
# An empty ignore pattern would match *all* strings, so insert some
# rubbish to match *no* string.
#
ignorePattern001='/[Tt][Rr][Aa][Ss][Hh]/' # files in a folder like /Trash/ or /trash/
ignorePattern002='/[Cc][Aa][Cc][Hh][Ee]/' # files in a folder like /Cache/
ignorePattern003='\.backup'
ignorePattern004='_____nothing______'
ignorePattern005='_____nothing______'
ignorePattern006='_____nothing______'
ignorePattern007='_____nothing______'
ignorePattern008='_____nothing______'
ignorePattern009='_____nothing______'
ignorePattern010='_____nothing______'
# Max size(s) of files to cache. help:
# We use an array to specify different sizes (in 2^n kiB). 2^ 0 kiB = 1 kiB
# It is usually all the damn small files for which caching makes the 2^10 kiB = 1 MiB
# most sense, because HDD-reads are extraordinary slow for them, 2^20 kiB = 1 GiB
# but they occupy only litle RAM, of course.
for i in {0..20}
do
maxFileSizekB[$i]="-size -"$((2**$i))"k" # query the entries using ${maxFileSizekB[$i]}
done
#
# ======================================================================
# root shouldn't do this. It's for interactive responsiveness
if [ "$(whoami)" = "root" ]
then
echo 'Do not run as root!' >&2
exit 1
fi
renice -n 19 -p $$ &> /dev/null # minimal CPU priority
ionice -c 3 -p $$ &> /dev/null # minimal I/O priority
read ScriptName < /proc/$$/comm # Yeah, that's me!
# Make sure all child processes are nuked if we hit Ctrl+C
# or use kill manually.
trap 'pkill -TERM -P $$; echo " Your God hates you, bastard."; exit 2' SIGINT SIGTERM
tmpDir="/tmp/${ScriptName}"
listOfFiles="${tmpDir}/fileList.txt"
createNewList="y" # make new list of files-to-cache except for special conditions
mkdir -p "${tmpDir}"
# /tmp may be in a precious RAM disk and the file list is easily compressible by >90%.
# So compress it fast with an available compressor:
if which xz > /dev/null # xz -1 is remarkably fast while
then # yielding impressive compression
compressor="xz -1"
uncompressor="xz -cd"
listOfFiles="${listOfFiles}.xz"
elif which lzma > /dev/null # quite identical to xz
then
compressor="lzma -1"
uncompressor="lzma -cd"
listOfFiles="${listOfFiles}.lzma"
elif which gzip > /dev/null # good old reliable gzip...
then
compressor="gzip -1"
uncompressor="gzip -cd"
listOfFiles="${listOfFiles}.gz"
elif which lzop > /dev/null # blazingly fast,
then # but "only" >80% compression
compressor="lzop -1"
uncompressor="lzop -cd"
listOfFiles="${listOfFiles}.lzo"
elif which bzip2 > /dev/null # slower than xz
then # and worse compression
compressor="bzip2 -1"
uncompressor="bzip2 -cd"
listOfFiles="${listOfFiles}.bz2"
else # no compression
compressor="cat"
uncompressor="cat"
fi
#
# Two helper functions, so we don't suck on battery needlessly
#
function isOnBattery () {
[ -d /proc/acpi/battery ] && grep -Fq 'off-line' /proc/acpi/ac_adapter/*/state
return $?
}
function delayIfOnBattery () {
BeenHere=""
while isOnBattery
do
[ "$BeenHere" ] || echo 'On Battery. Waiting for AC power...'
sleep 5
BeenHere=yes
done
[ "$BeenHere" ] && echo 'AC plugged in now. Continue...'
}
# Decide if we reuse an existing list-of-files-to-crawl
#
if [ -s "${listOfFiles}" ] # if file exists and has a size greater than zero
then
# modification time of the file list (in seconds since 1970-01-01 00:00:00 UTC):
modifyTime=$(ls -og --time-style=+%s "${listOfFiles}" | awk '{print $4}')
now="$(date +%s)"
if [ "$(( ($now - $modifyTime)/3600 ))" -lt "$Nhours" ]
then
createNewList="" # no new list required
fi
fi
# ============================================================================================================================================
# Specify the files we want to cache, here.
#
# I use this pretty much hard-coded table style, because all the directories
# often require special thinking about how large the files are allowed to be, or
# what a reasonable recursion depth might be (use the RAM economically!),
# so this is very hardly loopable.
#
# Put in those files, your frequently used (> 1/week) programs need to work.
# Typical examples: Browser, mail client, IDE, photo editor...
# To find out which files a running program needs (and their disk size), you can do
#
# $ lsof | grep -i ^MyProgram | awk '/.* REG .*\/.*$/ {print $NF}' | sort -u | xargs du -h "" 2>/dev/null | less
#
#
# For actual file sizes (in Bytes):
#
# $ lsof | grep -i ^MyProgram | awk 'BEGIN {ORS="\0"}; /.* REG .*\/.*$/ {print $NF}' | sort -uz | xargs -0 stat -c '%s %n' | column -t | less
#
# Non-existent files or folders do not matter. Erros are piped to /dev/null
# and *reading* non-existing things can never (?) be dangerous.
#
# The -P option tells find, not to follow symlinks
# (for fun: look at /usr/bin/X11/X11/X11/X11/X11/X11/X11/X11/X11/X11/X11)
#
# Appending "/" to a dir name assures we enter the dir, even if the dir itself
# is a symlink. _____________________
# | |
if [ "$createNewList" ] # | only files smaller |
then # | than |
delayIfOnBattery # | 2^n kiB |
commonOpt="-type f -print0" # \_____________________/
echo -n "Building a file list... " # ||
cat < <( # \/
find -P /bin/ -maxdepth 5 ${maxFileSizekB[12]} $commonOpt 2> /dev/null # Essential command binaries
find -P /etc/ -maxdepth 5 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # system-wide config files
find -P /lib/ -maxdepth 1 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # essential libraries
# find -P /lib/i386* -maxdepth 5 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # 32 Bit libraries
find -P /lib/x86_64* -maxdepth 7 ${maxFileSizekB[13]} $commonOpt 2> /dev/null # 64 Bit libraries
find -P /lib64/ -maxdepth 1 ${maxFileSizekB[13]} $commonOpt 2> /dev/null # 64 Bit libraries
find -P /opt/ -name '*.so' -maxdepth 5 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # libraries of optional application software
find -P /usr/bin/ -maxdepth 2 ${maxFileSizekB[13]} $commonOpt 2> /dev/null # non-essential command binaries
find -P /usr/lib/ -maxdepth 1 ${maxFileSizekB[13]} $commonOpt 2> /dev/null # libs for binaries in /usr/(s)bin/
find -P /usr/lib/apt/ -maxdepth 4 ${maxFileSizekB[12]} $commonOpt 2> /dev/null # apt package manager libs (Debian)
find -P /usr/lib/at-spi* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # [A]ssistive [T]echnology [S]ervice [P]rovider [I]nterface
find -P /usr/lib/atlas-base/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # [A]utomatically [T]uned [L]inear [A]lgebra [S]oftware (BLAS/LAPACK)
find -P /usr/lib/cinnamon* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # Cinnamon desktop
find -P /usr/lib/codecs -maxdepth 2 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # codecs
find -P /usr/lib/coreutil* -maxdepth 4 ${maxFileSizekB[11]} $commonOpt 2> /dev/null # coreutils
find -P /usr/lib/darktable/ -maxdepth 4 ${maxFileSizekB[11]} $commonOpt 2> /dev/null # darktable raw photo developer
find -P /usr/lib/eclipse/ -maxdepth 3 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # Eclipse IDE
find -P /usr/lib/enchant/ -maxdepth 3 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # generic spell checking library
find -P /usr/lib/evince/ -maxdepth 3 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # evince document viewer for Gnome
find -P /usr/lib/evolution* -maxdepth 4 ${maxFileSizekB[12]} $commonOpt 2> /dev/null # evolution mail&more (Gnome)
find -P /usr/lib/file* -maxdepth 4 ${maxFileSizekB[11]} $commonOpt 2> /dev/null # file-roller GUI (de-)compressor
find -P /usr/lib/firef* -maxdepth 4 ${maxFileSizekB[13]} $commonOpt 2> /dev/null # firefox browser
find -P /usr/lib/geany* -maxdepth 4 ${maxFileSizekB[12]} $commonOpt 2> /dev/null # geany, lightweight IDE
find -P /usr/lib/gedit* -maxdepth 4 ${maxFileSizekB[12]} $commonOpt 2> /dev/null # gedit, text editor
find -P /usr/lib/gimp* -maxdepth 4 ${maxFileSizekB[12]} $commonOpt 2> /dev/null # gimp, photo god
find -P /usr/lib/girepository* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # GObject Introspection
find -P /usr/lib/gjs* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # Mozilla-based javascript bindings for the GNOME platform
find -P /usr/lib/gnome* -maxdepth 3 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # GNOME desktop stuff
find -P /usr/lib/gthumb/ -maxdepth 3 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # gthumb, photo viewer for gnome
find -P /usr/lib/gvfs/ -maxdepth 3 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # gnome virtual file system
# find -P /usr/lib/i386* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # 32 Bit libs
find -P /usr/lib/iceweas* -maxdepth 4 ${maxFileSizekB[13]} $commonOpt 2> /dev/null # iceweasel (Firefox in Debian)
find -P /usr/lib/jvm/ -maxdepth 8 ${maxFileSizekB[12]} $commonOpt 2> /dev/null # Java
find -P /usr/lib/kde* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # KDE desktop
find -P /usr/lib/linuxmint/ -maxdepth 4 ${maxFileSizekB[12]} $commonOpt 2> /dev/null # Linux Mint
find -P /usr/lib/locale/ -maxdepth 7 ${maxFileSizekB[12]} $commonOpt 2> /dev/null # language stuff
find -P /usr/lib/meld/ -maxdepth 4 ${maxFileSizekB[12]} $commonOpt 2> /dev/null # meld, diff viewer
find -P /usr/lib/mozilla* -maxdepth 4 ${maxFileSizekB[12]} $commonOpt 2> /dev/null # Mozilla
find -P /usr/lib/muffin/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # window manager in Cinnamon, fork of Mutter (which is based on Metacity)
find -P /usr/lib/nemo* -maxdepth 4 ${maxFileSizekB[11]} $commonOpt 2> /dev/null # Nemo file manager (Nautilus fork)
find -P /usr/lib/pidgin/ -maxdepth 4 ${maxFileSizekB[11]} $commonOpt 2> /dev/null # Pidgin IM
find -P /usr/lib/policykit* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # Policykit provides an organized way for non-privileged processes to communicate with privileged ones.
find -P /usr/lib/purple* -maxdepth 4 ${maxFileSizekB[11]} $commonOpt 2> /dev/null # multi-protocol instant messaging library
find -P /usr/lib/pyshared/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # Python shared libraries
find -P /usr/lib/python* -maxdepth 4 ${maxFileSizekB[11]} $commonOpt 2> /dev/null # Python
find -P /usr/lib/ssh/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # SSH
find -P /usr/lib/ure/ -maxdepth 3 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # Uno Runtime Environment (for libreoffice)
find -P /usr/lib/virtualb* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # VirtualBox
find -P /usr/lib/vlc/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # VLC
# find -P /usr/lib/wuala/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # Wuala Client
find -P /usr/lib/x86_64* -maxdepth 7 ${maxFileSizekB[13]} $commonOpt 2> /dev/null # 64 Bit libs
find -P /usr/lib/xul* -maxdepth 4 ${maxFileSizekB[13]} $commonOpt 2> /dev/null # xulrunner, for iceweasel/firefox
find -P /usr/share/app* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # app-install/application-registry/applications/applnk/apport/apps
find -P /usr/share/calendar/${LANG//.*/} -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # localized calendar files from bsdmainutils
find -P /usr/share/cinnamon* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # Cinnamon desktop
find -P /usr/share/command-not-found/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # ?
find -P /usr/share/cups/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # [C]ommon [U]nix [P]rinting [S]ystem
find -P /usr/share/darktable/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # photography workflow application and raw developer
find -P /usr/share/deb* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # Debian things
find -P /usr/share/desktop* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null #
find -P /usr/share/evolution* -maxdepth 4 ${maxFileSizekB[11]} $commonOpt 2> /dev/null # GNOME's e-mail, address book, calendar, task list and note-taking suite
find -P /usr/share/file* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # file-roller is a GTK archive manager
find -P /usr/share/firefox* -maxdepth 4 ${maxFileSizekB[12]} $commonOpt 2> /dev/null # Mozilla's Firefox Browser
find -P /usr/share/font* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # whatever is needed to show nice fonts
find -P /usr/share/GConf* -maxdepth 6 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # GNOME configuration database system
find -P /usr/share/geany* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # Geany -- fast and lightweight IDE
find -P /usr/share/gimp/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # gimp photo editor
find -P /usr/share/gir* -maxdepth 4 ${maxFileSizekB[ 9]} $commonOpt 2> /dev/null # GObject Introspection
find -P /usr/share/glib* -maxdepth 4 ${maxFileSizekB[11]} $commonOpt 2> /dev/null # GIO -- GNOME software library designed to present programmers with a modern and usable interface to a virtual file system
find -P /usr/share/gnome* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # GNOME Desktop
find -P /usr/share/gstreamer* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # GStreamer is a pipeline-based multimedia framework
find -P /usr/share/gthumb/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # gThumb is an advanced image viewer and browser (GNOME world)
find -P /usr/share/gtk* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # GTK files
find -P /usr/share/guake/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # drop-down terminal for GNOME Desktop
find -P /usr/share/gvfs/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # [G]NOME [V]irtual [F]ile [S]ystem
find -P /usr/share/hyphen/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # hyphenation
find -P /usr/share/i18n/charmaps/ -maxdepth 4 ${maxFileSizekB[ 9]} $commonOpt 2> /dev/null # gucharmap, the GNOME Character Map
find -P /usr/share/iceweasel* -maxdepth 4 ${maxFileSizekB[11]} $commonOpt 2> /dev/null # Iceweasel, Firefox on Debian
find -P /usr/share/icons/DMZ* -maxdepth 4 ${maxFileSizekB[ 8]} $commonOpt 2> /dev/null
find -P /usr/share/icons/Elementary* -maxdepth 4 ${maxFileSizekB[ 8]} $commonOpt 2> /dev/null
find -P /usr/share/icons/gnome* -maxdepth 4 ${maxFileSizekB[ 8]} $commonOpt 2> /dev/null
find -P /usr/share/icons/hicol* -maxdepth 4 ${maxFileSizekB[ 8]} $commonOpt 2> /dev/null
find -P /usr/share/icons/lo* -maxdepth 4 ${maxFileSizekB[ 8]} $commonOpt 2> /dev/null
find -P /usr/share/icons/Mint* -maxdepth 4 ${maxFileSizekB[ 8]} $commonOpt 2> /dev/null
find -P /usr/share/jabref/ -maxdepth 4 ${maxFileSizekB[ 8]} $commonOpt 2> /dev/null # JabRef -- manage BibTeX databases (needs Java)
find -P /usr/share/java/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # Java
find -P /usr/share/linuxmint/adjustments -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # Linux Mint Distribution files
find -P /usr/share/locale/${LANG//_*/}* -maxdepth 4 ${maxFileSizekB[11]} $commonOpt 2> /dev/null # this system's localization files
find -P /usr/share/man/${LANG//_*/}* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # localized man-pages
# find -P /usr/share/mate* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # MATE Desktop Environment
find -P /usr/share/meld/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # meld -- graphical diff-and-merge tool
find -P /usr/share/menu/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null #
find -P /usr/share/mime/ -maxdepth 4 ${maxFileSizekB[11]} $commonOpt 2> /dev/null #
find -P /usr/share/mozilla* -maxdepth 4 ${maxFileSizekB[11]} $commonOpt 2> /dev/null #
find -P /usr/share/nemo* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # Nemo file manager (Nautilus fork)
# find -P /usr/share/nixnote/ -maxdepth 5 ${maxFileSizekB[ 9]} $commonOpt 2> /dev/null # Evernote clone (needs Java)
find -P /usr/share/pixmaps/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null #
find -P /usr/share/pyshared -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # Python
find -P /usr/share/python* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # Python
find -P /usr/share/software-properties/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null
# find -P /usr/share/stellarium/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # photo-realistic sky generator
find -P /usr/share/synaptic/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # Graphical package manager in Debian's GNOME world
find -P /usr/share/system-* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null #
find -P /usr/share/tex4ht -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # TeX4ht -- converts TeX documents to HTML/XML
find -P /usr/share/texlive -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # TeX Live (La-)TeX distribution
# find -P /usr/share/wuala/ -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # Wuala shared files
find -P /var/cache/font* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # fontconfig and fonts, used by plenty of programs
find -P /var/lib/apt/ -maxdepth 4 ${maxFileSizekB[12]} $commonOpt 2> /dev/null # apt - Advanced Package Tool (Debian World)
find -P /var/lib/apt-* -maxdepth 4 ${maxFileSizekB[12]} $commonOpt 2> /dev/null # apt - Advanced Package Tool (Debian World)
find -P /var/lib/dpkg/* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # Debian package management system
find -P /var/tmp/kdecache* -maxdepth 4 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # KDE tmp files (if this is already a tmpfs, it changes nothing)
find -P ${HOME}/.mozilla/firefox/ -maxdepth 8 ${maxFileSizekB[15]} $commonOpt 2> /dev/null # Firefox/Iceweasel user profile
find -P ${HOME}/.local/share/ -maxdepth 5 ${maxFileSizekB[10]} $commonOpt 2> /dev/null #
find -P ${HOME}/.fontconfig/ -maxdepth 5 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # fonts
find -P ${HOME}/.cinnamon/ -maxdepth 8 ${maxFileSizekB[12]} $commonOpt 2> /dev/null # Cinnamon desktop config
find -P ${HOME}/.config/ -maxdepth 7 ${maxFileSizekB[ 7]} $commonOpt 2> /dev/null # user configuration
find -P ${HOME}/.gconf/ -maxdepth 7 ${maxFileSizekB[ 7]} $commonOpt 2> /dev/null #
find -P ${HOME}/.gnome* -maxdepth 7 ${maxFileSizekB[10]} $commonOpt 2> /dev/null #
find -P ${HOME}/.icedtea* -maxdepth 7 ${maxFileSizekB[ 9]} $commonOpt 2> /dev/null # web browser plugin to execute Java applets
# find -P ${HOME}/.nevernote/ -maxdepth 7 ${maxFileSizekB[10]} $commonOpt 2> /dev/null # nevernote/nixnote (Evernote Client)
find -P ${HOME}/.pulse* -maxdepth 7 ${maxFileSizekB[ 7]} $commonOpt 2> /dev/null # PulseAudio sound server
# find -P ${HOME}/.thumbnails -maxdepth 7 ${maxFileSizekB[ 7]} $commonOpt 2> /dev/null # thumbnail images
find -P ${HOME}/.VirtualBox/ -maxdepth 7 ${maxFileSizekB[11]} $commonOpt 2> /dev/null # VirtualBox user files
# find -P ${HOME}/.wuala/ -maxdepth 7 ${maxFileSizekB[11]} $commonOpt 2> /dev/null # Wuala user files
# ######################################################################################
# Special/sophisticated find expressions
# ######################################################################################
# MATLAB libraries and jar files
# $(readlink -f $(which matlab) | sed 's|/bin/matlab||') is the installation path, which is hardly predictable.
find -P $(readlink -f "$(which matlab)" | sed 's|/bin/matlab||') \( -regex '.*\.so[\.0-9]*' -or -name '*.jar' \) ${maxFileSizekB[11]} $commonOpt 2> /dev/null
# Reaching the end of this process substitution magic, we will print the output to STDOUT
# with the above cat and directly pipe the data to the following stream of commands.
#
# This is a pretty long pipeline...
# But it is very flexible,
# while being fast as (w|h)ell.
#
# |
# |
# V
#
) |
xargs -0 stat -c '%s %n' 2> /dev/null | # determine each file's actual size in Bytes (not the disk usage!)
sort -bhr | # sort them in descending file size
sed "s|.*${ignorePattern001}.*||g" | # =====================================================================
sed "s|.*${ignorePattern002}.*||g" | # /.
sed "s|.*${ignorePattern003}.*||g" | # | These are our flexible, user-definable patterns to ignore
sed "s|.*${ignorePattern004}.*||g" | # | certain files or paths.
sed "s|.*${ignorePattern005}.*||g" | # | It is usually considered bad practice to call sed N times, instead
sed "s|.*${ignorePattern006}.*||g" | # | of one sed with N patterns after "-e" flags. However, this is very
sed "s|.*${ignorePattern007}.*||g" | # | readable and it is easy to recognize where to insert additional
sed "s|.*${ignorePattern008}.*||g" | # | filter rules if desired.
sed "s|.*${ignorePattern009}.*||g" | # \.
sed "s|.*${ignorePattern010}.*||g" | # =====================================================================
tee >(awk '{ sum+=$1} END {print "/" int(sum/1024^2)}') | # sum file sizes in MiB and print them with leading "/" (little hack, due to next line)
sed -e 's|^[^/]*||' | # remove strings *not* starting with "/" (the first columns, with the file sizes)
grep -v '^$' | # ignore empty lines
sed -e "s/\(.*\)/'\1'/g" | # enclose each line in apostrophes: '/a/path/to/a/file'
$compressor > "${listOfFiles}" # save compressed list (>90% size reduction)
echo "done."
fi
#
#
# ============================================================================================================================================
fileList="$($uncompressor "${listOfFiles}")"
sizeTotMB="$(tail -n1 <<< "$fileList" | sed 's|[^0-9]||g')" # Total file size was saved in the very last line as "/sizeInIntegerMB".
Nlines="$(($(wc -l <<< "$fileList") - 1))" # Last line contains only the total size, so subtract 1.
sufficientRAM="yes"
# pv should be installed... is it?
which pv &> /dev/null && have_pv="y" # [p]ipe [v]iewer
# Check Battery state, again
delayIfOnBattery
freeMB="$(free -m | awk '/Mem/ {print $4}')"
if [ "$freeMB" -lt "$minFreeMB" ]
then
sufficientRAM=""
echo "Free memory already low. stop."
else
echo "Unused RAM before: $freeMB MiB"
# Here, the files are finally read:
#
if [ "$have_pv" ]
then
echo "Trying to cache ${Nlines} files, sorted from large to small (total size: ${sizeTotMB} MiB)"
echo " ____ _____ ________ ________ __________________________________" 1>&2 # use STDERR, like pv
echo "/read\ / t \ / current\ / average\ / progress \ " 1>&2 # use STDERR, like pv
echo "${fileList}" | xargs cat 2> /dev/null | pv -perbtas "${sizeTotMB}m" -w90 >/dev/null & # That's all the work, done in background, with progress output
else
echo '*** No command "pv" found. You should really install it! ***' 1>&2
echo -n "Trying to cache ${Nlines} files from large to small ones (total size: ${sizeTotMB} MiB) ... "
echo "${fileList}" | xargs cat &> /dev/null & # That's all the work, done quietly in background
fi
# ID of the last process we sent to background
# We'll kill it if we don't like it, harr harr harr
PID=$!
# Here we control the process
while [ -d /proc/$PID ] # check if process still exists
do
freeMB="$(free -m | awk '/Mem/ {print $4}')"
[ "$freeMB" -lt "$minFreeMB" ] && pkill -SIGTERM -P $$ && sufficientRAM="" && break
while isOnBattery
do
[ ! "$sentStop" ] && pkill -SIGSTOP -P $$ && sentStop="y" && echo -e "\n--- battery pause ---" # pause the disk crawlers
sleep 5
done
[ "$sentStop" ] && pkill -SIGCONT -P $$ && sentStop="" && echo -n "continue... "
sleep 1
done
[ "$have_pv" ] && echo || echo "done."
# Check Battery state, again
delayIfOnBattery
echo -n "Caching inodes ($(free -m | awk '/Mem/ {print $6}') MiB currently used for buffers)... "
ls -lAR /bin /etc "${HOME}" /lib* /opt /srv /sys /usr /var &> /dev/null
echo "done."
echo "$(free -m | awk '/Mem/ {print $6}') MiB in the buffer now"
echo
echo "Unused RAM now: $(free -m | awk '/Mem/ {print $4}') MiB"
fi
# KTHXBAI!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment