python запуск bash скрипта
Выполнение shell команд с Python
Повторяющиеся задачи созрели для автоматизации. Разработчики и системные администраторы обычно автоматизируют рутинные задачи, такие как проверки работоспособности и резервное копирование файлов, с помощью сценариев оболочки. Однако, поскольку эти задачи становятся более сложными, сценарии оболочки могут усложняться в обслуживании.
К счастью, мы можем использовать Python вместо сценариев оболочки для автоматизации. Python предоставляет методы для запуска команд оболочки, предоставляя нам ту же функциональность, что и сценарии оболочки. Изучение того, как выполнять команды оболочки в Python, открывает нам возможность автоматизировать компьютерные задачи структурированным и масштабируемым образом.
В этой статье мы рассмотрим различные способы выполнения команд оболочки в Python и идеальную ситуацию для использования каждого метода.
Использование os.system для запуска команды
Давайте начнем с создания нового файла Python с именем echo_adelle.py и введите следующее:
В вашем терминале запустите этот файл с помощью следующей команды, и вы должны увидеть соответствующий вывод:
Давайте создадим новый файл с именем cd_return_codes.py и введите следующее:
В этом сценарии мы создаем две переменные, в которых хранятся результаты выполнения команд, которые изменяют каталог на домашнюю папку и на несуществующую папку. Запустив этот файл, мы увидим:
Выполнение команды с подпроцессом
В новом файле с именем list_subprocess.py напишите следующий код:
Запустите этот файл, и вывод вашей консоли будет похож на:
Мы используем довольно много параметров, давайте рассмотрим их:
Запуск этого файла приводит к следующему выводу:
Мы также можем бросить Exception без проверки значения возврата. В новом файле false_subprocess.py добавьте код ниже:
В вашем терминале запустите этот файл. Вы увидите следующую ошибку:
Выполнение команды с Popen
Класс subprocess.Popen предоставляет больше возможностей для разработчика при взаимодействии с оболочкой. Тем не менее, мы должны быть более точными в получении результатов и ошибок
По умолчанию subprocess.Popen не останавливает обработку программы Python, если ее команда не завершила выполнение. В новом файле с именем list_popen.py введите следующее:
Допустим, мы не хотим ждать завершения выполнения команды оболочки, чтобы программа могла работать над другими вещами. Как узнать, когда команда оболочки закончила выполнение?
В новый файл с именем cat_popen.py добавьте следующий фрагмент кода:
Какой из них я должен использовать?
Вот таблица с некоторыми различиями в юзабилити, которые вы также можете использовать для обоснования своего решения:
Запуск скрипта питон в скрипте баш
Решил более подробно изложить ситуацию.
Есть баш скрипт который делает всякие вычисления, и определяет переменные, которые затем будут заданы в виде параметров у питон скрипта
При запуске BASH скрипта, не чувствуется работа скрипта
и выполняю, то вывод будет такой:
2 ответа 2
на интерпретатор python, запускаемый из shell-скрипта, эта внутренняя команда оболочки, естественно, не оказывает (да и не может оказать) никакого влияния.
разница же в поведении вашего python-скрипта, возможно, вызвана разными наборами опций и параметров, которые вы передаёте этому скрипту в одном и в другом случае.
сравниваю аргументы двух вызовов (я убрал явно совпадающие):
и тут, вероятно сказывается либо специфика работы программы python (я встречал подобное в некоторых случаях), либо специфика скрипта crowbar.py : скрипт «воспринимает» эти строки не в качестве опций, а в качестве параметров.
возможно, сможет помочь использование встроенной в оболочку команды eval :
обновление
также можно попробовать «разорвать питонов узел». попробуйте вызывать crowbar.py без явного указания интерпретатора.
для этого предварительно файлу надо добавить бит исполнимости:
а затем в bash-скрипте вызывать его по имени:
этот же вызов можно попробовать и «завернуть» в eval :
Пишем shell скрипты на Python и можно ли заменить им Bash
В этой небольшой статье речь пойдет о том, можно ли легко использовать Python для написания скриптов вместо Bash/Sh. Первый вопрос, который возникнет у читателя, пожалуй, а почему, собственно, не использовать Bash/Sh, которые специально были для этого созданы? Созданы они были достаточно давно и, на мой взгляд, имеют достаточно специфичный синтаксис, не сильно похожий на остальные языки, который достаточно сложно запомнить, если вы не администратор 50+ левела. Помните, ли вы навскидку как написать на нем простой if?
Элементарно правда? Интуитивно понятный синтаксис. 🙂
Тем не менее в python эти конструкции намного проще. Каждый раз когда я пишу что то на баше, то непременно лезу в поисковик чтобы вспомнить как писать простой if, switch или что-то еще. Присвоение я уже запомнил. 🙂 В Python все иначе. Я хоть и не пишу на нем круглые сутки, но никогда не приходилось лезть и смотреть как там сделать простой цикл, потому что синтаксис языка простой и интуитивный. Плюс ко всему он намного ближе к остальным мейнстримовым языкам типа java или c++, чем Bash/Sh.
Также в стандартной и прочих библиотеках Python есть намного более удобные библиотеки чем консольные утилиты. Скажем, вы хотите распарсить json, xml, yaml. Знаете какой я недавно видел код в баше чтобы сделать это? Правильно:
И это был не мой код. Это был код баше/питоно нейтрального человека.
То же самое с регексом, sed бесспорно удобная утилита, но как много людей помнит как правильно ее использовать? Ну кроме Lee E. McMahon, который ее создал. Да впринципе многие помнят, даже я помню как делать простые вещи. Но, на мой взгляд, в Python модуль re намного удобнее.
В этой небольшой статье я хотел бы представить вам диалект Python который называется shellpy и служит для того, чтобы насколько это возможно заменить Bash на python в скриптах.
Введение
Shell python ничем не отличается от простого Python кроме одной детали. Выражения внутри grave accent символов ( ` ) в отличие от Python не является eval, а обозначает выполнение команды в шелле. Например
и это тоже будет корректным синтаксисом.
Можно выполнять сразу несколько команд на разных строках
и команды, занимающие несколько строк
Выполнение каждого выражения в shellpy возвращается объект класса Result
Это можно быть либо Result либо InteractiveResult (Ссылки на гитхаб с документацией, можно и потом посмотреть 🙂 ). Давайте начнем с простого результата. Из него можно легко получить код возврата выполненной команды
И текст из stdout и stderr
Можно также пробежаться по всем строкам stdout выполненной команды в цикле
Для результата есть также еще очень много синтаксического сахара. Например, мы можем легко проверить, что код возврата выполняемой команды равен нулю
Или же более простым способом получить текст из stdout
Все вышеперечисленное — это обзор синтаксиса вкратце, чтобы просто понять основную идею и не грузить вас всеми-всеми деталями. Там есть еще много чего и для интерактивного взаимодействия с выполняемыми командами, для управления исполнением команд. Но это все детали, в которые можно окунуться в документации (на английском языке), если сама идея вам покажется интересной.
Это ж не валидный синтаксис Python получается, как все работает то?
Магия конечно, как еще 🙂 Да, друзья мои, мне пришлось использовать препроцессинг, каюсь, но другого способа я не нашел. Я видел другие библиотеки, которые делают нечто подобное, не нарушая синтаксиса языка вроде
Но меня такой синтаксис не устраивал, поскольку даже несмотря на сложности, хотелось получить best user experience ©, а для меня это значит насколько это возможно простое и близкое к его величеству Шеллу написание команд.
Знакомый с темой читатель спросит, чем IPython то тебя не устроил, там ж почти как у тебя только значок другой ставить надо, может ты просто велосипедист, которому лень заглянуть в поисковик? И правда он выглядит вот так:
Я его пытался использовать но встретил пару серьезных проблем, с которыми ужиться не смог. Самая главная из них, то что нет простого импорта как в Python. То есть ты не можешь написать какой-то код на самом ipython и легко его переиспользовать в других местах. Невозможно написать для своего ipython модуля
и чтобы все сразу заработало как в сказке. Единственный способ переиспользовать скрипт, это выполнить его. После выполнения в окружении у тебя появляются все функции и переменные, объявленные в выполняемом файле. Не кошерно на мой взгляд.
В shellpy код переиспользуется легко и импортируется точно так же как и в обычном python. Предположим у нас есть модуль common в котором мы храним очень полезный код. Заглянем в директорию с этим модулем
Мы видим что тут объявлена функция, которая внутри себя использует shellpy синтаксис чтобы вернуть результат выполнения `echo 5. Как этот модуль используется в коде? А вот как
Видите? Как в обычном Python, просто взяли и заимпортировали.
Как же все работает. Это работает с помощью PEP 0302 — New Import Hooks. Когда вы импортируете что-то в своем коде то вначале Python спрашивает у хука, нет ли тут чего-то твоего, хук просматривает PYTHONPATH на наличие файлов *.spy или модулей shellpython. Если ничего нет, то так и говорит: «Ничего нету, импортируй сам». Если же он находит что-то там, то хук занимается импортом самостоятельно. А именно, он делает препроцессинг файла в обычный python и складывает все это добро в temp директорию операционной системы. Записав новый Python файл или модуль он добавляет его в PYTHONPATH и за дело берется уже самый обыкновенный импорт.
Давайте же скорее посмотрим на какой-нибудь пример
Этот скрипт скачивает аватар юзера Python с Github и кладет его в temp директорию
Установка
Запустим же что-нибудь
После установки можно потестировать shellpython на примерах, которые доступны прямо в репозитории.
Также здесь есть allinone примеры, которые называются так, потому что тестируют все-все функции, которые есть в shellpy. Загляните туда, чтобы лучше узнать что же там еще такого есть, либо просто выполните
Для третьего Python команда выглядит вот так
Совместимость
Если найдете проблемы — пишите в коммент, либо сюда либо телеграфируйте как-нибудь 🙂
Документация (на английском)
Можно ли законтрибьютить
Оно мне ничего в продакшене не разломает?
Сейчас версия 0.4.0, это не стейбл и продакшн процессы пока лучше не завязывать на скрипт, подождав пока все отладится. Но в девелопменте, CI можно использовать вполне. Все это покрыто тестами и работает 🙂
Запуск python скрипта с параметрами из bash
Добрейшего дня! Трабл. Есть скрипт ip-up, который отрабатывает при подключении pptp-клиента. Есть скрипт, назову его условно connect, которому передаются параметры от ip-up. Скрипты на bash. Все прекрасно работает. Возникла необходимость переписать bash-скрипт на python3. Скрипт умеет принимать параметры. Проблем тут нет. Проблема возникает когда, я пытаюсь передать параметры от ip-up. То есть connect(bash) принимает параметры, а connect(python) не воспринимает их. Если запускаю вручную в терминале (debian 8):
Тут загвоздочка. Не могу выложить. Не положено. Извините=)
Ну хотя бы часть, отвечающую за эту функциональность, либо сделать кошечные скрипты чтоб на них тренироваться
отрежь все, что секурно, выложи все, что можно. нужно глядеть именно связки запуска
Ну добавь логирования в скрипт, убедись что параметры действительно имеются. Попробуй перекатись на переменные среды.
Ща, господа, сбацаю пару простых скриптов. Для понимания сути просто. Немножко времени дайте.
Абсолютно стандартный скрипт ip-up из /etc/ppp. В него в конце добавлена строка:
вот в таких кавычках?
Делал уже. Не помогло.
И, кстати, у тебя там connectpy вместо connect.py. Не в этом ли проблема?
объясняю. Есть два варианта. Оба работают одинаково. 1. python3 connect.py 2. файл без py. Первой строкой #!/bin/python3
На всякий случай уточню:
Надеюсь все-таки #!/usr/bin/python3
Творятся чудеса. Нащупал нить. Отпишусь по результатам.
Пошел путем от простого к сложному. Один скрипт на bash запускает скрипт на python и передает ему параметры.
Я все-таки склоняюсь, что проблема в кодировке. А можно как-то в режиме отладки запустить скрипт и вывести инфу в файл?
Уже тоже подумал об этом. Буду пробовать варианты. Отпишусь.
А если так сделать:
т.е. скрипт ip-up сейчас оригинальный, без коррективов. Если его запустить в mc руками, то скрипт python из папки ip-up.d срабатывает как надо. Создает файл со строкой внутри.
Я имел в виду, эту строку прописать в баш-скрипт.
что только не пробовал. Уже через вызов внешней программы, которая запускает скрипт и передает ему параметры. Суть такова. Скрипт запущенный в любом месте и любым образом работает. При запуске с использованием ip-up действуют некие ограничения ввода/вывода, которые мешают корректной работе скрипта.
«Имеются следующие ограничения на /etc/ppp/ip-up:
Про полные пути понятно, А вот что конкретно таит в себе преднамеренно ограниченное окружение не совсем понятно. Но ограничения эти накладываются на все запущенные через ip-up скрипты и/или программы. Как я понял ввод/вывод происходит иначе, чем при ручном запуске скриптов. И дело тут нев правах и путях, а именно в самом принципе работы ip-up/down. Есть у кого какие мысли на этот счет? Не хочется переделывать python обратно на bash 🙁
Поэтому и не воспринимает получается мой скрипт на python корректно параметры, которые передает ip-up и запись в файл не происходит.
Блин, ребята, может кто у себя проверить? Может возникнут идеи.
Попробовал набросать скрипт на lua. Получилось принять параметры от ip-up и даже в файл все красиво записалось. Никаких манипуляций не пришлось делать ни с правами, ни с кавычками. Буду переписывать скрипт на lua. Одна проблема, что я в нем пока не шарю. Придется разбираться сразу на практике. Самое время для быдлокода=))
А вот что конкретно таит в себе преднамеренно ограниченное окружение не совсем понятно.
Не устанавливаются переменные окружения? Как их подтянуть в пистоне я хз.
В lua работает как надо. Ковыряюсь с переносом скрипта. Спасибо.
Запуск python скрипта в Linux
На этом языке написано огромное количество системных программ, среди них пакетный менеджер apt, видеоредактор OpenShot, а также множество скриптов, которые вы можете установить с помощью утилиты pip. В этой небольшой статье мы рассмотрим как запустить Python скрипт в Linux с помощью терминала различными способами.
Запуск python скрипта в Linux
Для примера нам понадобится Python скрипт. Чтобы не брать какой-либо из существующих скриптов, давайте напишем свой:
print(«Hello from losst!»)
Для того чтобы запустить скрипт необходимо передать его интерпретатору Python. Для этого просто откройте терминал с помощью сочетания клавиш Ctrl + Alt + T, перейдите в папку со скриптом и выполните:
Но как вы могли заметить, при запуске apt или openshot не надо писать слово python. Это намного удобнее. Давайте разберемся как это реализовать. Если вы не хотите указывать интерпретатор в командной строке, его надо указать в самом скрипте. Для этого следует в начало скрипта добавить такую строчку:
Сохраните изменения, а затем сделайте файл скрипта исполняемым с помощью такой команды:
chmod ugo+x script.py
После этого можно запустить скрипт Python просто обращаясь к его файлу:
Как видите, запуск команды python Linux выполняется довольно просто и для этого даже есть несколько способов. А каким способом пользуетесь вы? Напишите в комментариях!