У меня есть несколько машин Ubuntu с SSD и традиционным жестким диском, где жесткий диск используется только изредка.
Из-за снижения потребления шума, тепла и мощности и продления срока службы жесткого диска я хотел бы отключить его при каждой загрузке и разбудить его только тогда, когда это необходимо.
hdparm -y (или -Y) очень хорошо работает в командной строке и делает именно то, что я хочу.
Но запись службы systemd для выполнения hdparm не работает. Точнее: он работает, и диск действительно ложится спать (как отладочные шоу), но он сразу же пробуждается (и остается бодрствующим), потому что в системе есть что-то доступное к жестким дискам (и, следовательно, пробуждение это) в самом конце процесса загрузки systemd.
Итак, как я могу поместить hdparm -y в процессе загрузки достаточно поздно, чтобы за ним не последовал какой-либо другой процесс.
Мое последнее предположение заключалось в том, чтобы изменить цель systemd по умолчанию от графического до нового (sleepydisks), который затем зависит от прежней графической цели.
Но нет ли более простого и простого способа отключить диски?
С уважением
Я использую следующий сценарий, чтобы «принудительно» простаивать диски в spindown, где по силе я имею в виду прямую инструкцию к диску, так как многие накопители WD проблематичны с помощью self-spindown. Возможно, вы можете расширить это до ваших потребностей. Сценарий хорошо прокомментирован, поэтому вы можете легко его модифицировать. Я назову его из cron каждые 20 минут, при необходимости отрегулируйте:
spindown.sh
#!/usr/bin/env bash
logger "[SPINDOWN] Checking disk activity and spinning down idles..."
# Exit during maintenance
if pgrep snapraid > /dev/null; then
logger "[SPINDOWN] Detected snapRAID maintenance. Exiting.";
exit 0
fi
# Specify any drives you want to ignore; separate multiple drives by spaces; e.g. "sda sdb"
IGNORE_DRIVES=""
PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
# Check for idle disks and spin them down unless smartd is running tests
# Create a file on the ramdisk and cycle it to test for disk activity
( if [ ! -f /dev/shm/diskstats_1 ]; then
logger "[SPINDOWN] Creating initial state file on ramdisk";
touch /dev/shm/diskstats_1;
fi ;
logger "[SPINDOWN] Updating state files on ramdisk";
mv /dev/shm/diskstats_1 /dev/shm/diskstats_2;
cat /proc/diskstats > /dev/shm/diskstats_1 ) > /dev/null 2>&1
# Find all removable USB drives, so we can ignore them later,
# see http://superuser.com/a/465953
REMOVABLE_DRIVES=""
for _device in /sys/block/*/device; do
if echo $(readlink -f "$_device")|egrep -q "usb"; then
_disk=$(echo "$_device" | cut -f4 -d/)
REMOVABLE_DRIVES="$REMOVABLE_DRIVES $_disk"
fi
done
# Append detected removable drives to manually ignored drives
IGNORE_DRIVES="$IGNORE_DRIVES $REMOVABLE_DRIVES"
# Loop through all the array disks and spin down the idle disks. Will find all drives sda > sdz AND sdaa > sdaz...
logger "[SPINDOWN] Looping through drives to detect idle state"
for disk in `find /dev/ -regex '/dev/sd[a-z]+' | cut -d/ -f3`
do
# Skip removable USB drives and those the user wants to ignore
if [[ $IGNORE_DRIVES =~ $disk ]]; then
continue
fi
# Skip SSDs
if [[ $(cat /sys/block/$disk/queue/rotational) -eq 0 ]]; then
continue
fi
# Check if drive exists
if [ -e /dev/$disk ]; then
logger "[SPINDOWN] Checking drive $disk"
# Check if drive is currently spinning
if [ "$(smartctl -i -n standby /dev/$disk | grep "ACTIVE or IDLE")" ]; then
logger "[SPINDOWN] Disk $disk is ACTIVE or IDLE. Checking for selftest"
# Check if smartctl is currently not running a self test
if [ $(smartctl -a /dev/$disk | grep -c "Self-test routine in progress") = 0 ]; then
logger "[SPINDOWN] Disk $disk is not running a self test. Checking activity."
# Check if drive has been non idle since last run
if [ "$(diff /dev/shm/diskstats_1 /dev/shm/diskstats_2 | grep $disk )" = "" ]; then
logger "[SPINDOWN] Spinning down /dev/$disk `df -h | grep /dev/$disk | rev | cut -d ' ' -f 1 | rev`"
hdparm -y /dev/$disk
fi
else
logger "[SPINDOWN] /dev/$disk is running Self-test routine. Skipping."
fi
fi
fi
done
В соответствии с конкретным вопросом, как это сделать с помощью systemd? ... создать файл таймера, который вызывает этот скрипт (Ref: https://wiki.archlinux.org/index.php/Systemd/Timers)
Используйте опцию -S hdparm.
$ hdparm --help
-S Set standby (spindown) timeout
$ hdparm -S 60 /dev/sdd
/dev/sdd:
setting standby to 60 (5 minutes)
Обратите внимание, что это верхний регистр «S».
Обратите внимание, что это верхний регистр «S».Откройте утилиту для дисков и установите диск автоматически в течение 10 минут бездействия.
Я использую следующий сценарий, чтобы «принудительно» простаивать диски в spindown, где по силе я имею в виду прямую инструкцию к диску, так как многие накопители WD проблематичны с помощью self-spindown. Возможно, вы можете расширить это до ваших потребностей. Сценарий хорошо прокомментирован, поэтому вы можете легко его модифицировать. Я назову его из cron каждые 20 минут, при необходимости отрегулируйте:
spindown.sh
#!/usr/bin/env bash
logger "[SPINDOWN] Checking disk activity and spinning down idles..."
# Exit during maintenance
if pgrep snapraid > /dev/null; then
logger "[SPINDOWN] Detected snapRAID maintenance. Exiting.";
exit 0
fi
# Specify any drives you want to ignore; separate multiple drives by spaces; e.g. "sda sdb"
IGNORE_DRIVES=""
PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
# Check for idle disks and spin them down unless smartd is running tests
# Create a file on the ramdisk and cycle it to test for disk activity
( if [ ! -f /dev/shm/diskstats_1 ]; then
logger "[SPINDOWN] Creating initial state file on ramdisk";
touch /dev/shm/diskstats_1;
fi ;
logger "[SPINDOWN] Updating state files on ramdisk";
mv /dev/shm/diskstats_1 /dev/shm/diskstats_2;
cat /proc/diskstats > /dev/shm/diskstats_1 ) > /dev/null 2>&1
# Find all removable USB drives, so we can ignore them later,
# see http://superuser.com/a/465953
REMOVABLE_DRIVES=""
for _device in /sys/block/*/device; do
if echo $(readlink -f "$_device")|egrep -q "usb"; then
_disk=$(echo "$_device" | cut -f4 -d/)
REMOVABLE_DRIVES="$REMOVABLE_DRIVES $_disk"
fi
done
# Append detected removable drives to manually ignored drives
IGNORE_DRIVES="$IGNORE_DRIVES $REMOVABLE_DRIVES"
# Loop through all the array disks and spin down the idle disks. Will find all drives sda > sdz AND sdaa > sdaz...
logger "[SPINDOWN] Looping through drives to detect idle state"
for disk in `find /dev/ -regex '/dev/sd[a-z]+' | cut -d/ -f3`
do
# Skip removable USB drives and those the user wants to ignore
if [[ $IGNORE_DRIVES =~ $disk ]]; then
continue
fi
# Skip SSDs
if [[ $(cat /sys/block/$disk/queue/rotational) -eq 0 ]]; then
continue
fi
# Check if drive exists
if [ -e /dev/$disk ]; then
logger "[SPINDOWN] Checking drive $disk"
# Check if drive is currently spinning
if [ "$(smartctl -i -n standby /dev/$disk | grep "ACTIVE or IDLE")" ]; then
logger "[SPINDOWN] Disk $disk is ACTIVE or IDLE. Checking for selftest"
# Check if smartctl is currently not running a self test
if [ $(smartctl -a /dev/$disk | grep -c "Self-test routine in progress") = 0 ]; then
logger "[SPINDOWN] Disk $disk is not running a self test. Checking activity."
# Check if drive has been non idle since last run
if [ "$(diff /dev/shm/diskstats_1 /dev/shm/diskstats_2 | grep $disk )" = "" ]; then
logger "[SPINDOWN] Spinning down /dev/$disk `df -h | grep /dev/$disk | rev | cut -d ' ' -f 1 | rev`"
hdparm -y /dev/$disk
fi
else
logger "[SPINDOWN] /dev/$disk is running Self-test routine. Skipping."
fi
fi
fi
done
В соответствии с конкретным вопросом, как это сделать с помощью systemd? ... создать файл таймера, который вызывает этот скрипт (Ref: https://wiki.archlinux.org/index.php/Systemd/Timers)
Используйте опцию -S hdparm.
$ hdparm --help
-S Set standby (spindown) timeout
$ hdparm -S 60 /dev/sdd
/dev/sdd:
setting standby to 60 (5 minutes)
Обратите внимание, что это верхний регистр «S».
Обратите внимание, что это верхний регистр «S».Откройте утилиту для дисков и установите диск автоматически в течение 10 минут бездействия.