Знание некоторых принципов легко возмещает незнание некоторых фактов (К. Гельвеций).

Выполнение команд оболочки с Python

21.01.2019

Python — отличный язык сценариев. Все больше системных администраторов используют скрипты Python для автоматизации своей работы.

Поскольку в задачи системный администратор все время включает команды Linux, выполнение команд Linux из скрипта Python является отличной помощью.

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

 

Выполнить команду Shell в Python с модулем os

Позвольте нам создать простую программу на 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 с модулем подпроцесса

Несколько лучший способ запуска команд оболочки в 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. Если у вас есть вопросы или предложения, пожалуйста, не стесняйтесь оставить комментарий ниже.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (3 оценок, среднее: 5,00 из 5)
Загрузка...
Поделиться в соц. сетях:

6 комментариев

kadyr 30.03.2022 от 8:39

Есть ли возможность настроить взаимодействие python скрипта c консольным приложением linux

Денис 22.10.2023 от 19:03

Добрый день, а можно попросить Вас написать код, который будет запускать tcpdump контролирующий наличие трафика на UDP порту. Как трафик появился, написать в консоли 1, как трафик на порту пропал — написать 2. Мониторинг должен проводиться постоянно.

    AndreyEx 22.10.2023 от 19:07

    Примерно так:

    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)

      Денис 22.10.2023 от 19:53

      Спасибо за ответ.
      Еще не пробовал запустить код, но не вижу вывода «2» если трафик пропал. Сейчас попробую пояснить зачем мне нужен код.
      Есть два сервиса, один отправляет в другой по udp аудиотрафик, второй анализирует этот трафик и отдает его дальше, но есть нюанс, анализ трафика проходит неверно в конце из-за неожиданного прерывания трафика, когда первый сервис перестает его транслировать. Есть возможность помочь обработке, во втором (анализирующем сервисе) есть возможность указывать начало анализа и его конец через псевдоустройство PTY. Если В начале трансляции мы на это устройство отправим «1» а когда трафик пропадет «2», то сможем предотвратить неверную обработку.
      В итоге нужна примочка на питоне, которая всегда будет контролировать наличие трафика, и когда трафик появится — отправит в PTY_PATH=/tmp/sql «1», и будет ждать окончания трафика на порту, как трафик закончился — отправит туда «2» и продолжит анализировать порт.

        AndreyEx 22.10.2023 от 19:57

        так доработайте, основу так то дали, примерно так:

        if (…) :
        print(‘1’)
        else:
        print(‘2’)

          Денис 23.10.2023 от 15:41

          Добрый вечер, ковыряюсь в вышеуказанном коде. Понатыкал себе выводов для дебага, кое что причесал. Если от 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)

Оставить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Это может быть вам интересно


Загрузка...

Спасибо!

Теперь редакторы в курсе.

Прокрутить страницу до начала