Как запустить скрипт, когда на порту открывается соединение?

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

Из руководства flock(2)по моей системе:

Advisory locks allow cooperating processes to perform consistent operations on files, but do not guarantee consistency (i.e., processes may still access files without using advisory locks possibly resulting in inconsistencies).

Рассмотрим этот скрипт:

#!/bin/sh

( flock -x 9 || exit 1
  echo '1: Locking for 5 secs'; sleep 5; echo '1: Done' ) 9>/tmp/lock &

sleep 1
echo '2: Will now attempt to get lock'

( flock -x 9 || exit 1
  echo '2: Got lock' ) 9>/tmp/lock

# Since the second flock call only performs one operation, the whole last 
# subshell may be replaced by just
#    flock -x /tmp/lock -c echo '2: Got lock'
#
#  (-x and -c are not needed, a lock is exclusive ("write lock")
#   unless -s is used to create a shared lock ("read lock"),
#   and the -c is optional)

Выход:

1: Locking for 5 secs
2: Will now attempt to get lock
1: Done
2: Got lock

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

Также обратите внимание, что здесь защищен не файл блокировки, а echoоперации в подоболочках, которые гарантированно являются монопольными. В частности, файл блокировки не защищен от несговорчивых процессов, выполняющих запись или чтение из него.

Это означает, что каждой flockсубоболочке путем блокировки /tmp/lockв этом примере гарантируется, что операции (над файлами или другими общими ресурсами данных )не будут смешиваться с конфликтующими операциями из любого другая программа, которая использует flockс /tmp/lockв качестве файла блокировки.

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

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

Также обратите внимание, что не все файловые системы могут поддерживать блокировку файлов с помощьюflock(или его эквивалента в библиотеке C,flock()). Например, сетевые файловые системы AFS и NFS могут быть проблематичными в этом отношении. См.https://en.wikipedia.org/wiki/File_locking#Problems

1
03.11.2019, 04:55
1 ответ

Я еще немного покопался и обнаружил, что у команды ssесть несколько полезных функций:

-Eдает нам поток событий, но кажется, что он полезен только с соединениями TCP. Мы можем считать установленные и закрытые соединения, но ничего не печатается с соединениями udp.

Но мы можем проверить значения Recv -Q при использованииss -una state all '( sport = :<port> )'

Если он остается равным 0 достаточно долго, мы можем отменить приоритет процесса, а если он больше нуля, мы можем установить приоритет процесса.

В итоге я написал сценарий:

#!/bin/bash

state=idle
count=0
fstate=idle
ramptime=3
pid=$1
port=$2

while true; do
        while [ $count -lt $ramptime ]; do
                sleep 1
                activity=$(ss -unHa state all '( sport = :'$port' )' | awk '{ print $2 };')
                if [ $activity -eq 0 ]; then
                        fstate=idle
                else
                        fstate=active
                fi
                if [ $fstate = $state ]; then
                        count=0
                else
                        count=$((count+1))
                fi
                #echo $activity $count $state $fstate

        done
        count=0
        state=$fstate
        case $state in
                idle)
                        ramptime=3
                        schedtool -D $pid
                        renice 20 -p $pid
                        ionice -c 3 -p $pid
                ;;
                active)
                        ramptime=30
                        schedtool -R -p 1 $pid
                        renice -10 -p $pid
                        ionice -c 2 -p $pid
        esac
done
0
27.01.2020, 23:57

Теги

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