Linux начнет уничтожать мои процессы, не спрашивая меня, если память станет короткой?

Попробуйте что-то вроде этого:

#! /bin/bash

# Config variable(s)
ParentFolder="~/FilingCab"

# arg processing (minimalist :)
FileToMove="$1"

# use sed to extract folder number from filename.
FolderNo=$(echo "$FileToMove" | sed -r -e 's/.*zz([0-9]+)\.pdf/\1/')

# use find to search for subdirectories of parent folder that begin
# with the folder no followed by a '.'
TargetFolder=$(find "$ParentFolder" -maxdepth 1 -type -a -d -name "${FolderNo}.*")

NumFolders=$(echo "$TargetFolder" | wc -l)

if [ "$NumFolders" -eq 1 ] ; then 
 mv "$ParentFolder/$FileToMove" "$TargetFolder/" 
else
  echo "Error: $NumFolders beginning with "$FolderNo." found" >&2
  exit 1
fi

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

-maxdepth 1 в find управляйте только поисками прямых подкаталогов $ParentFolder (т.е. игнорирует subdirs subdirs). Если это не то, что Вы имели в виду, просто удалите ту часть. Это find поиски любых подкаталогов $ParentFolder, которые начинаются с $FolderNo.

Я не совсем уверен, под чем Вы подразумеваете, "если TargetFolder не равен для не освобождения", я предполагаю, что Вы имели в виду, "строковый непустой $TargetFolder". Обычно, я проверил бы, существовал ли $TargetFolder и был каталогом, но так как мы получаем имя каталога от a find -type d, это может только быть пусто или каталог. или возможно больше, если существует больше чем одно начало с "$FolderNo".

Я думаю, что лучше проверить, добираемся ли мы один и точно один результат находки. Любое другое значение является ошибкой, и мы не можем переместить файл. 0 средств никакие папки соответствия найдены. 2 или больше средства больше чем одна папка, начинающаяся с "$FolderNo". был найден.

Предупреждающее сообщение к stderr является дополнительным. так exit 1, но рекомендуемый. Это позволяет Вам называть этот сценарий из другого сценария и проверять, было ли это успешно или нет.

68
10.06.2014, 02:51
2 ответа

Может.

В Linux можно столкнуться с двумя различными условиями нехватки памяти. Которое зависит от значения sysctl vm.overcommit_memory (/proc/sys/vm/overcommit_memory)

Introduction:
. Кернел может выполнять то, что называется "перекоммутация памяти". Это происходит, когда кернел выделяет программам больше памяти, чем на самом деле присутствует в системе. Это делается в надежде, что программы на самом деле не будут использовать всю выделенную память, так как это довольно частое явление.

overcommit_memory = 2

Когда overcommit_memory установлено значение 2, кернел вообще не выполняет никакого оверкоммита. Вместо этого, когда программе выделяется память, гарантируется доступ к ней. Если системе не хватает свободной памяти, чтобы удовлетворить запрос на выделение, кернел просто вернёт ошибку на запрос. От программы зависит, насколько грациозно она справится с этой ситуацией. Если она не проверит, что выделение прошло успешно, когда оно действительно провалилось, приложение часто будет сталкиваться с проблемой сегментации.

В случае segfault, в выводе dmesg:

[1962.987529] myapp[3303]: segfault at 0 ip 00400559 sp 5bc7b1b0 error 6 in myapp[400000+1000]

The at 0 означает, что приложение пыталось получить доступ к неинициализированному указателю, который может быть результатом неудачного вызова выделения памяти (но это не единственный способ).

overcommit_memory = 0 и 1

Когда overcommit_memory установлено значение 0 или 1, overcommit включается, и программам разрешается выделять больше памяти, чем реально доступно.

Однако, когда программа хочет использовать выделенную ей память, но кернел обнаруживает, что на самом деле ему не хватает памяти, ему нужно вернуть немного памяти. Сначала оно пытается выполнить различные задачи по очистке памяти, такие, как промывка кэша, но если этого недостаточно, оно завершает процесс. Это завершение выполняется Убийцей OOM. Убийца OOM-Killer смотрит на систему, чтобы увидеть, какие программы используют какую память, как долго они выполняются, кто их выполняет, и ряд других факторов, чтобы определить, какой из них будет убит.

После того, как процесс был убит, память, которую он использовал, освобождается, и программа, которая только что вызвала состояние вне памяти, теперь имеет нужную ей память.

Однако даже в этом режиме программам все равно может быть отказано в запросе на выделение памяти. Когда overcommit_memory равен 0, кернел пытается угадать, когда ему следует начать отказывать в запросах на выделение памяти. Когда установлено значение 1, я не уверен, какое определение он использует для определения того, когда ему следует отказать в запросе, но он может отказать в очень больших запросах.

Вы можете увидеть, вовлечен ли OOM-убийца, посмотрев на вывод dmesg, и найдя такие сообщения, как:

[11686.043641] Out of memory: Kill process 2603 (flasherav) score 761 or sacrifice child
[11686.043647] Killed process 2603 (flasherav) total-vm:1498536kB, anon-rss:721784kB, file-rss:4228kB
74
27.01.2020, 19:31

Правда в том, что независимо от того, как вы на это смотрите - неважно, засорился ли ваш процесс из-за системного менеджера памяти или из-за чего-то еще - это все равно ошибка. Что случилось со всеми теми данными, которые вы только что обрабатывали в памяти? Они должны были быть сохранены.

Хотя overcommit_memory= является наиболее общим способом настройки управления Linux OOM, он также настраивается для каждого процесса, как:

echo [-+][n] >/proc/$pid/oom_adj

Использование -17 в вышеуказанном случае исключает процесс из управления вне памяти. Вероятно, в целом это не самая лучшая идея, но если вы занимаетесь поиском ошибок, то это может оказаться полезным - особенно если вы хотите знать, был ли это OOM или ваш код. Положительное увеличение числа сделает процесс более вероятным, чтобы быть убитым в событии OOM, что может позволить вам лучше укрепить устойчивость вашего кода в ситуациях с низкой памятью и гарантировать, что вы выйдете из него изящно, когда это необходимо.

Вы можете проверить текущие настройки обработчика OOM для каждого процесса, например:

cat /proc/$pid/oom_score 

Иначе вы можете пойти на самоубийство:

sysctl vm.panic_on_oom=1
sysctl kernel.panic=X

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

И если по какой-то причине вы решите, что вам нравится, сделайте его устойчивым:

echo "vm.panic_on_oom=1" >> /etc/sysctl.conf
echo "kernel.panic=X" >> /etc/sysctl.conf
16
27.01.2020, 19:31

Теги

Похожие вопросы