Комментарии 33
Автор написал свой пост в 16:10. Через полтора часа никакой реакции от сообщества не было. Я решил поддержать автора и написал ему слова благодарности. Тем более нашёл в его публикации что-то полезное для себя.

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

Мне кажется, минусовать без пояснения, в данном случае, — некрасиво, это — обнажать какие-то свои скрытые комплексы.

Вы читали комментарии к прошлым "статьям" (точнее переводам)? Я читал. Включая комментарии.


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


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

Кроме лирики конкретика какая-нибудь будет?

Я, например, не считаю ЭТУ статью плохой. И по комментариям к ЭТОЙ статье я это тоже вижу. Идёт здоровая дискуссия, аналогичная дискуссиям в комментариях к другим статьях на Хабре.

Я не знаю, может у Вас что-то этакое есть, позволяющие Вам безапелляционно навешивать всякие ярлыки («Тут всё плохо!» и далее «Я всех спасу!»). Вы, уж, предъявите тогда это, чтобы всем было понятно, что Вы за фрукт. Какую-нибудь ссылку на свою шикарную статью по данной тематике, например, или, может быть, даже книгу.

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

Как-то неубедительно Вы звучите пока.

Если говорить об этой статье: неправильная работа с массивами, использование . в скриптах. Вполне достаточно.


Плюс, эти проблемы уже освещались в комментариях к этой статье. Например, пользователем khim.

Не согласен, абсолютно. Доводы — никакие совсем.

Во-первых, как-то малова-то т.н. «недочётов» для такой обширной статьи, чтобы называть её плохой.

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

Да, khim указал, как более правильно использовать массивы, учитывающие разные контексты массивов. За это ему также огромное спасибо! Но формально-то автор прав. В этом и есть прелесть любой хорошей статьи на Хабре, что она не оставляет равнодушными тех, кто в комментариях эту статью может улучшить. Частенько, в комментариях к статьям содержится не меньше полезной информации, чем в самих статьях.

Я, например, хотел бы, чтобы эта дискуссия про Bash на Хабре продолжилась. Поэтому, спасибо автору и комментаторам, что они тратят своё личное время на это!

В-третьих, про точку в скриптах. Я не понял, что тут неправильного? Поясните, пожалуйста. Если открыть наугад, идущий в стандартной установки Linux, скрипт в /etc/init.d или /etc/rc.d (или что-то ещё похожее, не знаю, с чем Вы работаете), наверняка Вы там встретите использование точки. Я точку встречаю во многих скриптах.

Кроме того, автор не призывает использовать или не использовать точку в скриптах. Автор поделился вполне конкретной информацией о том, что source имеет псевдоним — точку. Разве это неправильная информация?
Во-вторых, про массивы. В том контексте, в котором упоминается работа с массивами, я, например, не вижу ничего неправильного. Скрипт отработает так, как нужно.

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


В этом и есть прелесть любой хорошей статьи на Хабре, что она не оставляет равнодушными тех, кто в комментариях эту статью может улучшить. Частенько, в комментариях к статьям содержится не меньше полезной информации, чем в самих статьях.

Часть комментаторов уже сдалась, т. к. в этой серии ошибки кочуют из статьи в статью.


В-третьих, про точку в скриптах. Я не понял, что тут неправильного? Поясните, пожалуйста. Если открыть наугад, идущий в стандартной установки Linux, скрипт в /etc/init.d или /etc/rc.d (или что-то ещё похожее, не знаю, с чем Вы работаете), наверняка Вы там встретите использование точки. Я точку встречаю во многих скриптах.

Использование точки, равно как и коротких опций в скриптах — code smell. Это ухудшает поддерживаемость скрипта. Насчёт же init.d/rc.d на моей системе оно выглядит так:


-> % ls /etc/init.d /etc/rc.d
ls: cannot access '/etc/rc.d': No such file or directory
/etc/init.d:
vmware

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


Я понял, что вам понравилась эта серия статей. Не буду мешать вам оставаться при своём мнении. Предлагаю завершить дискуссию.

Автор поделился вполне конкретной информацией о том, что source имеет псевдоним — точку.

Вот только нихр это не верное утверждение. Если сильно притянуть за уши — то это source псевдоним синоним «точки», поскольку точка перекочевала из оригинального борн шела а source — нововведение (причём я не рискну сказать баша или ksh).
Но если посмотреть мануал, а ещё лучше вообще исходники 23:52, то выяснится что это две абсолютно равнозначных встроенных команды (built-in) вызывающих одну и ту же функцию source_builtin

Я точку встречаю во многих скриптах.

А вы вообще знаете почему вы встречаете точку-то? Нет? А эта «статья» почему-то этот весьма важный момент опустила, не смотря на то, что об этих встроенных командах обмолвилась.
В качестве повышения квалификации предлагаю вам эту информацию нарыть и поделиться с другими читателями. Ключевое слово — POSIX. В догонку можете поискать на что ресолвится /bin/sh в современных линуксовых дистрах (для упрощения давайте возьмём debian, ubuntu, centos, opensuse, arch), и что будет если скрипт с шебангом #!/bin/sh этому делу скормить и в чём будет разница между source и точкой.

И о такого рода недочётах, которые рано или поздно начинающих приведут к «выстрели себе в ногу рикошетом в голову», я могу к каждой из этих публикаций писать полотна, но, зачем?! Ниже iig написал про absg. Этот материал я упоминал в комментариях к предыдущим статьям как минимум трижды.
Мой добрый совет — читайте мной ранее упомянутые вещи, а не это.
Спасибо огромное за совет! У меня он тоже есть для Вас.

Учитесь слышать людей.

Ваш опус в контексте статьи — ненужная шелуха, информация, чтобы блеснуть умом перед девочками. К чему Вы его написали-то? (Подумайте над этим вопросом и дайте себе ответ, только правдивый.)

Он доказывает, что точку в скриптах использовать неправильно? Нет. Мимо.

Он как-то показывает, что, если я буду использовать точку вместо source, я получу другой результат? Опять нет. «Молоко».

Автор статьи всего лишь пытался донести, что вместо source с таким же успехом можно использовать точку. Не больше, не меньше. А Вы эту простую мысль-то и не услышали! (И давай обнажать свой «ум».)

А так да, Вы написали много правильных слов. Но, как-то не туда, понимаете. Мимо. Может Вам книгу лучше написать, с таким умищем-то? И девочкам это нравится ещё больше.

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

Хамство вас не красит, успокойтесь

Успокойтесь, пожалуйста! Нам с ghostinushanka суфлёр не нужен. Мы сами разберёмся.

Кроме того нашу с Вами дискуссию мы уже прекратили (кстати, по Вашей же инициативе).

Не тратьте, пожалуйста, своё личное время на меня. Я своё точно уже на Вас тратить не собираюсь. Если хотите как-то отреагировать, то просто продолжайте меня минусовать, это точно не отнимет у Вас много Вашего личного времени.

Услышьте меня, пожалуйста, наконец!
Иными словами вы не стали ничего узнавать про POSIX.
В контекте вот этой вашей фразы, это, к великому моему сожалению, весьма печально:
Он как-то показывает, что, если я буду использовать точку вместо source, я получу другой результат?

Да получите, причём в самый неожиданный момент. Или вы серьёзно считаете, что я со злым умыслом и от нечего делать вас направил что-то поискать почитать?

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

#irony #rhetorical
А где мне спасибо на прямые ссылки на «Advanced bash scripting guide», которые я приводил комментариями к предыдущим статьям?

P.S. Прошу прощения у хабрапублики. Я надеюсь что эти комментарии всё же помогут начинающим и не очень писателям шелл скриптов.
Подписываюсь под этим абсолютно верным комментарием к следующей «статье из цикла».
Очень жаль, что Вы даже и не попробовали научиться слышать людей!
Да получите, причём в самый неожиданный момент.

Вы уж расскажите, пожалуйста, не томите.

Вы обиделись, а зря! Вы что, серьёзно считаете, что я со злым умыслом и от нечего делать Вас попытался направить научиться хоть немного слышать людей? Отнюдь.

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

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

Вот, Вы всё зачем-то вставляете в своих комментариях «POSIX, POSIX...». Поймите Вы, наконец, что очки — это ещё не признак ума. А, вот, умение слышать собеседника, по крайней мере, даёт надежду на его наличие.

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

К великой моей Радости, я бы очень хотел, чтобы Вы научились слышать людей. Но я не могу Вас заставить! Вы должны сами этого захотеть. Иначе — не получится. Я лишь могу только выдавать Вам информацию для размышления.

Например.
Иными словами вы не стали ничего узнавать про POSIX.

Разве Вы слышали от меня, что я ничего не знаю про POSIX? Как я могу, например, писать многопоточные сервера и не знать про POSIX? Я POSIX уже хорошо знал ещё в 90-х. Но я не вижу в этом ничего экстраординарного — знать POSIX. С таким же успехом Вы могли бы мне в также назидательном тоне посоветовать изучать, например, Linux. Моё восприятие Ваших слов совершенно бы не изменилось. Ваш совет меня искренне улыбнул. :)

Я хорошо понимаю, почему Вы по-доброму советуете мне, и с великим сожалением расстраиваетесь, что по-вашему я это не делаю, изучать именно POSIX, а, например, не Linux (в контексте Ваших неуместных обращениях ко мне я разницы не вижу). Просто для Вас он ещё свеж, а Linux скорее всего уже нет или лучше так — не так свеж. Поразмышляйте над этим.

Ещё, например.

Я совершенно не сомневался, что Вы обязательно напишите мне что-то типа этого:
А где мне спасибо на прямые ссылки на «Advanced bash scripting guide», которые я приводил комментариями к предыдущим статьям?


Вы умудрились обидеться (хотя и прикрылись якобы иронией) на комментарий, который предназначался не для Вас. Я, конечно, оброщался к iig, но для Вас этот комментарий тоже предназначался, но, только в качестве эксперимента. Мне же надо было как-то получить от Вас косвенные подтверждения, Вашей обидчивости. Спасибо, тест сдан, Вы это подтвердили! Поразмышляйте над этим тоже.

Продолжим.

P.S. Прошу прощения у хабрапублики. Я надеюсь что эти комментарии всё же помогут начинающим и не очень писателям шелл скриптов.
Подписываюсь под этим абсолютно верным комментарием к следующей «статье из цикла».


Ответьте честно для себя, как наша дискуссия поможет кому-то писать хорошие шелл скрипты? Вы же ничего конкретного по теме не написали вообще, в отличие от, например, khim. Откровенные самолюбование, желание «примазаться к славе», и, конечно, неуверенность в себе. Поразмышляйте и над этим.

Тут на Хабре есть реальные ребята, делящиеся своими знаниями в статьях и комментариях и делающих Хабр тем, что он есть, а есть закомплексованные критики, как правило, без публикаций и без конкретики в комментариях — одна лишь пустая неподкреплённая ничем критика (именно они активно минусуют любого, потому что никого не слышат) и лирика (активно стремяться всем «помочь», при этом ничем не помогая, и «спасти» — не спасая).

Хотите перейти на сторону реальных ребят? — научитесь для начала слышать людей.

Лимит моего личного времени на дискуссию с Вами, к сожалению, закончился. Но Вы, если у Вас есть что ответить, обязательно ответьте, а я обязательно прочту. Я не обидчивый. Мне людей изучать тоже интересно.
Канонический Advanced bash scripting guide не намного больше по размеру, я бы его рекомендовал.
Спасибо, добрый человек!

Хотя за слова благодарности тут есть много минусующих, я всё-таки решил поблагодарить за реально полезную информацию. Кто-нибудь, случайно наткнувшись на эту статью, сможет легко двинуться дальше (как и я, например).
Без обид, но если уж на то пошло — соберитесь вместе с умными людьми, и напишите свою серию статей!
И 100% найдётся люди умнее и также будут комментировать…

Вот честно, вы так высказываетесь, как будто тут выложили совершенно не работающий код. Главное — что он работает, а подточить — уже дело каждого.

Я, например, пол года назад совершенно не знал об администрировании серверов, а сейчас приходится содержать 2 сервера, и для меня хоть какие-то примеры — это послание от бога! Но я согласен, что примеры не ахти моментами, но что поделать…

Не беспокойтесь, без ваших мудрых советов от активного автора разберусь чему посвятить своё свободное время. И тут мои и не только мои open source проекты куда в большем приоритете, чем статьи на хабре.

Тут стоит отметить, что для того, чтобы вышеприведённый пример заработал, может понадобиться выйти из системы, а потом войти снова.
Если добавляли в .bashrc, то не надо выходить из системы. Достаточно либо запустить новую копию баша (например, открыть новую вкладку в терминале или прямо в текущей вкладке запустить ещё один дочерний bash), либо в текущей командной строке вызвать ту же команду для подгрузки функций, которую добавляли в файл.

Кроме того, обратите внимание на то, что если имя функции из библиотеки совпадёт с именем какой-нибудь стандартной команды, вместо этой команды будет вызываться функция.
И зачастую это очень удобно. Подменяем grep на функцию, которая запускает «настоящий» grep, динамически выбирая для него разные опции в зависимости от того, запущен ли в терминале (а не, скажем, в pipe-цепочке команд):
function grep {
        if [ -t 1 ] ; then
                /bin/grep --color -n "$@"
        else
                /bin/grep "$@"
        fi
}
source просто вставляет кусок кода из другого файла. Внутри может и не быть никакой библиотеки.
И опять у нас статья, которая учит пользователей писать неправильные скрипты на bash'е. Давайте немного модифицируем пример с передачей массивов:
#!/bin/bash
function myfunc {
local newarray
newarray=("$@")
echo "The new array value is:"
for value in "${newarray[@]}" ; do
  echo "  $value"
done
}
myarray=(1 "2 3" "4 5")
echo "The original array is:"
for value in "${myarray[@]}" ; do
  echo "  $value"
done
myfunc ${myarray[*]}

Запустим, и…

The original array is:
  1
  2 3
  4 5
The new array value is:
  1
  2
  3
  4
  5
Таки у нас проблема.

А как надо? А вот так:
#!/bin/bash
function myfunc {
local newarray
newarray=("$@")
echo "The new array value is:"
for value in "${newarray[@]}" ; do
  echo "  $value"
done
}
myarray=(1 "2 3" "4 5")
echo "The original array is:"
for value in "${myarray[@]}" ; do
  echo "  $value"
done
myfunc "${myarray[@]}"
Теперь — порядок:

The original array is:
  1
  2 3
  4 5
The new array value is:
  1
  2 3
  4 5
Собственно я вообще не могу припомнить ни одного учебника по bash, где не было бы каких-либо ошибок (в bash есть много разных способов «выстрелить себе в ногу).

И вот это вот — «простой» язык? Да ни в жизнь. Иначе бы „гуру“, пишущие учебники, уж наверное, не совершали бы „детских“ ошибок.

При этом — всё ведь есть! Давайте например, распечатаем не весь массив в функции, а подмассив:
#!/bin/bash
function myfunc {
local newarray
newarray=("$@")
echo "The new array value is:"
for value in "${newarray[@]:1:2}" ; do
  echo "  $value"
done
}
myarray=(1 "2 3" "4 5" 6 7)
echo "The original array is:"
for value in "${myarray[@]}" ; do
  echo "  $value"
done
myfunc "${myarray[@]}"
Работает отлично:

The original array is:
  1
  2 3
  4 5
  6
  7
The new array value is:
  2 3
  4 5
А теперь попробуем „отрезать кусочек“ в момент его создания:
#!/bin/bash
function myfunc {
local newarray
newarray=("${@:1:2}")
echo "The new array value is:"
for value in "${newarray[@]}" ; do
  echo "  $value"
done
}
myarray=(1 "2 3" "4 5" 6 7)
echo "The original array is:"
for value in "${myarray[@]}" ; do
  echo "  $value"
done
myfunc "${myarray[@]}"
Всё сьехало:
The original array is:
  1
  2 3
  4 5
  6
  7
The new array value is:
  1
  2 3
Довайте поэкспериментерием:
#!/bin/bash
function myfunc {
local newarray
newarray=("${@:0}")
echo "The new array value is:"
for value in "${newarray[@]}" ; do
  echo "  $value"
done
}
myarray=(1 "2 3" "4 5" 6 7)
echo "The original array is:"
for value in "${myarray[@]}" ; do
  echo "  $value"
done
myfunc "${myarray[@]}"
И:
The original array is:
  1
  2 3
  4 5
  6
  7
The new array value is:
  test.sh
  1
  2 3
  4 5
  6
  7
Ага. Теперь понятно: $0 — ведь это название скрипта (скрипта, а не функции, заметьте!) и когда мы „массив агументов“ обрабатываем — про это нужно помнить… Но „для удобства“ когда мы работает с "$@" нулевой элемент выкидывается автоматически!

Ну что за прелесть этот bash! PHP — это ужас, как всем известно, но bash… bash — это ужас-ужас-ужас-ужас-ужас!

И это вы ещё поверхность не поцарапали...


cd $dir
rm -fr *

Спойлер: представим, что $dir не существует или пустой.


file=/etc/passwd
foo() {
  # local file
  for file in /*; do # file теперь глобально видна всем
    :
  done
}
foo
# ой!
echo $file

copy_file_to_tmp() {
  cp "$1" /tmp # работает ровно до момента появления файла с названием "-f"
}

Тысячи их.


А ещё bash -ue script.sh.


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


P.S.


count=$(( $count + 1 ))
# так тоже работает
((count++))

P.P.S. В systemd поняли ошибку и переписали всё с шелл-портянок на Си. Но в последний момент всё равно что-то пошло не так...

Ну дык. Решение первой проблемы «всем известно»:
#!/bin/bash
set -eu
dir=oops
cd "$dir"
rm -rf ./*
Получаем:
$ bash test.sh 
test.sh: строка 4: cd: oops: Нет такого файла или каталога
Писать скрипты на bash'е без set -eu — нарываться на неприятности.

Для второй проблемы существует директива local.

Для cp — тоже есть решение, даже два:
1. Можно использовать cp -- "$1" /tmp
2. Можно сделать функцию примерно такого вида:
function make_safe {
  if [[ "${1::1}" != "/" && "${1::2}" != "./" ]]; then
    echo -n "./$1"
  else
    echo -n "$1"
  fi
}
После чего имея переменную unsafe_name вы можете «легко» сделать её безопасной:
IFS= read -rd '' safe_name < <(make_safe "$unsafe_name")
В общем если принять «как данность», что написание скриптов на bash'е — это скорее разгадывание ребусов, то всё можно сделать. Но на нормальное программирование это ни разу не похоже.

Если же скрипты пишутся для себя, то часто можно обойтись более простыми средствами. Если имена файлов, с которыми вам приходится работать не заканчиваются на возврат каретки и не начинаются со знака минус, то ведь и просто cp "$1" /tmp сработает!
cd $dir
rm -fr *


Выстрелить в ногу и жаловаться, что теперь больно.

cd "$dir" && rm -fr *


И тут оказывается, что rm -fr * не удаляет скрытые файлы (имена которых начинаются с точки)…
И тут оказывается, что rm -fr * не удаляет скрытые файлы (имена которых начинаются с точки)…
Я так понимаю, что на это и был рассчёт. Хотя фиг его знает. Целиком скрипта мы не видим, так что…

А вообще — set -eu надёжнее, чем
cd "$dir" && rm -fr *
Потому что просто тупо игнорировать тот факт, что перейти куда-то не удалось — нехорошо. Нужно либо вывалиться, либо if cd "$dir" сделать и потом как-то обработать ошибку…
У каждого свой набор шаблонов чтобы подпирать особенности программ на bash ;)
Ошибки желательно обрабатывать, кто ж против.
И опять у нас статья, которая учит пользователей писать неправильные скрипты на bash'е.

После того как все мои замечания к предыдущим «статьям» остались без внимания, я просто забил их комментировать.
Было бы неплохо, еслиб НЛО вывесило баннер над этими статьями в стиле «Бородатые комментаторы советуют к статьям относиться со скепсисом»
Бородатые комментаторы весь баш выкинули уже 3 года как
и увольняют за попытку его использования

Ansible проще поддерживать и развивать
ну-ну, если б они пореже функционал меняли. Обновился, а переменные уже локальные для include и переопределить их можно только через set_fact. Или with_item синтаксис поменяли, или loop_var. Я уже заколебался переписывать. В баше такого нет :)
Это краш-тест начинающих и любопытных башо-писателей, к тому же в рамках статьи :).

Толсто. У кого в современном миру не настроены ulimits и cgroups?

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.
Информация
Дата основания

27 июля 2015 г.

Местоположение

Россия

Сайт

ruvds.com

Численность

11–30 человек

Дата регистрации

18 марта 2016