Назад | Перейти на главную страницу

Как перевести сервер Ubuntu в спящий режим, если сеть не используется в течение трех часов?

Я действительно использую сервер только несколько часов в день несколько дней в неделю.

Это резервный сервер, он запрашивает данные резервного копирования у клиентов.

Об этой части позаботятся, она просыпается через запланированный волшебный пакет и делает свое дело. Все хорошо. Я могу разбудить его, чтобы использовать не по расписанию, это тоже нормально.

Как мне просто узнать, что сеть не использовалась какое-то время, и чтобы он заснул? Сетевой трафик, который я хотел бы записывать, - это SSH, SFTP, rsync и обновления от Canonical. Весь остальной трафик - это просто болтовня, которая меня не волнует.

Я хотел бы, может быть, добавить следующий псевдокод в качестве cron-скрипта ... который проверяет каждые 15 минут или около того. Я не беспокоюсь о добавлении функционала cron, чувствую себя в этом уверенно.

if [ lastSignificantNetworkActivity > 3h ] { hibernate }

У меня может быть проблема X-> Y. Я просто хочу перевести свой сервер в режим пониженного энергопотребления в режиме диска на обычные 18 часов, иначе он бы ничего не делал. Я думаю, сетевая активность была хорошим показателем для проверки. Я открыт для более развитых и надежных решений или присущих свойств сервера, чтобы проверить их наличие.

(Я не уверен, что ежедневное включение и выключение питания будет хуже, чем постоянный износ от ZFS, выполняющей проверки целостности данных в течение всего дня ... просто не уверен.)

Возможная реализация для обнаружения признаков сетевого трафика, генерируемого сеансами SSH, - через правила брандмауэра:

  • Первоначально правила, соответствующие трафику, приходящему на порт 22 / tcp и исходящему из него, загружаются во время загрузки;
  • Затем сценарий периодически извлекает статистическую информацию из межсетевого экрана и сохраняет счетчики попаданий этих правил во временный файл;
  • Скрипт сможет обнаруживать сетевой трафик, обнаруживая изменения в любом количестве попаданий.

Этот подход также будет обнаруживать трафик, генерируемый SFTP и RSYNC, поскольку оба приложения работают по протоколу SSH.

Обнаружение обновлений через брандмауэр будет сложно выполнить, поскольку при загрузке пакетов используются протоколы FTP, HTTP и HTTPS, а правила брандмауэра необходимо настроить, чтобы отличать обновления программного обеспечения от записанного HTTP-трафика. По этой причине я предлагаю обнаруживать обновления программного обеспечения, проверяя время модификации /var/lib/apt/lists, /var/cache/apt/archives и /var/lib/dpkg/lock.

Мое предложение по реализации выглядит следующим образом:


Эти командные строки настроили iptables и ip6tables правила.

# apt-get install iptables-persistent

# iptables -w -N fwstats
# iptables -w -A fwstats
# iptables -w -A INPUT -p tcp --dport 22 -m state --state ESTABLISHED -j fwstats
# iptables -w -A OUTPUT -p tcp --dport 22 -m state --state ESTABLISHED -j fwstats
# iptables-save > /etc/iptables/rules.v4

# ip6tables -w -N fwstats
# ip6tables -w -A fwstats
# ip6tables -w -A INPUT -p tcp --dport 22 -m state --state ESTABLISHED -j fwstats
# ip6tables -w -A OUTPUT -p tcp --dport 22 -m state --state ESTABLISHED -j fwstats
# ip6tables-save > /etc/iptables/rules.v6

Это эквивалентная установка для nftables:

# apt-get install nftables
# nft add chain inet filter fwstats
# nft add rule inet filter fwstats counter
# nft add rule inet filter input tcp dport ssh ct state established jump fwstats
# nft add rule inet filter output tcp dport ssh ct state established jump fwstats
# echo -e \#\!`which nft` -f\\nflush ruleset > /etc/nftables.conf
# nft list ruleset >> /etc/nftables.conf

А это шаблон скрипта мониторинга. В getStats функция должна быть настроена в соответствии с используемым межсетевым экраном.

#!/bin/bash

getStats () {
    if using_nftables; then
        nft list chain inet filter fwstats | grep counter
    elif using_xtables; then
        for xtable in iptables ip6tables; do
            "${xtable}" -w -xnvL fwstats | egrep '^([[:space:]]+[0-9]+){2,2}'
        done
    fi
}

stateFile="/run/hibernation_state"

currentStats="`getStats`"
if [ "x${currentStats}" != "x" ]; then
    previousStats="`cat \"${stateFile}\"`"
    if [ "x${currentStats}" == "x${previousStats}" ]; then
        # No network traffic has been detected. Check files related do DPKG and APT
        clearToHibernate='true'
        now="`date '+%s'`"
        for path in "${stateFile}" \
            '/var/lib/apt/lists' \
            '/var/cache/apt/archives' \
            '/var/lib/dpkg/lock' ; do
            pathModTime="`stat -c '%Y' "${path}"`"
            # 10800 seconds = 3 hours
            if [ "$((now-10800))" -lt "${pathModTime}" ]; then
                clearToHibernate='false'
            fi
        done
        if "${clearToHibernate}"; then
            # OK to hibernate.
            systemctl hibernate
        fi
    else
        # Network traffic has been detected. Refresh stats.
        echo "${currentStats}" > "${stateFile}"
    fi
fi

Ужасное время идеи! Давайте кататься сами!

Истекать запущенные сеансы SSH

cat > /etc/ssh/sshd_config <<__CONFIG__
AcceptEnv LANG LC_*
Banner none
ChallengeResponseAuthentication no
ClientAliveCountMax 0
ClientAliveInterval 1800
PasswordAuthentication yes
PrintMotd no
Subsystem sftp /usr/lib/openssh/sftp-server
UsePAM yes
X11Forwarding yes
__CONFIG__

Установить спящий режим

apt install hibernate

Установите общесистемный формат журнала, для развлечения

echo "HISTTIMEFORMAT=\"%Y-%m-%d %T \"" > /etc/environment

Начни работу cron!

echo "0,12,24,36,48  *    * * *   root    bash /usr/local/sbin/hibernation" >> /etc/crontab

А теперь скроенные ужасные:

cat <<-EOF > /usr/local/sbin/hibernation

#!/bin/bash -i

# The hibernation delay script

echo "----------------------" >> /tmp/justchecking.txt

EXTEND=0
SCRIPTTIME=$(date +%s)

echo $(date) >> /tmp/justchecking.txt

echo "script timetamp" $SCRIPTTIME >> /tmp/justchecking.txt

# Make sure there is a hibernation time file

if [ ! -f /var/run/hibernation.time.txt ]
    then
        echo $SCRIPTTIME > /var/run/hibernation.time.txt
        echo "created hibernation.time.txt sbin script" >> /tmp/justchecking.txt
fi

SLEEPTIME=$(</var/run/hibernation.time.txt)

if [ $SLEEPTIME -eq 999999999999 ]
    then
        echo "just came out of suspend, set extend to 360" >> /tmp/justchecking.txt
        EXTEND=360
fi

# Check the logs for recent activity

HISTTIMEFORMAT="%Y-%m-%d %T "
HISTFILE=/root/.bash_history
set -o history
history 75 > /tmp/recenthistory.txt
set +o history
unset HISTFILE
ece
echo $(tail -n5 /var/log/apt/history.log | head -n1) "apt" >> /tmp/recenthistory.txt
LASTACTIVITY=$(grep -e apt -e dpkg -e chebackup /tmp/recenthistory.txt | tail -n1 | awk '{print $2" "$3}')
echo "last activity" $LASTACTIVITY >> /tmp/justchecking.txt

#LASTACTIVITYDATE="$(</tmp/recenthistory.txt)"

#echo "last activity date"$LASTACTIVITYDATE"." >> /tmp/justchecking.txt

# Store last activity date time as a timestamp

ACTIVITYTIMESTAMP=$(date -d "$LASTACTIVITY" +%s)
echo "activity time stamp" $ACTIVITYTIMESTAMP >> /tmp/justchecking.txt

# Calculate 

ACTIVITYCOOLDOWNTIME=$(( 3960 - ( $SCRIPTTIME - $ACTIVITYTIMESTAMP ) ))

echo "activity cool down time" $ACTIVITYCOOLDOWNTIME >> /tmp/justchecking.txt

(($ACTIVITYCOOLDOWNTIME > 0)) && EXTEND=$ACTIVITYCOOLDOWNTIME
echo "extend variable after activity cool down command" $EXTEND >> /tmp/justchecking.txt

#if [ $ACTIVITYCOOLDOWNTIME > 0 ]
#    then
#        echo "activity was recent, adding cooldowntime to extend" >> /tmp/justchecking.txt
#        EXTEND = $ACTIVITYCOOLDOWNTIME
#fi

# Check for updates or backup currently running

if [ $(ps -aux | grep -e apt -e dpkg -e chebackup | wc -l) -gt 1 ]
    then
        EXTEND=3960
        SLEEPTIME=$(($SCRIPTTIME + $EXTEND))
        echo $(ps -aux | grep -e apt -e dpkg -e chebackup | wc -l) > /tmp/justchecking.txt
        echo "activity actively running, extended 3960" >> /tmp/justchecking.txt
fi

# Check for any users logged in

if [ $(who -u | wc -l) -gt 0 ]
    then
        EXTEND=10800
        #EXTEND=180
        echo $(who -u) >> /tmp/justchecking.txt
        echo "extended 10800" >> /tmp/justchecking.txt
        #echo "extend 180" >> /tmp/justchecking.txt
fi

echo "sleeptime" $SLEEPTIME >> /tmp/justchecking.txt

if [ $EXTEND -gt 0 ]
    then
        SLEEPTIME=$(($SCRIPTTIME + $EXTEND))
fi

if [ $SLEEPTIME -lt $SCRIPTTIME ]
    then
        echo "hibernate" >> /tmp/justchecking.txt
        echo $(date +%s) >> /tmp/justchecking.txt
        echo "hibernate" >> /tmp/justchecking.txt
        echo "999999999999" > /var/run/hibernation.time.txt
        hibernate &
        disown
    else
        echo $SLEEPTIME > /var/run/hibernation.time.txt
        echo "update sleeptime" $SLEEPTIME >> /tmp/justchecking.txt
fi

tail -n100 /tmp/justchecking.txt > /tmp/justchecking.txt
wc -l /tmp/justchecking.txt >> /tmp/justchicking.txt

exit 0

EOF

Не забудьте изменить разрешения

chmod 500 /usr/local/sbin/hibernation