Часть сценария, который у меня есть, просматривает все 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, потому что я не хочу запускать его на других компьютерах без установки каких-либо дополнительных инструментов.
Кроме того, если вы уже используете python, вероятно, было бы намного быстрее написать логику в скрипте python, а не разветвлять пару сотен дочерних элементов.
Пишите на питоне. because I wan't to run this on other computers without having to install any additional tools.
Вы буквально используете Python.
Спасибо за ответ на мой пост. Суть этого скрипта в том, что в конечном итоге он должен стать одной строкой. Я не уверен, что смогу сделать это на питоне.
Что значит "все в одну строку"? python3 -c '<commands>' "$myMachine" "$ip_range".{0..255}
технически это одна строка.
Оболочка не поддерживает многопоточность. Вы можете запустить несколько процессов, но это технически другое; процесс может иметь один или несколько потоков.
Простое решение в основном на 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 минут.
Кроме того, я добавил тайм-аут, потому что, если IP-адрес не указан, команда python будет ждать около секунды, а затем завершится. Но если он жив, то для возврата полного доменного имени требуется не более 0,3 секунды.
Согласно документации 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
, потому что изменения переменных в подоболочке не отражаются в родительском.
Влияние для OP заключается в том, что если они заполнят my_ip
в одной из этих подоболочек, у них не будет доступа к ней позже - им придется найти другой способ сообщить родительской оболочке, какой IP они нашли, что добавляет некоторую дополнительную сложность их возможное решение.
echo $ip > /tmp/mymachine
Не имеет прямого отношения к вопросу, но вы никогда не увеличиваете
ws
, так что это похоже на бесконечный цикл.