Написание консольных скриптов: Bash против Python
Компьютер — это цифровое устройство, распознающее только определенные двоичные инструкции. Без операционной системы можно пользоваться лишь некоторым количеством встроенных на аппаратном уровне микропрограмм, таких как утилиты BIOS.
Операционные системы упрощают работу с компьютерами и позволяют запускать предварительно разработанные программы (например, текстовые процессоры, веб-браузеры и утилиты). Сегодня большинство операционных систем работают как с графическим интерфейсом пользователя (GUI, Graphical User Interface), так и с интерфейсом командной строки (CLI, Command Line Interface).
Программисты обычно выбирают интерфейс командной строки, поскольку по сравнению с графическим интерфейсом он лучше подходит для их повседневных дел. Через CLI часто развертывают ПО, работают с файловой системой и настраивают компьютер. CLI — это эффективный способ выполнять разные задачи. Но при этом часто одни и те же вводимые команды приходится запускать с некоторыми изменениями.
В результате появились интерпретаторы CLI и концепция сценариев (англ. shell script) для запуска файлов с предварительно написанными командами. Bash — это популярный командный язык для запуска сценариев, который встроен в большинство операционных систем. С другой стороны, многие программисты используют в качестве альтернативы Python, имеющий встроенные функции, которых нет у Bash.
Сравним Bash и Python с точки зрения написания консольных сценариев. Помимо этого, разберем менее известные методы написания таких сценариев, позволяющие улучшить навыки автоматизации с помощью Bash и Python.
Bash: самый естественный способ писать консольные скрипты
Основным предназначением сценариев командной оболочки является запуск и выполнение с помощью интерпретатора предварительно написанной последовательности команд. Обрабатывая каждый ввод/выражение как команду, Bash обеспечивает эффективную автоматизацию повседневных рутинных операций. Вспомните, как вы впервые использовали терминал на базе Bash, не читая документации и не следуя учебнику:

Bash не работает как язык общего назначения — он всегда мотивирует использовать другие программы. Например, для приведенного выше сценария можно использовать expr 10 + 15. Однако сегодня Bash поддерживает еще и встроенные функции для решения распространенных задач, поэтому другие программы вызывать нужно не всегда.
Например, основные арифметические операции позволяет выполнять функция арифметических расширений
Bash выполняет команды нативно, без специального расширенного синтаксиса. Для стандартных задач программирования этого достаточно.
Python: современный способ расширения функциональности Bash
Если Bash нативно выполняет стандартные команды и поддерживает многие популярные функции, то почему программисты используют для автоматизации своих операций Python? Ответ в следующей выдержке из документации Python самых ранних выпусков
Согласно этой документации, Python изначально разрабатывался для объединения языка сценариев оболочки и возможностей программирования на уровне операционной системы. Bash не имеет нативного доступа к API уровня операционной системы (известным как C API).
Таким образом, если сценарию требовался доступ к C API, приходилось использовать такие обходные пути, как создание исполняемого файла на другом языке программирования. Python решил эту проблему: он предложил удобный для автоматизации лаконичный язык с доступом к C API и даже с кросс-платформенным доступом к API уровня операционной системы.
Python оценивает исходный код с точки зрения операций стандартного программирования — сам по себе он не может выполнять другие программы, но предлагает API дочерних процессов (child process API).
Выяснив как цели, так и основы Bash и Python, займемся теперь их сравнением.
Bash или Python: что лучше для автоматизации
Программисты пишут различные сценарии оболочки, в том числе выполняющие несколько команд POSIX (например, mv, cp и т. д.). В некоторых случаях необходимо включить в них обработку данных и операции на уровне ОС. А иногда нужно писать и кроссплатформенные скрипты автоматизации.
При сравнении современных языков программирования почти всегда, как и в данном случае, нет победителя. Оптимальный вариант сценария оболочки определяет сценарий разработки.
Bash хорош для следующих сценариев.
- Автоматизация операций командной строки POSIX с небольшим объемом обрабатываемых данных, т. е. сценариев системного администрирования.
- Написание сценариев оболочки, которые выполняют настройку, обработку и другие операции с помощью программ CLI. Например, написание сообщений фиксации Git и развертывание приложения с помощью инструментария CLI.
- Bash — хороший вариант для сценариев в Unix с расширенной переносимостью, поскольку интерпретатор Bash более широко предустановлен, чем Python.
Python хорош для следующих сценариев.
- Автоматизация задач, включающих больше обработки данных (алгоритмических операций) и доступа к низкоуровневым API, чем выполнения других программ CLI.
- Написание кроссплатформенных сценариев автоматизации, которые выполняют команды, используют низкоуровневые API и выполняют общую обработку данных в GNU/Linux, Windows, macOS и других ОС с поддержкой Python. Например, исходный код BuildZri.
В целом, Bash — это самый минимальный, естественный и нативный способ написания сценариев автоматизации с другими программами командной строки в текстовом окне. С другой стороны, Python — это стандартный кроссплатформенный язык. Его можно использовать в качестве альтернативы Bash для написания сценариев оболочки с доступом к низкоуровневым API операционной системы и обработкой данных.
Используйте Bash и Python совместно
Между Bash и Python нет особой конкуренции, поскольку это два разных типа инструментов программирования. Bash — командный язык, а Python — язык общего назначения. В зависимости от требований можно выбрать либо один вариант, либо оба.
Предположим, что для добавления двух десятичных знаков используется bc следующим образом:
#!/bin/bash sum=$(bc <<< "1.5 + 2.51") echo $sum
С помощью Python можно сделать то же самое:
#!/bin/bash sum=$(python3 <<< "print(1.5 + 2.51)") echo $sum
Многие программисты используют Bash в своих сценариях Python. Это удобнее, чем применять разные сторонние пакеты Python. Например, следующий скрипт находит идентификатор процесса программы Gedit:
#!/usr/bin/env python3
import subprocess
gedit_pid = subprocess \
.getoutput("ps -ef | grep gedit | head -1 | awk '{print $2}'") \
.strip()
print(gedit_pid)
Решение проблем Bash и Python
И у Bash, и у Python есть некоторые недостатки применительно к современным требованиям к автоматизации. С Bash довольно трудно писать сценарии оболочки с доступом к API на уровне операционной системы и выполнять обработку сложных данных. В Python с API subprocess написание минимально исполняемых программ из командной строки синтаксически не похоже на оболочку.
Для C API в Bash имеется расширение Bash ctypes.sh..
Есть даже веб-сервер HTTP httpd.sh, написанный на Bash с использованием интерфейса внешних функций (FFI) ctypes.sh.
Проект pysh предлагает простой способ выполнения операторов Bash в скриптах Python с помощью символа >, как показано в следующем фрагменте кода:
for i in xrange(100): index = "%02d" % i > mv from$index.txt to$index.txt
Проект zxpy (на основе zx от Google) позволяет продуктивно выполнять операции командной строки с помощью Python следующим образом:
#! /usr/bin/env zxpy
~'echo Hello world!'
file_count = ~'ls -1 | wc -l'
print("file count is:", file_count)
Заключение
Концепция сценариев оболочки появилась в 1970-х годах вместе с оболочкой Thompson для среды Unix. Идея традиционных сценариев оболочки заключается в выполнении операций командной строки из файла в целях автоматизации. Современная методология DevOps расширила традиционную концепцию сценариев оболочки для автоматизации, включив в нее вызовы RESTful API, обработку данных и другие операции DevOps.
Использовать Bash для создания сценариев оболочки не считается устаревшей практикой, поскольку так можно выполнять команды в исходном формате без API дочерних процессов (они включены нативно). Python часто используют как современную альтернативу Bash, расширяющую его нативные возможности операций командной строки.
Перевод статьи Shalitha Suranga: Bash vs. Python: For Modern Shell Scripting