Ускорение выполнения bash-скрипта

Посмотрите, какой процесс открыл файл с помощью lsof /var/lib/dpkg/lockили fuser /var/lib/dpkg/lock.

Скорее всего, это ежедневная служба apt -, которая обычно запускается один раз в день для запуска apt-get updateи уведомления пользователя о доступных обновлениях. Если вам это не нравится, см. Как отключить `apt -daily.service `в образе облачной виртуальной машины Ubuntu?

2
09.02.2020, 19:17
2 ответа

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

см. iptables (8)

[!] -s, --source address[/mask][,...] Source specification. Address can be either a network name, a hostname, a network IP address (with /mask), or a plain IP address. Hostnames will be resolved once only, before the rule is submitted to the kernel. Please note that specifying any name to be resolved with a remote query such as DNS is a really bad idea. The mask can be either an ipv4 network mask (for iptables) or a plain number, specifying the number of 1's at the left side of the network mask. Thus, an iptables mask of 24 is equivalent to 255.255.255.0. A "!" argument before the address specification inverts the sense of the address. The flag --src is an alias for this option. Multiple addresses can be specified, but this will expand to multiple rules (when adding with -A), or will cause multiple rules to be deleted (with -D).

Тогда вы ограничены максимальной длиной командной строки bash, которая может отличаться в зависимости от ОС. Чтобы узнать свой лимит, запустите

getconf ARG_MAX

Это избавит вас от многократного выполнения команды iptables.

Пример из вопроса будет:

iptables -A INPUT -s 216.187.112.96/27,216.187.112.128/27,216.187.112.160/31,216.187.112.163/32 -j DROP

Чтобы сделать его более читабельным, вы должны иметь возможность разбивать строки следующим образом:

iptables -A INPUT -s\
  216.187.112.96/27,\
  216.187.112.128/27,\
  216.187.112.160/31,\
  216.187.112.163/32 \
  -j DROP

Давайте посчитаем:

  • Ваш файл имеет размер 9 МБ. Строки составляют около 48 байт, что составляет примерно 9 * 1024^2 / 48 ≈ between 190000 and 200000строк (1 строка = 1 вызову iptables ).
  • В Ubuntu есть ARG _MAX 2097152. 9 * 1024^2 / 2097152 ≈ 5строк
0
28.04.2021, 23:23

iptables имеет ограничения из-за своей концепции. Когда iptables меняет правила, вот что происходит на самом деле:

  • iptables запрашивает у ядра весь набор правил
  • iptables изменяет (в пространстве пользователя )набор правил, обычно добавляя одну запись
  • iptables возвращает ядру весь набор правил

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

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

Что нельзя делать:

  • Не пытайтесь запускать несколько iptablesпараллельно, для этого не предусмотрена блокировка ядра, и в конечном итоге вы потеряете правила. Использование iptables --waitблокирует (пользовательское пространство ), но тогда оно больше не будет параллельным.

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

  • используйтеiptables-restoreдля загрузки всего набора правил за один раз.

    Либо запустите один раз ваш bash-скрипт (, подождите )и выгрузите окончательный результат с помощью iptables-save, готовый к повторному использованию с iptables-restore,или отредактируйте с помощью sed и т. д. ваш скрипт, чтобы иметь готовый файл для формата iptables-restore. Если это таблица фильтров по умолчанию, она должна иметь формат, подобный этому:

    *filter
    :INPUT ACCEPT [0:0]
    :FORWARD ACCEPT [0:0]
    :OUTPUT ACCEPT [0:0]
    -A INPUT -s 216.187.112.96/27 -j DROP
    -A INPUT -s 216.187.112.128/27 -j DROP
    -A INPUT -s 216.187.112.160/31 -j DROP
    -A INPUT -s 216.187.112.163/32 -j DROP
    [...]
    -A INPUT -s 192.0.2.0/24 -j DROP
    COMMIT
    
  • В противном случае не используйте напрямую iptables для загрузки списков адресов, используйте сопутствующийipset , который оптимизирован для этого, используя хэш-таблицы и отправляя только в ядро. запись для добавления, не спрашивая сначала ее список, как это делает iptables:

    If you want to

    • store multiple IP addresses or port numbers and match against the collection by iptables at one swoop;
    • dynamically update iptables rules against IP addresses or ports without performance penalty;
    • express complex IP address and ports based rulesets with one single iptables rule and benefit from the speed of IP sets

    then ipset may be the proper tool for you.

    Вы должны определить максимальное количество элементов (, которое по умолчанию равно "только" 65536 ). Размер хеша динамически изменяется с помощью ipset, поэтому не нужно (или рассмотрите возможность добавления hashsize 65536по крайней мере ). Для вашего простого случая (только исходные IP-сети )вы должны сделать что-то вроде этого:

    ipset create usa_ips hash:net maxelem 300000 hashsize 65536
    

    А теперь вы прокрутите свой список, используя ipset. Список может быть файлом usa_ips.txtвроде этого:

    216.187.112.96/27
    216.187.112.128/27
    216.187.112.160/31
    216.187.112.163/32
    [...]
    

    Это должно занять примерно 10 минут в таком цикле:

    while read net; do
        ipset add usa_ips $net
    done < usa_ips.txt
    

    В конце или перед концом вы можете увидеть, насколько большим стал список, например,:

    # ipset -t list usa_ips
    Name: usa_ips
    Type: hash:net
    Revision: 6
    Header: family inet hashsize 65536 maxelem 300000
    Size in memory: 3847384
    References: 0
    Number of entries: 131076
    

    И теперь вы можете удалить все, что соответствует этому списку, с помощью этого единственного правила iptables :

    iptables -A INPUT -m set --match-set usa_ips src -j DROP
    

    Это установит запись Ссылки выше на 1, так как iptables использует ее.

  • Текущий набор, сделанный выше, можно сохранить и перезагрузить с помощью ipset save usa_ips > ipset_usa_ips.txtи ipset restore usa_ips < ipset_usa_ips.txt. Когда вы увидите выходной формат, вы узнаете, что вы также можете подготовить для него один -файл снимка, как указано выше, что намного быстрее:занимает < 1 с для загрузки ~130000 записей . Формат такой:

    ОБНОВЛЕНИЕ :на самом деле вы получите сообщение об ошибке, потому что набор сейчас используется, поэтому в ipset доступна команда swap. Вы должны загрузить список в альтернативный набор и поменять его местами с предыдущим набором.

    create usa_ips_new hash:net family inet hashsize 65536 maxelem 300000
    add usa_ips_new 216.187.112.96/27
    add usa_ips_new 216.187.112.128/27
    add usa_ips_new 216.187.112.160/31
    add usa_ips_new 216.187.112.163/32
    [...]
    

    И он может заменить ранее созданный набор на:

    # ipset restore < usa_ips_new.txt
    # ipset swap usa_ips usa_ips_new
    # ipset destroy usa_ips_new
    
  • переключиться на nftables или, по крайней мере, на iptables -поверх -nftables API (, который по умолчанию используется в Debian 10 и RHEL 8/CentOS 8)

    nftables был создан для устранения многих ошибок, допущенных с iptables . При добавлении правила в ядро ​​​​передается только эта дельта :, для этого не потребуется запрашивать весь набор правил/редактировать/отправлять обратно, выполняемый iptables . Уровень совместимости iptables -поверх -nftables делает то же самое, так как он реализован с помощью nftables (и слоя совместимости в основном для специальных совпадений и целей iptables, среди них ipset , который может не подлежит переводу ).

    На этом я остановлюсь и оставлю вам упражнение. Просто знайте, что недавние nftables , используемые в последнем ядре, имеют поддержку собственных наборов , которые при использовании сflags interval(и, возможно, auto-mergeво избежание дубликатов )могут полностью заменить использование ipset для вашего случая.

4
28.04.2021, 23:23

Теги

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