Pull to refresh

Comments 173

Странный выбор для сравнения... Помню тут некоторое время назад кто то Airflow c NiFi сравнивал - из той же оперы....

Почему? Выбор "уже писать скрипт на python или ещё bash справится?" стоит часто.

В реальных задачах за свои почти 20 лет опыта никогда не встречал такой дилеммы.
Можете привести реальные примеры рабочих задач? Не когда вам надо "для себя" что-либо сделать локально?

Автоматизировали CI силами разработчиков, попробовали оба варианта. В итоге стало однозначно понятно, что Python разработчиками на .NET и Kotlin читается и пишется гораздо проще, чем Bash)

Для реальных рабочих задач можно всегда выбирать питон.

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

Мониторим Proxmox. Возникла проблема: сам прокс отсылает метрики нечасто, в них отсутствуют дополнительные маунтпойнты, теги и пулы.
Пилежка своих метрик заканчивается разбором конфигов, мониторингом конфигов на предмет изменений, попыткой изобрести join в консоли…

Если я правильно вас понял, вы пытаетесь решить задачу каким-то быстрым наколеночным решением. Это не плохо. Часто так приходится делать. Но это не для ПРОДа.

Ну, у нас есть некоторые сервисы типа oneshot, которые отсылают метрики curl'ом — просто и без затей.
С самим проксом сначала задача была примитивной: вытащить в метрики теги для упрощения строительства дашборд. Часто их обновлять не надо, так что можно просто сделать это на баше.
Но задача стала раздеваться по мере выполнения, и баш справляться с ней перестал. Точнее, он перестал справляться удобно.

Я думаю тут ключевое - "удобно". ОЧень часто простые и "правильные" решения обычному обывателю(в т.ч. разработчику) как раз неудобны. Но надо понимать, что "неудобность" - понятие субъективное

Если в команде код понимает только один человек, то надо менять или команду или код ) Второе — проще.

всегда топлю за то чтобы скриптовать рабочие задачи именно на bash. да, питон даёт больше возможностей, но скрипт написанный на bash мной 10 лет назад всё ещё в проде ни как не изменившись, а скрипт написанный мной на питоне 5 лет назад уже трижды переписывался, сначала из pypi пропала какая-то важная для скрипта зависимость, потом между версиями питона сломали что-то.. радует только то что это уже не мои проблемы.

Алсо, в прошлом году довелось поучавствовать в созвоне где стильномодномолодёжный девопс предлагал переписать все скрипты на nodejs.. сказать что у меня волосы зашевелились по всему телу ничего не сказать..

сначала из pypi пропала какая-то важная для скрипта зависимость

Сдается мне, что если скрипт на питоне требует зависимостей - на баше его реализовать будет невероятно сложно.

Не всегда это является правдой. Иногда народ делает зависимости на какие-то совершенно тривиальные вещи.

Например: https://www.npmjs.com/package/is-number

https://www.npmjs.com/package/is-number?activeTab=code почитал я код - нетривиальные проверки. я бы навскидку только Number.isNan( ) проверял бы. После парочки трудноуловимых багов пришел бы к коду как в библиотеке.

просто ставите зависимости, тольк не через pip а через системный пакетный мереджер.

Кажется тот-же jq не везде идёт из коробки.

А чё в Докер не запихнули? :)

А для стабильности скриптов нужно использовать не pypi, а системные пакеты. :)

Хотя, ИМХО, Python-скрипты обычно стабильнее. Ибо CLI API любят ломать гораздо чаще, чем API библиотечный.

А потом из системы исчезает python2.

Не прошло и 20 лет.

А bourne shell вышел в 1977

Но, справедливости ради, в некоторых новых версиях сломалась обратная совместимость в некоторых местах.

https://mywiki.wooledge.org/BashPitfalls

Можно немного поточнее, для общего развития?
То там длиннючий список типичных ошибок новичка, вроде о, в nginx есть if'ы! сейчас я вам запрограммирую!

Вот что я имел ввиду:

Скрытый текст
62. (( hash[$key]++ ))

Surprise!  Associative arrays are even more
 broken in math contexts.  The single-quoting trick from the previous 
pitfall isn't enough to fix this, either -- it only works in versions 
5.0 and lower. 

После версии 5.0 использование одиночных кавычек для применения хешмап в математическом контексте ограничили. Т.е. то что работало раньше перестало работать. Ну и экранирование знака доллара после 5.2 здесь же тоже сломали.

Либо я не правильно понял, тогда прошу меня поправить, пожалуйста.

p.s.: Сделал кодом, т.к. цитатой не давало вставить...

А, ассоциативные массивы! Да, похоже, для нетривиальных случаев они немного поломаны…
Посмотрел свои скрипты — \$() и \${} работают.

С баш аргументами есть особенности когда пишешь и тестируешь на маке, а прод на линуксе. GNU и BSD командны не полностью совместимы по аргументам.

На маке всегда можно локальную машинку с линуксом поднять. Я так и делаю.

А для стабильности скриптов нужно использовать не pypi, а системные пакеты. :)

и я полностью согласен, и именно из реп и юзал, вот только если питоняшка пропадает из pypi (читай первоисточника) то мейнтейнеры дистрибутива её и из реп выпинывают тоже, ни в одном вменяемом дистрибутиве ни один вменяемый мейнтейнер не станет держать в репозиториях пакет оставшийся без апстрима.

Это действительно важный аргумент, однако в противовес можно сказать, что Python предоставляет бОльшую гибкость, за что расплачивается как раз тем, что надо окружение настраивать дополнительно (должны быть стандарты по конфигурации серверов, внутренние репозитории-зеркала, надо больше отслеживать уязвимости и реагировать на них) . И не всегда эта гибкость нужна и даже уместна. Плюс научить стильноможномолодежных девопсов проще писать на Python. Поэтому тут надо смотреть под задачу/команду и выбирать с умом.

У меня волосы шевелятся когда я вижу любой код на bash)) Как вообще на этом можно что-то писать? Хотя Питон я тоже не люблю, но он хотя-бы придерживается классического синтаксиса языков программирования.

Нет, вполне понятно что любые скрипты командной строки - это в каком-то смысле развитие самой идеи запуска программ в командной строке, а значит синтаксис путей, аргументов командной строки, пайплайнов и т.п. должен быть в скриптах без изменений. Это накладывает существенные ограничения на синтаксис скриптов - строки не в кавычках, пробелы вместо запятых и прочая муть, делающая bash очень сильно отличающимся от любого классического языка. Не знаю можно ли было пойти по другому пути в принципе... Я не пишу "скрипты" как таковые, но если мне нужна простая утилита командной строки - я пишут ее на Go.

В эту тему в истории вляпывались уже много раз. IBM неизменно приходила к языку REXX, а тут, видимо, питоном дело кончится:

VM/CMS: exec -> exec2 -> rexx

PC-DOS: bat -> rexx

OS/2: cmd -> rexx

*nix: sh -> bash -> python?

Мысленно плюсую к данной позиции её, позиции, сдержанность. Вы хотя бы признаёте, что не являетесь скриптером. Окей. Именно поэтому спорить не буду.

Только лишь замечу, что вы интуитивно правильно сказали, действительно, дело именно в том, что shell-подобные языки должны быть в первую очередь удобными интерактивными интерпретаторами, и уже во вторую очередь скриптовыми языками, для выполнения команд по сложной логике.

В действительности же на bash можно писать даже довольно большие скрипты, и работать это будет великолепно.

и работать это будет великолепно.

Только не забывать экранировать пробелы, кавычки, символы экранирования. Иногда 2 раза ;)

на bash можно писать даже довольно большие скрипты

Чуть более 10 лет назад я на bash писал скрипт, который забирал и парсил статистику по API World of Tanks и отображал ее в conky.

строки не в кавычках, пробелы вместо запятых и прочая муть

Зато нет управления логикой программы отступами, а это уже большой +:)

Зато нет управления логикой программы отступами

Вам отступы или ехать ;)

Это какой такой классический синтаксис у питона? по моему там синтаксис отсутствует как понятие вообще. Эти дурацкие пробелы, с которыми постоянно куча проблем. Но главный подвох в том, что вроде бы все построено на пробелах, но ифы ты двоеточиями закрывай, да и циклы тоже закрывай и много чего еще и встает вопрос, а зачем тогда было делать все на пробелах, если по итогу я выборочно буду завершение строк проставлять?

Если писать в блокноте, то и в скобочках можно запутаться. Я и на питоне и на языках в стиле С пишу. И там и там нормально. А еще код в сиподобных языках часто форматируют оступами, что выглядит очень похоже на Питон.

Так с таким успехом, если удобство синтаксиса определяется не синтаксисом, а ИДЕ в которой ты пишешь, то и у баша замечательный синтаксис и у с подобных, если в правильной ИДЕ кодить.

Согласен, за это я Питон не люблю (как уже отметил выше). Но в сравнении с bash у него хотя-бы частично классический синтаксис. Строки это строки, числа это числа, классически задаются списки, массивы и т.д.

Так если у вас скрипты не изменяются десятилетиями, то почему бы не собрать бинарник питоновского скрипта?

а если через 10 лет захочется поменять?

Если проект еще будет жить, то новый человек перепишет к этому моменту под себя.

Используем на работе pex. При переходе на новую операционку pex собранные в старой операционке перестали работать. Там была зависимость от системных библиотек, которые в операционке поменялись.

Это странно звучит на фоне того, что в плюс питону ставят мол он скриптовый, очень удобно. И вот вы предлагаете пойти по пути компилируемых языков, тем самым намекая, что плюса у питона и не было.

Ksh обычно используется в операционных системах семейства BSD

???
в последния раз я слышал про ksh в контексте скотоюникса, в р-не 1999 г.

Ещё в AIX он идёт по умолчанию.

Из BSD вроде только openBSD его по умолчанию использует. Остальные же sh.

Скрипты на sh обычно используют утилиты которые есть практически во всех дистрибутивах из коробки.

В случае если мне надо написать что то на питоне начинается пляска зависимостями. Которые нужно дополнительно устанавливать всегда. А если это изолированная машина и никакой pip недоступен, то это вообще гроб гроб кладбище.

Если задача стоит написать на более человеческом современном языке, то проще на go собрать один бинарник и залить на удаленный сервер, чем поднимать всё окружение python.

а читать его как?

Что-то мешает собрать из пайтона standalone?

Для сборки из пайтона standalone нужно хорошее понимание внутрянки, нюансов того или иного тула и окружения. Особенно если в зависимостях используется что-то бинарное. Такие навыки находятся сильно сбоку, если вы просто пишите скрипты. Проще собрать docker контейнер. Но это все равно получается какое-то нагромождение.

Глобально-то да, но речь идет как раз о простых случаях же

Для таких случаев придумали pyinstaller, который среди прочего может превратить скрипт со всеми зависимостями в один монолитный файл

У Питона сильная стандартная библиотека. Часто можно обойтись вообще без зависимостей.

зачем зависимости для аналога башевского скрипта?

А еще если кто помнит лет так много назад половину системных скриптов писали на Perl.
Но видимо новые программисты не осилили и придумали Python, чтобы делать то же самое.

При этом, "развитие" Perl (а точнее переделка и нарушение совместимости) закончилось давным-давно, поэтому скрипты на нем 10-20 летней давности, еще для тех, медленных компьютеров с небольшим объемом памяти, работают и сегодня, только быстрее.

В отличии от скриптов на python2, например wicd, которые еще попробуй заставить работать с python3...

В этом смысле лучше всего чистый sh, оно будет работать везде, ну еще более-менее bash.
Но и там ломают совместимость, заменяя стандартные UNIX-утилиты типа ifconfig на ip, создавая потом эмуляторы ifconfig на python...

В общем, нескучно людям.

Звучит как "новое поколение не осилило рассчёты на бумажке и решили использовать компьютеры". На Perl плохочитаемые скрипты сделать было даже проще, чем на bash ;)

На Perl плохочитаемые скрипты сделать было даже проще, чем на bash ;)

Я насмотревшись на подобные произведения современного админского искусства начал ценить то, что Python за такое бьёт по рукам. :)

А кто заставляет писать плохо читаемые скрипты?

Разве что стремление показать свои глубокие знания языка.

Но если простые скрипты "плохо читаемые" это и называется "ниасилил" )

Я не знаю кто писать заставляет, но читать их мне приходится.

В питоне синтаксис намного беднее чем в баше. Если нуно сравнить два объекта в питоне у вас ==, is и __equals__. А в баше много вариантов.

А кроме баша нужно еще и синтакис системных комманд.

Чистый sh может и будет работать везде, но ведь в нем будут использоваться другие программы для всего, например grep, cut. И которые уже начинают работать по разному в разных ОС, придется проверять GNU ли версия (солярис), cut работает как-то по другому в AIX итд. Про специфичные утилиты типа ipconfig я вообще молчу.

Для этого есть posix стандарт (и на sed и на другие стандартные утилиты), благодаря которому даже древний sh скрипт будет работать везде.

Не знаю, как по мне, перл это не то что хочется осиливать, его философия "There’s more than one way to do it" привела к избыточной сложности на ровном месте и засилию любителей однострочников, а дальнейшее развитие языка несколько раз заходило в тупик.

Так что я прекрасно понимаю желание людей свалить с него на Пайтон.

привела к избыточной сложности на ровном месте

И где там "избыточная сложность", и, главное, что заставляет Вас её использовать?
Perl ­— не только гибкий, но и стройный язык.

При этом, "развитие" Perl (а точнее переделка и нарушение совместимости) закончилось давным-давно

Ну, развитие какое-то есть. Но я до сих пор на нём регулярно пишу скрипты автоматизации, разборки конфигов и т. д. Он вообще и был предназначен для подобного ("Practical Extraction and Report").
Ну и Bash. Без него никуда, конечно.

заменяя стандартные UNIX-утилиты типа ifconfig на ip

Задели за живое. Во-первых ifconfig не имеет никакого отношения ни к оболочке, ни к стадартам. Это просто отдельная утилита. Во-вторых, текущая версия ifconfig для линукс датирована октябрём 2001-го (!!!!) года. Тот факт, что она не только компилируется но и как-то работает, иначе как божьим промыслом, объяснить невозможно. Особенно учитывая что сетевой стек переписали раза 4 за это время. В-третьих, ifconfig основан на всратых сетевых ioctl-ах. Которые живы до сих пор, только потому, что "don't break the userspace". To ли дело iproute2 (к которому относится утилита ip), просто переводящий из английского в netlink-пакеты, которые только и позволяют описать всё богатство и разнообразие линуксового сетевого стека. Так что отмирание ifconfig — есть вселенское благо.

Имхо - скрипты на JS имеет место только в одном месте - сборочные/вспомогательные скрипты для JS проекта. Не надо это тащить в систему

UFO landed and left these words here

Баш можно править везде без проблем, а вот питон чуть посложней - без айди будет очень напряжно.

Да и версионность питона напрягает: 2 отдельно, 3 ещё на несколько поколений делится.

Пару раз щупал бесплатные впс-ки со старыми системами типа шестого цента, где в качестве системного гвоздями приколочен питон2, а сбоку для юзверя - 3.2. Так себе впечатления.

Делать выводы по каким-то бесплатным ВПС'кам довольно странно.

Автор, кстати, забыл упомянуть, что Python ещё можно собрать в exe'шник под linux/windows и он будет работать даже без Python'а в системе.

Статья отличная. Сравнения очень хорошо сделаны. Я отдаю своё предпочтение Python всё же.

В самой статье несколько раз встречал опечатки, но это не страшно. Например, "loggong.DEBUG" - надеюсь, что автор перечитает и всё поправит.

А shell=True в статье вас не смущает? Это же возможность писать баш прямо внутри Питона, чтобы собрать минусы обоих систем.

Ага, особенно пробелы вокруг "=" в статье. В целом статья хорошая и выводы сделаны на мой субъективный взгляд верные. Баш для простых задач, а Python для сложных составных. Хотя лично я стараюсь всегда использовать именной Python.

Про пробелы — PEP 8 не рассматривает случаи, когда каждое значение функции указывается на отдельной строке. А в этом случае читабельнее код именно с пробелами. Тут приходится мириться с предупреждениями IDE.

Питон отлично программируется и без IDE, в простом текстовом редакторе. Тут особой разницы с баш-скриптингом нет.

В моей практике баш-скрипты чаще используются для автоматизации сборки и деплоймента продуктов, а питоновские - для разнообразного сбора и анализа данных. Стратегически это себя оправдывает :)

Никаких проблем с правкой Питона в mcedit нет, разве что надо четко соблюдать отступы. А Питон2 помер уж лет десять назад, едва ли стоит его подтаскивать в качестве актуального довода. При этом 3-ка вполне себе совместима снизу вверх

Сравнение Bash и Python при написании скпритов в Linux

Если статья начинается с очепятки в названии, ей можно верить? 🤔😎

cat < some_other_text_file.txt

Это где так работает?

В Debian просто cat some_other_text_file.txt .

$ cat --help
Usage: cat [OPTION]... [FILE]...
Concatenate FILE(s) to standard output.

With no FILE, or when FILE is -, read standard input.
...

Это везде так работает, просто непонятно зачем так делать, если можно просто в параметр подставить.

Там в тексте полно странных решений. Например, код

mapfile -t lines < <(grep -P -v '(^\s*$|^\s*#)' /etc/hosts)

# Выводим список с нумерацией:
for ((i = 0; i < "${#lines[@]}"; i += 1)); do
    echo "$((i + 1)). ${lines[$i]}"
done

Можно заменить на

grep -P -v '(^\s*$|^\s*#)' /etc/hosts | cat -b


Каждое новое поколение программистов придумывает свой язык.
Потому что не разобралось со старым

Это же надо man cat читать! (вот я, кстати, как-то пропустил про -b, а ведь иногда пригодится)

Это потому что -b в POSIX и не было (man cat.1p)

На самом деле cat не выдаст абсолютно такой же результат. В моем примере после номеров строк точки стоят. Придётся ещё команду sed использовать, чтобы один в один сделать. .

Но пример именно такой, поскольку необходимо было дать пример циклов со счётчиком. А сторонние команды я использовал по-минимуму, поскольку к bash они непосредственно не относятся, а статья именно по bash. Ну и на этом моменте статьи нужно было стараться использовать уже рассмотренные в статье возможности. То есть от простого к сложному с как можно меньшим забегает наперёд. Классический подход в подаче обучающих материалов.

Не придётся. Придётся заменить cat на awk: awk '{print NR". "$0}'

Отладка bash через вывод в файл или консоль несколько устарела.

VSCODE имеет плагин bashdb предоставляющий полноценный отладчик с просмотром переменных, точками останова и пошаговым исполнением.

Он не без некоторых особенностей, но все ещё несопоставимо лучше чем просто консоль.

Круто, не знал! Спасибо)

Но обычно аргумент за bash "я в любом текстовом редакторе напишу и отлажу, да и вообще прямо в консоли". Если уж взялись за IDE - можно и Python затащить)

Кайфую со статей про баш. В принципе многое знал, но некоторые особенности баша имеют неприятное свойство в самый нужный момент вылетать из головы. Спасибо большое за статью.

Раньше был отличный сайт с "однострочниками", рейтингами и т. д. Но весь вышел...
Сейчас полно разных "сборок для начинающих" типа https://github.com/onceupon/Bash-Oneliner

Большие Bash-портянки не ломаются потому что в них просто боятся лезть все, даже их авторы.

Небольшой юзкейс по итогам переписывания админскриптов Sh -> Py: время кодинга 4:1, объем кода в КБ 1:2, время выполнения 1:1. Личный вывод: надо неспешно переписать на Python всё что больше 3-х строк в Bash-е. И главная причина не время кодинга, а то что Bash c awk/grep быстро "упрутся", в то время как Python c его строками, срезами и словарями и pandas в одну дополнительную строку преодолеет пропасть между цветным текстом в консоли до web-микросервиса уровня офиса,

>> Большие Bash-портянки не ломаются потому что в них просто боятся лезть все, даже их авторы.

Этот надёжный автомобиль не ломается потому что я боюсь его чинить.

На самом деле просто нет никаких критических изменений в этих sh, в отличие от python. Если python прибить гвоздями на десятилетия то может и будет сегодня смысл в переписывании скриптов. Даже c perl теперь фиг знает чего ждать ибо мутировал в raku, но всё ещё жив.

И главная причина не время кодинга, а то что Bash c awk/grep быстро "упрутся", в то время как Python c его строками, срезами и словарями и pandas в одну дополнительную строку преодолеет пропасть между цветным текстом в консоли до web-микросервиса уровня офиса

А можно пример задачи, на которой эти два тула быстро упрутся? Без сарказма, мне как инженеру интересно.

Ну, и, если вам нужен был веб-микросервис уровня офиса, почему вы с шелл-скриптов начали? Изначально такой задачи не стояло, поэтому был выбран неподходящий инструмент, а потом решили развивать?

Изначально такой задачи не стояло, поэтому был выбран неподходящий инструмент, а потом решили развивать?

Ну в смысле, обычная история же. Вы сначала делаете сервис для себя для грепа логов, потом дописываете его до удобной программки, потом им начинают пользоваться соседние отделы, все начинают путаться в версиях и вы решаете сделать веб-сервис, в окошко которого вставляете логи и получаете результат. Скрипт на питоне переделывается примерно за полчаса, и еще полчаса на настройку деплоя.

Скрипт на баше... Скрипт на баше не переделывается никак, его проще переписать на питоне, чем делать из него веб-сервис.

Веб-сервис с грепом (тут нужна иконка фейспалма)

Это инструмент для быстрого поиска вхождения строки в 1 огромном или кучке разных файлов. Ни то, ни другое в веб-сервис засовывать в принципе не надо, а если всему отделу приспичило этим заниматься, но в шелл сами они не умеют - значит, что-то не так с организацией работы.

Какой вы крутой, разбили в пух и прах пример, придуманный для иллюстрации!

ну так придумайте более реальный, делов-то?

это я еще про CGI не вспоминаю, когда те же bash-скрипты можно запускать как веб-сервисы, со своими особенностями, конечно, но можно.

ну так придумайте более реальный, делов-то?

Чтобы что? Чтобы вам еще раз потренироваться в нахождении слабых сторон в чужих примерах? Карта не территория, в компаниях разные ландшафты, требования и инструменты. Некоторые ситуации весьма всратые, но "так вышло". И с этим тоже приходится работать.

Если писать эти инструменты на баше, их гораздо сложнее интегрировать в современные пайплайны работы. Ну запустите вы баш-скрипт как CGI, угу. Так к нему интерфейс нужен. То, что на питоне с помощью nicegui делается за пять минут (и работает консистентно с кодом, потому что это и есть код), для баша требует отдельной статики на html или такого же интерфейса на питоне рядом.

Я даже этот коммент в закладки добавлю, чтобы проверить потом. Вангую, примеров, когда grep\awk "упрутся" не будет, что бы это ни означало вообще.

За меня коллеги ответили очень точно и емко. Начало обычно такое: свежий сервер без GUI, консоль only, что-то пошло не так. И понеслось...

Архитектурно правильно мыслят только хорошие дорогие спецы, но сами они ничего не кодят, да и нет их. DS/DI/AI-спец постепенно разматывает клубок автоматизации, и если начал с начала нити - быстро пройдет CLI-утилиты и влезет в Pandas/Streamlit итд. Тот же Streamlit это fullstack, изучить который можно за 3 дня. На bash столько же понадобится чтобы уверенно экранировать и циклы писать.

Python, в свою очередь, является полноценным интерпретируемым языком программирования

Так и bash является полноценным, тьюринг-полным языком программирования.

Вещественные же числа в Bash не поддерживаются.

Фраза вводит в заблуждение. Они хоть и "типа не поддерживаются", но их легко получить сразу несколькими способами, например, через AWK, использование которого является вообще распространённой практикой.

Тем не менее, вещественные числа поддерживаются в Ksh.

И в zsh

Цикл со счётчиком в Bash выглядит непривычно, используется форма для арифметических вычислений ((инициализация; условия; действия после итерации)).

Непривычно? C-style цикл for выглядит непривычно?) Серьезно?)

В Python же ассоциативные массивы называются словарями

Это, безусловно, плюс.

В действительности же, в bash есть и массивы и ассоциативные массивы, и работа с ними достаточно легка и продвинута, до определённого уровня. Разумеется, питон тут на другом уровне совсем.

В целом же статья оставляет впечатление питон-ангажированной. Нехорошо.

Применяются классические софистические приёмы, известные нам со славных времён холиваров Шиндошс vs. линукс.

"то, как сделано в винде\питоне\нужное подчеркнуть -- это правильно, и так надо делать. Если в другом месте сделано не так, то это косяк. А если что-то в винде\питоне не так, ну это такая особенность, понимать надо"

Например

но отсутствует какой‑либо ассоциативный массив всех переменных окружения. Получить информацию о них можно лишь через внешнюю команду env

Запоминайте, printenv ИМЯ_ПЕРЕМЕННОЙ -- это плохо, потому, что в питоне не так.

И так далее, даже разбирать это не хочу дальше.

Непривычно? C-style цикл for выглядит непривычно?) Серьезно?)

Попавил, спасибо за замечание. Разумеется, непривычно он выглядит по сравнению с остальным кодом на bash.

cmd_path="`which ls`" # косые кавычки выполняют команду и возвращают её выводecho "${cmd_path}" # вывести путь к команде

Не нужно использовать устаревшую подстановку команд с грависом ``, нужно использовать конструкцию $(). Она более читаема и поддерживает вложение.

cmd_path=$(which ls)
bin_path=$(dirname $(which ls))

А это уже башизм. Устаревший вариант работает и sh, и в старых и в новых скриптах.

Насчёт читаемости - это вообще вкусовщина: кому-то стандартный С-стиль { .... }; это читаемо и удобно, а кому-то "; бесит!“ и больше нравится стиль древнего PL/1 с отступами

Ну тут в заголовке статьи bash написан.

Какая ирония, ведь один из доводов против Питона - это наличие несовместимой 2й версии (которая по факту замшелая донельзя и едва ли встретится в современном мире).

Это не "башизм". Подстановка $(...) является частью POSIX и поддерживается всеми shell оболочками, включая самый урезанный BusyBox ash.

Хм, возможно. Сейчас под рукой нет совсем древней машины, чтобы проверить, но КОГДА-ТО рекомендованное использование было вот такое, с обратными кавычками. Даже книжка была учебная на эту тему, от Sun )

Смотря как давно это было, но в 1994 подстановка $(...) уже была частью POSIX. Так что найти в работающем состоянии хоть что-то Unix-подобное её не поддерживающее будет весьма затруднительно.

И, тем не менее, я, например, тоже за апострофы, хотя примеров, почему может быть предпочтителен $() могу привести даже больше, чем вы.

Почему? А мне нравится старый стиль. И для меня ни одна из причин почему $() лучше – не актуальна.

В реальности, когда учу джунов, поступаю наилучшим образом – честно рассказываю оба подхода, все плюсы и минусы. И мне норм, когда вижу, что новички потом используют $().

И какие же плюсы у апострофов и минусы у $(...) вы рассказываете джунам?

Не нужно использовать which, нужно использовать command -v ;) Deprecated debianism.

Квест предлагаю. Кто сможет заключить переменную в кавычки в следующем примере?

cd ~/'Рабочий стол'
ls "$(ls ${PWD})" # нужно починить команду

Поправка, забыл параметр -d указать, чтоб именно информацию о каталоге выводила ls:

cd ~/'Рабочий стол'
ls "$(ls -d ${PWD})" # нужно починить команду

Там, в первую очередь, надо чинить не кавычки.
Там ls вообще не нужен, а нужен find

Когда я писал "тавтологию" из двух ls, я думал, что будет понятно, что суть квеста в исправлении кавычек, а не команды. Иначе б квестом это не называл и придумал бы пример из реальной жизни. :)

Первая же проблема, с который вы столкнетесь, заключается отнюдь не в кавычках, а в колоризованном выводе.
Потому что ls — это команда для человекопонятного вывода. Для скриптов придумали find.
Но вам, конечно, никто не помешает самостоятельно удалять гланды через анус — только не надо этот специфический вид копрофагии называть "квестом" и предлагать в приличном обществе.

Опция -d выводит информацию только о самом каталоге. Без других опций там колонка будет только одна - то же самое имя, которое подавалось в качестве аргумента.

Вы вообще не понимаете, о чем вам говорят, но лезете спорить:
ls: cannot access ''$'\033''[0m'$'\033''[01;34m/home/user'$'\033''[0m': No such file or directory

Окей, колоризованный вывод команда по умолчанию не делает, за это отдельная опция, которую надо включать, поэтому в таких ситуациях сразу надо проверять, не выставлен ли случаем алиас и что вообще запускается через:

type ls
which ls

Покажите вывод этих команд, пожалуйста.

Но еще покажите, пожалуйста, вывод решения квеста, скажу его, раз уж решать его все равно, судя по всему, никто не намерен:

set -e
cd ~/'Рабочий стол'
/bin/ls "`/bin/ls -d \"${PWD}\"`"

Я с телефона набирал это сообщение, команды не проверял, но вроде правильно написал.

И мы опять ходим по кругу.
Что в этом сообщении вам непонятно? Уделите особенное внимание второму и третьему абзацам.

А какой результат будет получен, при правильном выполнении этой команды?

Список файлов в каталоге Рабочий стол, если вложенная команда была с опцией -d. Если в каталоге ничего нет, просто ничего не покажет. Суть задачи именно в правильной расстановке кавычек, сама команда особого смысла не имеет. То есть не должно выдаваться сообщение об ошибке (предполагается, что каталог существует).

Предположим что вот это и есть "Рабочий стол". Что будет показано?

~$ find ./test\ 01/
./test 01/
./test 01/01
./test 01/01/01.txt
./test 01/02
./test 01/02/02.txt

Выполните команду ls и увидите. К чему такой странный вопрос?

Вопрос в том, что чтобы что-то починить, надо знать как оно должно работать правильно.

Если задача просто в том, чтобы не было сообщений об ошибках, то надо просто закомментировать или удалить строчку.

Уже неактуально, я прямо в статью добавил информацию о разнице между `` и $(). Эта ветка обсуждений явно пошла вообще не в то русло, поэтому эта тема стоит разбора прямо в статье.

В таком случае, её нужно снова убирать, потому, что разницы нет

$ ls "$(ls -d "${PWD}")"

1

$ ls "`ls -d "${PWD}"`"

1

Разница должна была быть, если бы кавычки попытались добавить с экранированием. А те, кто пришли из Сишки, Питона и подобных языков, наверняка бы это попытались сделать. То есть теоретически таких может быть большинство читающих людей статью. И тут возникла бы интуитивно непонятная ошибка, которая легко решается через использование косых кавычек, которые, в свою очередь, делают код плохо читаемым (еле заметны).

Кстати, спасибо за ответ! Мне никогда даже в голову не приходило косые кавычки без экранирования попробовать. Что-то новое узнал. :)

$ touch 1

$ ls -d "${PWD}"

'/home/blackfire/Рабочий стол'

$ ls "`ls -d "${PWD}"`"

1

Не нужно ломать - не придется чинить ;)
Какой сермяжный смысл в этом заклинании?

Главная и практически неразрешимая проблема bash - долбанное экранирование. То, как оно работает со строками - это просто какой-то 3.14здец. Как ни старайся экранировать, какие методы ни применяй, а при обработке большого количества файлов всё одно найдётся такое сочетание символов в имени и пути, которое сломает весь скрипт.

В итоге при использовании Bash я никогда не могу быть уверен, что вот на всём объёме в 100 тыс. файлов оно отработало как надо, что нигде ничего не потеряно.

printf %q (bash) плюс array (bash)? Но это всё равно каждый раз боль.

Не хватает нам духу признать что Python - возможно самый легкочитаемый язык, а Bash - наоборот, один из самых трудночитаемых. Но код на них очень часто делает одно и то же и примерно с такой же скоростью/RAM/CPU/io.

Девальвировать оверскилл башистов так же плохо как и потакать смузихлебам-питонистам. Современники обречены знать обе технологии, но Bash/BAT/PS безусловно, встречаются реже и мельче. И вытесняет его не Perl/Rust, а именно Python.

А ещё можно писать на Python, но с Shell-синтаксисом, чтобы совместить преимущества обоих вариантов: https://plumbum.readthedocs.io/en/latest/

>>> chain = ls["-a"] | grep["-v", "\\.py"] | wc["-l"]
>>> print(chain)
/bin/ls -a | /bin/grep -v '\.py' | /usr/bin/wc -l
>>> chain()
'13\n'
>>> ((cat < "setup.py") | head["-n", 4])()
'#!/usr/bin/env python3\nimport os\n\ntry:\n'
>>> (ls["-a"] > "file.list")()
''
>>> (cat["file.list"] | wc["-l"])()
'17\n'

Я пользовался, мне понравилось.

Почти баш, но только скобочки надо ставить.
Еще там можно в бэкграунде запускать и есть код для цветовой раскраски.

Скорее, как обычно бывает в таких случаях, совмещаются только недостатки. Несмотря на все синтаксичнские ухищрения, в код приходится добавлять кучу лишних символов. А по существу, оно не поддерживает элементарное разделение stderr и stdout . Обработка ошибок тоже сделана своеобразно.

Несмотря на все синтаксичнские ухищрения, в код приходится добавлять кучу лишних символов.

Это да, но на чистом питоне будет еще больше.

А по существу, оно не поддерживает элементарное разделение stderr и stdout

Поддерживает.

У них довольно своеобразная поддержка:

Unlike common posix shells, plumbum only captures stderr of the last command in a pipeline. If any of the other commands writes a large amount of text to the stderr, the whole pipeline will stall (large amount equals to >64k on posix systems). This can happen with bioinformatics tools that write progress information to stderr. To avoid this issue, you can discard stderr of the first commands or redirect it to a file.

Несмотря на то, что синтаксически они пытаются копировать sh, но работает это иначе и результат получается не таким как ожидаешь. В поддержке это кошмар.

Интересно я использовал это для биоинформатических тулзов и оно работало.

Хотя насколько я помню, там особо цепочек не было или в файл редиректил.

Это проблема не только библиотеки но и всего Питона. Можно создавать свои промежуточные буферы для данных и нужно следить, чтобы они не переполнились.

А по существу, оно не поддерживает элементарное разделение stderr и stdout

Поддерживает:

from plumbum import local

ls = local["ls"]

retcode, stdout, stderr = ls.run(["-l", "/tmp", "/nonexistent"], retcode=None)

print("Exit Code:", retcode)
print("stdout:\n", stdout)
print("stderr:\n", stderr)

Если надо чтоб работало везде, то bash
Если есть внешние команды, то скорее всего bash
Если среда контролируемая и удобнее работать с объектами, то python

Еще бы сравнение с powershell. Он выглядит где-то посередине между bash и python

Он реально посередине.
С одной стороны, у него отсутствуют развитые встроенные средства, как в пайтоне, с другой он не так прост в написании и отладке, как шелл-код.
Есть места, где он незаменим, но все они — управление виндой. И ничего не мешает дернуть апплеты или целый ps-скрипт из того же баша

Если надо чтоб работало везде, то bash

Как правило если "везде" это linux и windows, то уже не факт что баш.

Если есть внешние команды, то скорее всего bash

Даже не совсем "скриптовые" языки как Scala или Groovy (у обоих правда есть REPL) прекрасно справляются с вызовом внешних команд. Т.е. грубо говоря, выглядеть это будет примерно так:

def out= "ls -la".execute().text

и в итоге out будет содержать stdout команды ls. И при этом вполне имеется гибкость, чтобы переварить вывод произвольного размера через стримы. И не имеется заморочек с искейпами, характерных для баша.

У автора просто ложная дилемма. Не неправильная, а скорее ограниченная. Вот в моем окружении энтерпрайза я всегда знаю, что "везде" (везде где мне нужно) стоит Java. И поэтому могу скриптовать на груви или скале, не заморачиваясь, потому что ни то ни другое не нужно устанавливать и настраивать окружение, в отличие от питона, и если мне нужны зависимости - то с ними все гораздо проще. Ну т.е. да, моя среда - контролируемая. И работать с объектами удобнее - и кроме питона появляется еще довольно широкий выбор.

Но да, если ваше или их "везде" не такое как мое - у вас другой выбор оптимален.

powershell? Ну в общем да, его бы тоже не мешало бы добавить к этому ограниченному сравнению.

Как правило если "везде" это linux и windows, то уже не факт что баш.

Экий Вы ретроград. :)

У меня вот отключен WSL, политиками там или как - не вникал, и чо? Cygwin предлагаете?

отключен

Ну тогда bash скрипт может и на Линуксе не работать, потому что на конкретном компе что-то отключено или не стоят какие-то утилиты.

Техническая возможность есть, но пользователь от неё отказался.

Ну или иными словами - если вы хотели сказать, что баш почти всегда есть и в windows, то я согласен - почти всегда он есть (у меня вот он из дистрибутива Git). Но гарантии работоспособности типичного баш скрипта нет никаких. Надо специально писать так, чтобы оно работало и в этой среде тоже.

Надо специально писать так, чтобы оно работало и в этой среде тоже.

Например что? (только давайте не будем постить тот хитрый вариант эрэм минус эрэф :) )

Например (сорян что специфичный, но совершенно реальный для меня) керберос. В винде у вас не будет krb5.conf, а будет krb5.ini. И синтаксис команд рабочей станции разный. И лежать оный krb5.ini будет не там (и не факт что переменная окружения будет на него указывать). Ну т.е. я бы сказал, что как только мы выйдем за пределы просто файлов - мы сразу столкнемся со спецификой винды или линукса. Между тем, автоматизация логина в домен - это одна из типовых задач в моем случае. И таки я ее пишу на груви :)

Ну, да, есть такая проблема.

Я как-то обнаружил, что в библиотеке работы с DJVU есть баг. Начал искать и оказалось, что баг старый и даже пофиксеный, но просто не во всех версиях под разные линуксы он пофиксен.

Как только вы привлекаете хоть сколь либо сложный софт, не входящий в более менее дефолтный набор /usr/bin , так у вас сразу начнутся различия версий, вплоть до того, что на одной машине у вас свежая версия софта, а на другой нет - потому что там старая версия оси, которую обновлять не стоит, потому что из свежей версии оси что-то вынесли, что нужно для работы какого-то другого сложного софта.

Ну и, само собой, дефолтный набор /usr/bin это миф, ибо, например, тот же Докер создаёт контейнер в котором есть не всё из того, что считается как "да точно везде есть".

Ну и кстати - юникс это же не только линукс, но и скажем macos. А там и там разные пакетные менеджеры. И грубо говоря, написать скрипт для автоматизации установки чего-либо всегда придется так, чтобы проверять ОС. Я просто хорошо вижу на примерах софта от Apache Group, где скажем весь Java софт, который казалось бы, должен быть переносим, так вот он переносим - но все скрипты запуска, написанные на баше (да, потому что он "везде есть"), во-первых, проверяют тип ОС, и отличают скажем солярис от macos и от линукса, и всех их от цигвина. А еще оный баш дополняется .cmd для виндоус. И я таки склонен опыту этих людей доверять, потому что тиражи их софта намного больше, чем допустим моего.

И я таки склонен опыту этих людей доверять

Это специфический опыт для проекта у которого много пользователей и он поддерживает много платформ.

И это критическая часть системы. Я думаю человеческих ресурсов там потрачено не мало. Докладывать рядом cmd файл, будет перебором для 99% случаев.

Ну вот и получается, что везде есть какие-то особенности, и либо универсальности/совместимости нет вообще, либо она везде либо она везде не 100%, и WSL тут просто один из пунктов списка.

Я согласен с вами, но мне кажется дилемма между bash vs python обусловлена тем, что там где есть bash, обычно так же есть python (т.е. линукс). Windows же из коробки не обладает ни тем ни другим, да и даже тот же powershell core придется устанавливать, или проверять совместимость с изкоробочным powershell 6 или какой он там даже на Windows. При чем Python легко установить "везде", а bash на винде это имо какой-то мазохизм. Поэтому в этом смысле выбор понятно-очевидный в пользу питона.

И да, когда сложность растет, то мой выбор C#, потому что в моей контролируемой среде он есть везде. А питоновые скрипты задолбали, их точно так же сложно править как баш, обширная стандартная библиотека совсем не идеальная, как и везде. Поэтому два раза согласен с вами! :))

Ну в общем, да, "где есть bash, обычно так же есть python (т.е. линукс)", особенно с учетом того, что у автора в заголовке уточнение, что речь про линукс.

Но есть нюанс. Скажем, у меня коллеги пишут на питоне всякое, ML либо ETL, и у них по сравнению со мной (а я пишу на java или scala) проблема простая - нужно установить зависимости. Мне это не требуется. Ну т.е. есть - голый питон и голый баш. Все что нужно для работы скрипта - далеко не всегда. И даже далеко не всегда это в типичном случае оформляется как зависимость - потому что баш не обязывает. Поэтому выбор в сложном случае - более "промышленный" язык, где можно сформулировать, что нам нужно, скачать это условным nuget-ом в вашем случае, или maven в моем, посмотреть версии зависимостей, посмотреть уязвимости в них, ну и так далее.

Питон тоже можно упаковывать - начиная от зипа с исходниками для полностью нативных программ до компиляции в бинарник через pyinstaller для более суровых вариантов с библиотеками.

Речь именно о библиотеках. Я не в курсе, почему. так, но на практике у нас никто не пакует. Все ставят зависимости статически.

Баш работает везде, но команды которые он используют нет. Это работает на убунте но не на макоси.

rm folder -rf

Если использовать только стандартные флажки (POSIX), то проблем с переносимостью будет меньше.

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

90% статьи сравнивает синтаксис. Зачем? Выводы никак не следуют из предыдущего описания. Сами выводы — спорные.

Моё неформальное правило: если можно обойтись потоковой обработкой строк, скармливая их в стандартные утилиты, то надо писать на баше. Всё что связано с более сложными структурами — питон.

Семантику, то есть не чисто синтаксис, а то, как он используется в совокупности с командами, насколько понятен код. Синтаксис как раз почти не рассматривал. Про синтаксис Python можно почитать тут, например, это наборы правил, что и как писать:

https://docs.python.org/3/reference/grammar.html

По примерам из написанной мной статьи видно, насколько удобен и читабелен язык в тех или иных ситуациях, насколько интуитивно его использование в тех или иных ситуациях.

Для примера, Python без доп. библиотек для запуска процессов и создания между ними конвейеров не очень удобен, в то время как Bash очень интуитивен.

А вот при математических вычислениях уже неудобен Bash, особенно если учитывать, что работа на самом деле ведется со строками, которые переводятся в числа и назад.

Я конечно предвзят. Потому что пишу на питоне и хорошо знаю этот язык.

Питон проще, его проще читать, его проще выучить. На баше можно многие вещи сделать намного короче, это домен специфичный язык.

В том окружении, где я сейчас работаю, питоне есть всегда, так-что это не проблема. Скрипты на вынос писать не надо.

Прологосовал за Питон. Хотя приходится и на баше писать.

Самый мой худший опыт с башем: писать скрипты для Jenkins задач внутри кода на Groovy. То есть в строке с форматированным кодом надо заэскейпить всё для груви и потом заэскейпить всё для баша.

Еще я ни разу не видел, чтобы для баша подключали форматеры и линтеры. Для питона это норма.

Для сложных моментов для питона можно накидать тесты, которые будут дёргать реальные части кода. Для баша скорее всего придётся скопировать кусочек кода и его там проверять.

Я всегда shellcheck использую, не проблема

shellcheck очень много ругается, когда намеренно используется раскрытие без окавычивания…
Совет хороший, но хотелось бы его заставить игнорировать некоторые переменные, иначе возможный полезный вывод тонет в потоке бесполезных сообщений

Мне кажется хорошо было бы подписать фрагменты кода: где на bash и где на python. Было бы немного удобнее. Лично я не сразу понял когда начал читать, что второй фрагмент - это уже на питоне.

Некоторые вещи проще и короче написать на баше, чем на питоне. По дефолту пишу на баше, если небольшие скрипты, не нужно работать с массивами и т.д.

Лет десять назад использовал и перл и питон для сисадминских задач.
Сейчас только кубернетес и баш, остальное уже не нужно

В баше очень удобно запускать сторонний софт и получать вывод, а также оперировать файлами. Хотя Питоновский os.system и shutil.copytree не намного сложнее. А вот чуть более сложные конструкции на баше - по мне, это издевательство над собой и здравым смыслом. Синтаксис ветвлений и case такой, что хочется биться головой об стену. Операции с путями - застрелиться (напр., элементарное получение папки скрипта). Да и вечные шаманства с кавычками тоже поддают жару. Так что если это что-то сложнее линейного списка команд для сборки максимум с самыми простыми условиями - Питон намного дружелюбнее, логичнее, понятнее и проще в отладке.

Кроме того, в стандартной библиотеке чуть ли не пол-Линукса реализовано своими средствами. Не знаю уж, чего там кому не хватает для системных скриптов. Этого в любом случае не будет в баше, так что вообще не довод.

Sign up to leave a comment.

Articles