G

SSD-Optimierung durch automatisiertes Trimmen

Begonnen von guest37, 17. Dezember 2017, 16:17:38

« vorheriges - nächstes »

0 Mitglieder und 1 Gast betrachten dieses Thema.

guest37

Automatisches Trimmen mit fstrimDaemon (Ein sehr leichter Daemon, welcher fstrim alle paar Stunden ausführt).
Eine SSD sollte regelmäßig getrimmt werden (→ TRIMMEN = Markierung ungenutzter oder ungültiger Datenblöcke zum Zweck der späteren Wiederbeschreibung). Dadurch werden Schreibzugriffe auf das Laufwerk beschleunigt und zudem SSD-Abnutzungseffekte verringert.
Normalerweise wird fstrim durch einen cron-Befehl ausgeführt, jedoch nur zu einem festgelegten Zeitpunkt und bei zwischenzeitlich ausgeschaltetem System nicht nachholbar.
Dieser Daemon löst dieses Problem, indem er fstrim in einer Schleife ausführt mit sehr niedriger Priorität, um gleichzeitiges arbeiten am PC nicht zu beeinträchtigen. Installiert und konfiguriert wird fstrimDaemon durch folgende drei Scripts, welche mit dem nano-Editor erstellt werden können:   [# = mit ROOT, $ = ohne ROOT]

1. # nano /etc/conf.d/fstrimDaemon:

# /etc/conf.d/fstrimDaemon: config file for /etc/init.d/fstrimDaemon

# Time to wait after daemon start to perform first fstrim
# e.g. "30m" - 30 minutes. See man sleep.
SLEEP_AT_START="2h"

# Time to sleep between next repetition of fstrim
# e.g. "5d" - 5 days. See man sleep.
SLEEP_BEFORE_REPEAT="3h"

# Maximum CPU Load when fstrim is allowed.
# If current CPU Load is above daemon sleeps for 5 min.
# 1.0 means all cores are busy.
MAX_CPU_LOAD="0.3"

# Divide sleep into sleep chunks (in seconds) in order to
# prevent including computer suspend time into sleep time
# and performing fstrim just after resume
SLEEP_CHUNK=3000

# integer [-20 .. 19 ] default 0
# change the priority of the server -20 (high) to 19 (low)
# see nice(1) for description
NICE="17"

# See start-stop-daemon(8) for possible settings
# Modifies the IO scheduling priority of the daemon.  Class
# can be 0 for none, 1 for real time, 2 for best effort and 3
# for idle.  Data can be from 0 to 7 inclusive.
IONICE="3"

# Here Daemon's process id will be stored
PID="/var/run/fstrimDaemon.pid"

# Here Daemon logs
LOG="/var/log/fstrimeDaemon.log"

# The main daemon script i.e. fstrim-sleep loop
DAEMON="/usr/sbin/fstrimDaemon.sh"


Speichern mit Strg+O, Return, beenden mit Strg+X und ausführbar machen: # chmod +x /etc/conf.d/fstrimDaemon

2. # nano /usr/sbin/fstrimDaemon.sh

#!/bin/bash

source /etc/conf.d/fstrimDaemon

SLEEP_CMD="sleep"
# SLEEP_CMD="echo debug: SLEEP"

# We divide sleep for smaller portions in order to protect
# against being awaken when computer resume from suspension
function vigilantSleep()
{
	local VAL=${1%?}

	if   [[ "$1" == *s ]] ; then
		local MULTIPLEXER=1
	elif [[ "$1" == *m ]] ; then
		local MULTIPLEXER=60
	elif [[ "$1" == *h ]] ; then
		local MULTIPLEXER=60*60
	elif [[ "$1" == *d ]] ; then
		local MULTIPLEXER=24*60*60
	else
		local MULTIPLEXER=1
		local VAL=${1}
	fi

	let "HOURS= ${VAL} * ${MULTIPLEXER} / ${SLEEP_CHUNK}"
	let " REST= ${VAL} * ${MULTIPLEXER} % ${SLEEP_CHUNK}"

	for i in $(seq 1 ${HOURS}) ; do
		${SLEEP_CMD} ${SLEEP_CHUNK}
	done

	${SLEEP_CMD} ${REST}
}

CORES=`grep 'model name' /proc/cpuinfo | wc -l`
U_MAX_CPU_LOAD=`echo "0${CORES} * 0${MAX_CPU_LOAD}" | bc -l`
# echo debug: U_MAX_CPU_LOAD=${U_MAX_CPU_LOAD}

function waitForLowCpuLoad()
{
	local CPU_LOAD=999999
	while true ; do
		local CPU_LOAD=`cut -f 1 -d" " /proc/loadavg`
		local TMP=`cut -f 2 -d" " /proc/loadavg`
		local DIFF=`echo "${CPU_LOAD} < ${TMP}" | bc -l`
		if [ `echo "${CPU_LOAD} < ${TMP}" | bc -l` = 1 ] ; then
			local CPU_LOAD=${TMP}
		fi
		local TMP=`cut -f 3 -d" " /proc/loadavg`
		if [ `echo "${CPU_LOAD} < ${TMP}" | bc -l` = 1  ] ; then
			local CPU_LOAD=${TMP}
		fi

		[ `echo "${CPU_LOAD} < ${U_MAX_CPU_LOAD}" | bc -l` = 1 ] \
			&& echo "debug: CPU_LOAD=${CPU_LOAD}" \
			&& break
		sleep 5m
	done
}

function doTRIM()
{
	echo `date`: RUN FSTRIM FOR ${TRIM_DIRS}
	for DIR in ${TRIM_DIRS}; do
		waitForLowCpuLoad
		time fstrim -v ${DIR}
	done
	echo ----------------------------
}

if [ "$1" != "one_shot" ]; then
	echo =============================
	echo `date`: FSTRIM DAEMON STARTED
	echo -----------------------------
	vigilantSleep ${SLEEP_AT_START}
fi

echo "Searching for trimable directories"
TRIM_DIRS=
for mount_point in `mount | grep -E "type ext|type bfs|type msdos|type fat|type vfat" | cut -d" " -f3`
do
	fstrim ${mount_point} 2> /dev/null
	if [ "$?" = "0" ] ; then
		TRIM_DIRS="${TRIM_DIRS} ${mount_point}"
	fi
done
echo Trimable directories are: ${TRIM_DIRS}

if [ "$1" == "one_shot" ]; then
	echo "One shot done"
	exit 0
fi

while true ; do
	vigilantSleep ${SLEEP_BEFORE_REPEAT}
	doTRIM
done


Speichern mit Strg+O, Return, beenden mit Strg+X und ausführbar machen: # chmod +x /usr/sbin/fstrimDaemon.sh

3. # nano /etc/init.d/fstrimDaemon

#!/sbin/openrc-run

checkconfig()
{
  if [ ! -f /etc/conf.d/fstrimDaemon ] ; then
    eerror "/etc/conf.d/fstrimDaemon does not exists."
    return 1
  fi

  if [ -z "${DAEMON}" ] \
  	|| [ -z "${PID}" ] \
  	|| [ -z "${IONICE}" ] \
  	|| [ -z "${NICE}" ] \
  	|| [ -z "${LOG}" ] \
  	|| [ -z "${SLEEP_AT_START}" ] \
  	|| [ -z "${SLEEP_BEFORE_REPEAT}" ] \
  	|| [ -z "${SLEEP_BEFORE_REPEAT}" ]
  then
    eerror "You must set config options in /etc/conf.d/fstrimDaemon first"
    return 1
  fi

  if [ ! -f ${DAEMON} ] ; then
    eerror "Script ${DAEMON} does not exists."
    return 1
  fi
}

start()
{
  ebegin "Starting fstrimeDaemon"
  checkconfig || return 1
  echo `date`: Starting...  >> ${LOG}
  start-stop-daemon --start \
    --exec ${DAEMON} \
    --pidfile ${PID} \
    --background \
    --make-pidfile \
    --ionice ${IONICE} \
    --nice ${NICE} \
    --stdout ${LOG} \
    --stderr ${LOG}
  eend $?
}

stop()
{
  ebegin "Stopping fstrimeDaemon"
  start-stop-daemon --stop \
    --exec ${DAEMON} \
    --pidfile ${PID}
  eend $retval
  echo `date`: Stopped  >> ${LOG}
}


Speichern mit Strg+O, Return, beenden mit Strg+X und ausführbar machen: # chmod +x /etc/init.d/fstrimDaemon
 
4. openrc-Dienst und -Startbefehl für fstrimDaemon:
     # rc-update add fstrimDaemon default && rc-service fstrimDaemon start

5. Kontrolle:
     $ cat /var/log/fstrimeDaemon.log