Почему этот бесконечный цикл не использует мои системные ресурсы?

Вы можете использовать команду inotifywait из inotify-tools в сценарии для создания жестких ссылок на созданные файлы в / tmp / some_folder . Например, жестко связать все созданные файлы из / tmp / some_folder в / tmp / some_folder_bak :

#!/bin/sh

ORIG_DIR=/tmp/some_folder
CLONE_DIR=/tmp/some_folder_bak

mkdir -p $CLONE_DIR

inotifywait -mr --format='%w%f' -e create $ORIG_DIR | while read file; do
  echo $file
  DIR=`dirname "$file"`
  mkdir -p "${CLONE_DIR}/${DIR#$ORIG_DIR/}"
  cp -rl "$file" "${CLONE_DIR}/${file#$ORIG_DIR/}"
done

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

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

Если вы хотите клонировать все изменения в / tmp , вы можете использовать более распределенную версию скрипта:

#!/bin/sh

TMP_DIR=/tmp
CLONE_DIR=/tmp/clone
mkdir -p $CLONE_DIR

wait_dir() {
  inotifywait -mr --format='%w%f' -e create "$1" 2>/dev/null | while read file; do
    echo $file
    DIR=`dirname "$file"`
    mkdir -p "${CLONE_DIR}/${DIR#$TMP_DIR/}"
    cp -rl "$file" "${CLONE_DIR}/${file#$TMP_DIR/}"
  done
}

trap "trap - TERM && kill -- -$$" INT TERM EXIT

inotifywait -m --format='%w%f' -e create "$TMP_DIR" | while read file; do
  if ! [ -d "$file" ]; then
    continue
  fi

  echo "setting up wait for $file"
  wait_dir "$file" &
done

4
12.05.2017, 19:22
2 ответа

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

Вы можете отобразить свой уровень оболочки, запустив

echo $SHLVL

Вы увидите, что это число не меняется при последовательном вводе команд exit.

6
27.01.2020, 20:47

Ваш цикл запускает один сеанс интерактивной оболочки на каждой итерации.

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

Вот почему вы не получаете огромное количество процессов bash одновременно, только два, родительский, который запускает цикл, и дочерний, который дает вам новое приглашение.


Цикл также может быть записан.

while true; do bash; done

Утилита true не принимает аргумент, она просто возвращает нулевое значение выхода, которое интерпретируется оболочкой как «истина».


Если вам нужен взрыв процессов bash (так называемая «форк-бомба»), вы можете написать

while true; do { bash & }; done

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

Возможно, вам придется перезагрузить систему, чтобы восстановиться.

Эта форк-бомба более безвредна, чем могла бы быть, поскольку она запускает только один новый процесс на каждой итерации. Другие вполне могут запускать процессы экспоненциально.

6
27.01.2020, 20:47

Теги

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