Многопоточная обработка нескольких строк кода в сценариях bash

Часть сценария, который у меня есть, просматривает все IP-адреса в локальной сети и проверяет связанное полное доменное имя.

while [[ $ws -le $total_ip ]]; do
    ip = "${ip_range}.${ws}"
    machine=$(timeout 0.3s python3 -c "import socket; print(socket.getfqdn('$ip'))")
    if[[ "$machine" = "$myMachine" ]]; then 
        my_ip=$ip
        break
    fi
done

Это работает прямо сейчас, но занимает довольно много времени. Я добавил команду timeout перед командой python, чтобы убедиться, что она не длится более 0,3 секунды, но это все равно довольно долго.

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

machine=$(timeout 0.3s python3 -c "import socket; print(socket.getfqdn('$ip'))")
if[[ "$machine" = "$myMachine" ]]; then 
    my_ip=$ip
    break
fi

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

Не имеет прямого отношения к вопросу, но вы никогда не увеличиваете ws, так что это похоже на бесконечный цикл.

tjm3772 08.02.2023 15:33

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

tjm3772 08.02.2023 15:35

Пишите на питоне. because I wan't to run this on other computers without having to install any additional tools. Вы буквально используете Python.

KamilCuk 08.02.2023 16:37

Спасибо за ответ на мой пост. Суть этого скрипта в том, что в конечном итоге он должен стать одной строкой. Я не уверен, что смогу сделать это на питоне.

Young Fellow 08.02.2023 16:51

Что значит "все в одну строку"? python3 -c '<commands>' "$myMachine" "$ip_range".{0..255} технически это одна строка.

tjm3772 08.02.2023 17:15

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

tripleee 08.02.2023 17:48
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
6
67
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Простое решение в основном на Python. Это передает имя машины и диапазон IP-адресов для проверки, печатает IP-адрес, если он найден, и устанавливает ненулевой код выхода, если он не находит IP-адрес для данного имени машины. Общее время выполнения составляет всего несколько миллисекунд, если вашей целью является производительность.

#!/bin/bash
myMachine=$1
ip_range=$2

if my_ip=$( python3 -c '
import sys
import socket
my_machine = sys.argv[1]
for ip in sys.argv[2:]:
  if socket.getfqdn(ip) == my_machine:
    print(ip)
    sys.exit(0)
sys.exit(1)
' "$myMachine" "$ip_range".{0..255} ) ; then
  echo "$myMachine IP: $my_ip"
else
  echo "IP for $myMachine not found."
fi

Тайм-аут в вашем примере bash не сильно улучшает производительность, если вообще вообще, потому что каждый отдельный экземпляр python, вероятно, работает очень быстро. Ваши проблемы с производительностью являются результатом создания множества дочерних процессов: fork — это очень затратный системный вызов, и вы заставляете bash вызывать его повторно, вызывая новый экземпляр python3 на каждой итерации. Даже добавление «поточности» не сильно улучшит производительность, потому что (опять же) узкое место не в том, что python слишком медленный, а в том, что создание экземпляра python — медленная операция. Попытка решить проблему с помощью многопоточности приведет к очень беспорядочному и подверженному ошибкам коду с минимальным приростом производительности.

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

Спасибо, что предложили ответ на мой вопрос. Однако основная проблема заключалась в том, что для прохождения всех 254 IP-адресов требуется много времени, мой простой цикл for занимает около 1,5 минут, в то время как предложенное вами решение заняло около 5 минут.

Young Fellow 09.02.2023 06:12

Кроме того, я добавил тайм-аут, потому что, если IP-адрес не указан, команда python будет ждать около секунды, а затем завершится. Но если он жив, то для возврата полного доменного имени требуется не более 0,3 секунды.

Young Fellow 09.02.2023 06:17
Ответ принят как подходящий

Согласно документации Bash вы можете обернуть свой код в {}, чтобы сгруппировать его. Если за этой группой поставить &, она будет выполняться асинхронно. чтобы дождаться завершения всех подпроцессов, используйте wait

Пример:

{
    echo "foo"
    sleep 1
    echo "bar"
} &
echo "baz"
wait

Выведет:

baz
foo
# and after one second
bar

больше информации об управлении заданиями bash можно найти здесь.

Это верно и обеспечивает некоторую степень асинхронности, но имейте в виду, что фоновые группы запускаются в подоболочках, что ограничивает взаимодействие с ними родительской оболочки. Например, foo=bar ; { foo=baz ; } & wait ; echo "$foo" печатает bar, потому что изменения переменных в подоболочке не отражаются в родительском.

tjm3772 08.02.2023 18:26

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

tjm3772 08.02.2023 18:34
echo $ip > /tmp/mymachine
Young Fellow 09.02.2023 09:04

Другие вопросы по теме