如何使用 systemd 关闭磁盘?

如何使用 systemd 关闭磁盘?

我有几台 Ubuntu 机器,既有 SSD,也有传统硬盘,其中硬盘只是偶尔使用。

为了减少噪音、热量和功耗,并延长硬盘的使用寿命,我想在每次启动时将其关闭,并仅在需要时唤醒它。

hdparm -y(或-Y)在命令行上运行得很好,并且完全符合我的要求。

但是编写一个 systemd 服务来执行hdparm是行不通的。更准确地说:它可以工作,磁盘确实进入睡眠状态(如调试所示),但它会立即再次被唤醒(并保持唤醒状态),因为系统上有一些东西在 systemd 启动过程的最后访问了硬盘(从而唤醒了它)。

那么,我怎样才能将 ahdparm -y放入启动过程足够晚一些,以便它不再被任何其他过程所跟随。

我的最后一个猜测是将 systemd 的默认目标从图形更改为新的目标(sleepydisks),然后依赖于前一个图形目标。

但是,有没有更简单、更直接的方法来关闭磁盘呢?

问候

答案1

打开磁盘实用程序并将驱动器设置为在 10 分钟不活动后自动旋转停止。

答案2

使用 hdparm 的 -S 选项。这将设置驱动器应保持的旋转停止超时时间。

$ hdparm --help
-S   Set standby (spindown) timeout

$ hdparm -S 60 /dev/sdd
/dev/sdd:
 setting standby to 60 (5 minutes)

请注意,这是一个大写的“S”。

答案3

我使用以下脚本“强制”空闲磁盘降速,这里的强制是指直接向驱动器发出指令,因为许多 WD 驱动器在自动降速方面存在问题。也许您可以根据需要扩展它。该脚本注释得很好,因此您应该能够很容易地修改它。我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 来做到这一点?...创建一个调用此脚本的计时器文件(参考:https://wiki.archlinux.org/index.php/Systemd/Timers

相关内容