Python — отличный язык сценариев. Все больше системных администраторов используют скрипты Python для автоматизации своей работы.
Поскольку в задачи системный администратор все время включает команды Linux, выполнение команд Linux из скрипта Python является отличной помощью.
В этой статье мы покажем вам пару способов, которыми вы можете запускать команды оболочки и получать их вывод в своей программе Python.
Позвольте нам создать простую программу на Python, которая выполняет команду оболочки с модулем os.
import os myCmd = 'ls -la' os.system (myCmd)
Теперь, если мы запускаем эту программу, и вот что мы видим в выводе.
python myprog.py total 40 drwxr-xr-x 3 andreyex andreyex 4096 Jan 20 13:23 . drwxr-xr-x 49 andreyex andreyex 4096 Jan 20 13:34 .. -r--r--r-- 1 andreyex andreyex 456 Dec 19 20:51 andreyex.txt -rw-r--r-- 1 andreyex andreyex 0 Jan 20 11:32 master -rw-r--r-- 1 andreyex andreyex 14 Jan 10 21:22 masterX.txt -rw-r--r-- 1 andreyex andreyex 14 Jan 10 12:17 destroyer.txt --w-r--r-- 1 andreyex andreyex 356 Jan 20 13:12 mytest.txt -rw-r--r-- 1 andreyex andreyex 356 Dec 24 15:18 login.txt -rw-r--r-- 1 andreyex andreyex 44 Jan 20 10:53 mymyprog.py -rw-r--r-- 1 andreyex andreyex 356 Dec 22 15:33 turbo.txt drwxr-xr-x 3 andreyex andreyex 4096 Jan 3 20:51 target
Это содержимое каталога, в котором хранится myprog.py.
Если вы хотите использовать вывод команды оболочки, вы можете сохранить его в файле непосредственно из команды оболочки:
import os myCmd = 'ls -la > out.txt' os.system(myCmd)
Вы также можете сохранить выходные данные команды оболочки в переменной следующим образом:
import os myCmd = os.popen('ls -la').read() print(myCmd)
Если вы запустите вышеупомянутую программу, она напечатает содержимое переменной myCmd и будет такой же, как и результат команды ls, которую мы видели ранее.
Теперь давайте посмотрим другой способ запуска команды Linux в Python.
Несколько лучший способ запуска команд оболочки в Python — использование подпроцессмодуль.
Если вы хотите запустить команду оболочки без каких-либо параметров и аргументов, вы можете вызвать подпроцесс следующим образом:
import subprocess subprocess.call("ls")
Метод call выполнит команду оболочки. Вы увидите содержимое текущего рабочего каталога при запуске программы:
python myprog.py agatha.txt count1.txt file1.txt myprog.py target count count2.txt file2.txt sherlock.txt
Если вы хотите предоставить опции и аргументы вместе с командой оболочки, вам придется предоставить их в виде списка.
import subprocess subprocess.call(["ls", "-l", "."])
Когда вы запустите программу, вы увидите содержимое текущего каталога в виде списка.
Теперь, когда вы знаете, как запустить команду оболочки с подпроцессом, возникает вопрос о сохранении вывода команды оболочки.
Для этого вам нужно будет использовать функцию Popen. Он выводит объект Popen, у которого есть метод communication(), который можно использовать для получения стандартного вывода и ошибки в виде кортежа.
import subprocess MyOut = subprocess.Popen(['ls', '-l', '.'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout,stderr = MyOut.communicate() print(stdout) print(stderr)
Когда вы запустите программу, вы увидите stdout и stderr (которых в данном случае нет).
python myprog.py total 32 -r--r--r-- 1 andreyex andreyex 456 Dec 11 21:29 agatha.txt -rw-r--r-- 1 andreyex andreyex 0 Jan 20 12:11 count -rw-r--r-- 1 andreyex andreyex 14 Jan 10 16:12 count1.txt -rw-r--r-- 1 andreyex andreyex 14 Jan 10 16:12 count2.txt --w-r--r-- 1 andreyex andreyex 356 Jan 20 12:10 file1.txt -rw-r--r-- 1 andreyex andreyex 356 Dec 17 09:59 file2.txt -rw-r--r-- 1 andreyex andreyex 212 Jan 20 16:54 myprog.py -rw-r--r-- 1 andreyex andreyex 356 Dec 11 21:35 sherlock.txt drwxr-xr-x 3 andreyex andreyex 4096 Jan 4 20:10 target None
Мы надеемся, что этот быстрый совет помог вам выполнить команду оболочки в программах Python. Если у вас есть вопросы или предложения, пожалуйста, не стесняйтесь оставить комментарий ниже.
Есть ли возможность настроить взаимодействие python скрипта c консольным приложением linux
Добрый день, а можно попросить Вас написать код, который будет запускать tcpdump контролирующий наличие трафика на UDP порту. Как трафик появился, написать в консоли 1, как трафик на порту пропал — написать 2. Мониторинг должен проводиться постоянно.
Примерно так:
import subprocess
import re
import time
def monitor_udp_traffic(port):
while True:
# Запускаем tcpdump с указанием порта
command = f»tcpdump -i any udp port {port}»
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# Ждем, пока tcpdump начнет собирать данные
time.sleep(2)
try:
while True:
# Считываем строки из вывода tcpdump
line = process.stdout.readline().decode(‘utf-8’)
if not line:
break
# Проверяем, появился ли трафик на порту
if re.search(f»UDP.*:{port}», line):
print(«1»)
except KeyboardInterrupt:
# Обрабатываем прерывание с клавиатуры (Ctrl+C)
process.terminate()
break
if __name__ == «__main__»:
# Укажите номер UDP порта, который вы хотите мониторить
udp_port = 12345
monitor_udp_traffic(udp_port)
Спасибо за ответ.
Еще не пробовал запустить код, но не вижу вывода «2» если трафик пропал. Сейчас попробую пояснить зачем мне нужен код.
Есть два сервиса, один отправляет в другой по udp аудиотрафик, второй анализирует этот трафик и отдает его дальше, но есть нюанс, анализ трафика проходит неверно в конце из-за неожиданного прерывания трафика, когда первый сервис перестает его транслировать. Есть возможность помочь обработке, во втором (анализирующем сервисе) есть возможность указывать начало анализа и его конец через псевдоустройство PTY. Если В начале трансляции мы на это устройство отправим «1» а когда трафик пропадет «2», то сможем предотвратить неверную обработку.
В итоге нужна примочка на питоне, которая всегда будет контролировать наличие трафика, и когда трафик появится — отправит в PTY_PATH=/tmp/sql «1», и будет ждать окончания трафика на порту, как трафик закончился — отправит туда «2» и продолжит анализировать порт.
так доработайте, основу так то дали, примерно так:
if (…) :
print(‘1’)
else:
print(‘2’)
Добрый вечер, ковыряюсь в вышеуказанном коде. Понатыкал себе выводов для дебага, кое что причесал. Если от tcpdump нет вывода, нет трафика на порту, программа останавливается на process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) и ждет пока не появится какой либо вывод из tcpdump. Как это можно исправить, мне нужно как либо зафиксировать момент, когда трафик остановился и изменить переменную trig на 0.
#!/usr/bin/python3
import subprocess
import re
import time
def monitor_udp_traffic(port):
<——>trig=0
<——>while True:
<——><——>command = f»tcpdump -i any udp port {port}»
<——><——>print(«0»)
<——><——>process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
<——><——># Ждем, пока tcpdump начнет собирать данные
<——><——>print(«000»)
<——><——>time.sleep(1)
<——><——>try:
<——><——><——>while True:
<——><——><——># Считываем строки из вывода tcpdump
<——><——><——><——>print(«Reading»)
<——><——><——><——>line = process.stdout.readline().decode(«utf-8»)
<——><——><——><——>print(line)
<——><——><——><——>if not line:
<——><——><——><——><——>print(«10»)
<——><——><——><——><——>trig=0
<——><——><——><——><——>break
<——><——><——><——>#Проверяем, появился ли трафик на порту
<——><——><——><——>print(«4»)
<——><——><——><——>if re.search(f'{str(port)}: UDP’, line):
<——><——><——><——><——>trig=1
<——><——><——><——><——>print(«1»)
<——><——><——><——>else:
<——><——><——><——><——>print(«8»)
<——><——><——><——>print(trig)
<——><——>except KeyboardInterrupt:
<——><——><——># Обрабатываем прерывание с клавиатуры (Ctrl+C)
<——><——><——>process.terminate()
<——><——><——>break
if __name__ == «__main__»:
<——># Укажите номер UDP порта, который вы хотите мониторить
<——>udp_port = 4810
<——>monitor_udp_traffic(udp_port)