Комментарии 46
Не знаю, откуда вы взяли совет 1. Я бы написал наоборот:
- Никогда ничего не спрашивайте, если действие, производимое скриптом, не деструктивно по сути и притом работает с резервной копией. Если деструктивно, но не трогает резервную копию тоже не спрашивайте, при исполнении следующих правил риска никакого, а вопросы раздражают.
- Давайте нормальные имена скриптам и всегда добавляйте документацию, если сам скрипт не умещается на экране.
- Для того, чтобы запустить именно нужный скрипт, есть консоль и автодополнение в ней. Никогда не запускайте что‐либо по нажатию в MC.
+44
3.1 chmod a-x ./*
-5
Таким образом вы запретите использование всех подкаталогов.
+10
find. -type f -exec chmod a-x {} \;
+3
Большинство современных chmod умеет -R:
Кстати, хорошая задачка, которую я иногда на собеседованиях админов спрашиваю: как восстановить систему после такого — хороша тем, что потенциальных решений сотни :)
chmod -R a-x .
Кстати, хорошая задачка, которую я иногда на собеседованиях админов спрашиваю: как восстановить систему после такого — хороша тем, что потенциальных решений сотни :)
-1
Ещё бы большинство людей научились проверять свои предположения, прежде чем публиковать их.
$ chmod -R a-x .
chmod: cannot read directory ‘.’: Permission denied
+4
Эм, речь о том, чтобы выполнять это из под рута, разумеется.
-1
Речь о том, что ваш вариант запретит использование большего числа каталогов вместо того, чтобы решить проблему, только и всего.
+1
Мы вообще-то изначально говорили о способе _повредить_ систему, а не решить какую-то проблему (какую, кстати?).
0
Нет. vlivyur привёл решение, которое, по его мнению должно было запретить запуск чего‐либо по нажатию в MC (для текущего каталога) (во всяком случае, я так понял).
Я указал, что данное решение также запретит использование всех подкаталогов, затем Frosty показал, как можно этого избежать.
Ваш комментарий к ответу Frosty был воспринят как попытка указать на лучший способ решения проблемы (никаких явных указаний, что вы хотите этим способом повредить систему в нём нет, а других причин иметь именно такой комментарий именно к тому ответу я не вижу).
Поэтому sledopit указал, что это просто усугубляет проблему.
Вы, очевидно, не поняли, что sledopit хотел этим сказать, так как указанное им поведение наблюдается при запуске от пользователя.
Поэтому я уточнил, о чём там идёт речь.
Теперь вы говорите, что кто‐то говорил о том, как повредить систему, хотя ни в каком из предшествовавших вашему комментариев это не предполагалось.
Вот этот
Я указал, что данное решение также запретит использование всех подкаталогов, затем Frosty показал, как можно этого избежать.
Ваш комментарий к ответу Frosty был воспринят как попытка указать на лучший способ решения проблемы (никаких явных указаний, что вы хотите этим способом повредить систему в нём нет, а других причин иметь именно такой комментарий именно к тому ответу я не вижу).
Поэтому sledopit указал, что это просто усугубляет проблему.
Вы, очевидно, не поняли, что sledopit хотел этим сказать, так как указанное им поведение наблюдается при запуске от пользователя.
Поэтому я уточнил, о чём там идёт речь.
Теперь вы говорите, что кто‐то говорил о том, как повредить систему, хотя ни в каком из предшествовавших вашему комментариев это не предполагалось.
Вот этот
Да, упустил это, но смысл решения понятен.комментарий vlivyur ясно указывает на то, что речь не шла о повреждении системы.
+3
Забавно. Я воспринял первое сообщение от vlivyur не как попытку что-то «исправить» (мне даже в голову такое не пришло) и «запретить запуск чего-либо», а как попытку проиллюстрировать, какие бывают «вредные» команды, запуск которых может испортить систему. Обычно народ в качестве такого пытается показать различные варианты
Frosty, видимо, понял это так же и предложил «исправленный» вариант команды, которая гарантированно портит execution-биты во всех подкаталогах ниже текущего, а я, соответственно, добавил, что куда проще, если уж говорить о случайных командах, которые могут все испортить, попасться на рекурсивном chmod.
Как можно пытаться «решать» проблему того, что человек пользуется mc, работает под рутом и случайно может что-то запустить — я не знаю. Видимо, для начала отбирать у человека права и, возможно, mc.
rm -rf /
, а тут — видимо, человек попытался изобразить chmod, снимающий x со всех-всех файлов.Frosty, видимо, понял это так же и предложил «исправленный» вариант команды, которая гарантированно портит execution-биты во всех подкаталогах ниже текущего, а я, соответственно, добавил, что куда проще, если уж говорить о случайных командах, которые могут все испортить, попасться на рекурсивном chmod.
Как можно пытаться «решать» проблему того, что человек пользуется mc, работает под рутом и случайно может что-то запустить — я не знаю. Видимо, для начала отбирать у человека права и, возможно, mc.
+1
Мне бы тоже не пришло в голову исправлять эту проблему этим способом. Но строки «3.1» в начале сообщения было достаточно, чтобы понять, что это уточнение к моему третьему пункту. В третьем пункте говорилось о том, что не надо использовать MC для запуска скриптов, соответственно напрашивается единственное толкование. Предположение о том, что та команда являлась примером скрипта с деструктивным поведением, противоречит контексту беседы: «3.1» в начале и вообще весь мой комментарий, на который, собственно, отвечали, не предполагают возможности данного толкования.
0
Да, упустил это, но смысл решения понятен.
+1
1. Возможно первое правило действительно нуждается в лучшей формулировке. Да, у меня тоже не все скрипты просят подтверждения. Ключевые слова «выполняют действия» — это именно то, что Вы называете деструктивным поведением.
2. Я пока не нашел универсального способа именования скриптов… Поделитесь.
3. Я пользуюсь mc 12 часов в сутки. И он у меня по Enter не только запускает скрипты, но и открывает почти все файлы. Не говоря обо всех его остальных возможностях. Это такой удобный и естественный инструмент, что мне как-то даже нечего сказать по поводу «автодополнения в консоли».
2. Я пока не нашел универсального способа именования скриптов… Поделитесь.
3. Я пользуюсь mc 12 часов в сутки. И он у меня по Enter не только запускает скрипты, но и открывает почти все файлы. Не говоря обо всех его остальных возможностях. Это такой удобный и естественный инструмент, что мне как-то даже нечего сказать по поводу «автодополнения в консоли».
-4
Лично я именую скрипты по принципу «дополнения» какого-то функционала, это более-менее общепринятая практика, например для алиасов команд:
Функции, подгружаемые оболочкой, обычно делаю «обобщающими», придумывая собственные запоминающиеся названия, например есть такая, давно откуда-то скопированная:
lsa = ls -a
или самописный скрипт обновления dns-записей локальной сети: bindlocalupdate
Функции, подгружаемые оболочкой, обычно делаю «обобщающими», придумывая собственные запоминающиеся названия, например есть такая, давно откуда-то скопированная:
extract
смотреть код
#
# extract archives
#
extract ()
{
if [ -f "$1" ]
then
case "$1" in
*.tar.bz2) tar xvjf "$1" ;;
*.tar.gz) tar xzvf "$1" ;;
*.bz2) bunzip2 -v "$1" ;;
*.deb) ar xv "$1" ;;
*.gz) gunzip -v "$1" ;;
*.rar) unrar xv "$1" ;;
*.rpm) rpm2cpio -v "$1" | cpio --quiet -i --make-directories ;;
*.tar) tar xfv "$1" ;;
*.tbz2) tar xjfv "$1" ;;
*.tgz) tar xzfv "$1" ;;
*.zip) unzip "$1" ;;
*.z) uncompress -v "$1" ;;
*.7z) 7z xv "$1" ;;
*) echo "'$1' cannot be extracted via extract" ;;
esac
else
echo "'$1' is not a valid file"
fi
}
+1
Подумал. Надо дописать, что именование «дополнением» удобно для вывода всех связанных с какой-то утилитой функций при дополнении в консоли (особенно удобно это в zsh, когда список динамически меняется под строкой ввода, а не пролистывается).
0
Что характерно — в современном мире эта функция практически бесполезна, все то же самое делает просто
tar -xf
. Использование «bunzip2» и «gunzip» — вообще сурово, т.к. в отличие от всех других альтернатив, еще и убивает исходный файл, никого не спрашивая.0
Таскаю в .zshrc уже три года, не переписывая. Привёл в качестве примера, т.к. это самая используемая функция у меня.
Привычка таскать из системы в систему свои функции и писать вспомогательные скрипты — это тема отдельного разговора. Многие программисты старшего поколения воспринимают такие привычки, как само-собой разумеющееся, для меня же польза этого открылась сравнительно недавно, а для многих моих сверстников, разбалованных современными DE, остаётся тайной.
Привычка таскать из системы в систему свои функции и писать вспомогательные скрипты — это тема отдельного разговора. Многие программисты старшего поколения воспринимают такие привычки, как само-собой разумеющееся, для меня же польза этого открылась сравнительно недавно, а для многих моих сверстников, разбалованных современными DE, остаётся тайной.
0
Таскать, по идее, надо все настройки целиком — у меня они просто банально скоммичены в некий репозитарий, откуда деплоятся вот скриптом в виде симлинков, т.е. что-то типа:
~/.signature => ~/personal-home/home/.signature
~/.ssh/id_dsa => ~/personal-home/home/.ssh/id_dsa
~/bin/sum_all => ~/personal-home/home/bin/sum_all
и т.д.
~/.signature => ~/personal-home/home/.signature
~/.ssh/id_dsa => ~/personal-home/home/.ssh/id_dsa
~/bin/sum_all => ~/personal-home/home/bin/sum_all
и т.д.
0
С первым правилом не согласен.
В крайнем случае можно так:
а) скрипт без параметров должен ничего не делать, либо делать что-то с теми путями, которые в нём (или в файле конфига) hardcoded (а раз так, значит он настроен пользователем системы на эту систему и ничего плохого не случится)
б) если скрипт делает действительно что-то ужасное, добавить обязательный параметр --force
в) можно добавить --dry-run
И никаких проблем при случайном нажатии на скрипт в mc не будет.
Если Вам нужен скрипт который что-то спрашивает, может Вам стоит в сторону GUI приложений посмотреть?
В крайнем случае можно так:
а) скрипт без параметров должен ничего не делать, либо делать что-то с теми путями, которые в нём (или в файле конфига) hardcoded (а раз так, значит он настроен пользователем системы на эту систему и ничего плохого не случится)
б) если скрипт делает действительно что-то ужасное, добавить обязательный параметр --force
в) можно добавить --dry-run
И никаких проблем при случайном нажатии на скрипт в mc не будет.
Если Вам нужен скрипт который что-то спрашивает, может Вам стоит в сторону GUI приложений посмотреть?
+2
Возможно первое правило действительно нуждается в лучшей формулировке. Да, у меня тоже не все скрипты просят подтверждения. Ключевые слова «выполняют действия» — это именно то, что Вы называете деструктивным поведением.
Зачем нужны скрипты, которые не выполняют действия?
То, что я называю «деструктивным поведением» — это поведение, в результате которого безвозвратно теряются данные. Это неbunzip file.bz2
/bzip2 file
— оно обратимо. Это не загрузка скриншотов на Яндекс.Фотки, отмонтирование, убийство operapluginwrapper, печать файла как книги на принтере или даже удаление сокетов dtach (даже если всех, включая соответствующие рабочим процессам) (dtach — аналог screen, из которого выпилен весь функционал за исключением возможности работы после убийства эмулятора терминала/ssh сессии и возможности переприсоединения).Я пока не нашел универсального способа именования скриптов… Поделитесь.
Именуйте так, как вам будет понятно. Более универсального принципа я не знаю.Я пользуюсь mc 12 часов в сутки. И он у меня по Enter не только запускает скрипты, но и открывает почти все файлы. Не говоря обо всех его остальных возможностях. Это такой удобный и естественный инструмент, что мне как-то даже нечего сказать по поводу «автодополнения в консоли».
Естественным он быть не может, равно как и консоль и вообще все интерфейсы.
Относительно удобства — опишите любой use‐case и я скажу, как это сделать быстрее в консоли с автодополнением. Единственный случай, когда mc является удобным — это когда я не помню, что находится в конкретном каталоге. Так как единственные каталоги, про которые я этого не помню — это то куда скачиваются torrent’ы, а все операции сводятся к изредка используемымaplayer /mnt/files/torrent/Series/Common\ series\ prefix\ <->\ *.mkv
(можно и просто …/*.mkv, но в этом случае при случайном выходе из mplayer сложнее сказать, что хочешь смотреть все серии, начиная со, скажем, 15‐й. А так<->
заменяется на<15->
), то иметь mc ради такого случая мне кажется странным. Кроме того, мне не понятно, как в случае запуска с N‐й серии мне поможет mc.
+1
По поводу первого пункта — поддерживаю. Считаю гораздо правильнее обвешать критичные действия проверками, чем заставлять пользователя каждый раз делать проверки самому. Все мы знаем, чем заканчиваются бесконечные y/n?
0
Я бы сказал, что тут практически все советы — вредные:
- Для того, чтобы писать скрипты на *bash*, по-моему, нужны серьезные основания. От использования /bin/sh вместо bash жизнь часто становится сильно проще.
- Написание велосипедных «пользовательских интерфейсов» с помощью read, а не dialog — ужасно и приводит к совсем диким последствиям, если вместо пользователя внезапно возникает пайп.
- Написание выводимых сообщений безальтернативно на русском языке — однозначное зло и грабли, которые больно бьют, как только человеку внезапно придется воспользоваться какой-нибудь консолью со странной кодировкой или передать скрипт коллеге, не говорящему по-русски.
- Написание собственных getopt — зло. За нарушение всеми принятых и всеми ожидаемых принципов обработки однострочных опций и предложение сокращать "--show-files-only" до "-sfo" нужно убивать :)
- Написание собственных библиотек функций — может, и не столь очевидное зло (хотя вот зачем писать, когда можно взять готовое, явно более оттестированное и документированное, чем напишется на коленке?), но совет класть это в /usr/bin, а не в ~/bin, например — это явно bad practice.
- «Постоянно встречающееся сочетание»
1>&2
, субъективно, во-первых, лучше записывать, как>&2
, во-вторых, раз уж выводить error messages хочется так часто — сделать в библиотеке функций типа функции «log_info», «log_warning», «log_error» — их и раскрашивать можно, и поотключать, и позаворачивать при желании в разные места — и все такое. echo ""
не стоит писать почти никогда — достаточноecho
без параметров.
+15
1) имхо тоже не лучший вариант, я пользуюсь в таком случае правилом:
скрипт всегда должен требовать ключи для свой работы, скрипт запущенный без ключей выдает справку по пользованию скриптом
скрипт всегда должен требовать ключи для свой работы, скрипт запущенный без ключей выдает справку по пользованию скриптом
0
Названия функций вроде «myAskYNE» никуда не годятся. По такому названию не определишь, что функция делает.
+4
Читал и ждал совета всегда использовать «set -e». Этим часто пренебрегают, но это действительно спасает от глупых ошибок.
что-то вроде
Если some_function выдаст ошибку, PATH будет пустой строкой и будет вызван rm -rf /path/to/ и удалит всю папку
Если же использовать set -e, то скрипт прекратит работу сразу после первой строки
что-то вроде
PATH="$(error_function)"
rm -rf /path/to/$PATH
Если some_function выдаст ошибку, PATH будет пустой строкой и будет вызван rm -rf /path/to/ и удалит всю папку
Если же использовать set -e, то скрипт прекратит работу сразу после первой строки
+4
set -e
это очень хорошо, но неиспользование стандартных переменных должно быть условным рефлексом. В данном конкретном примере ничего не будет удалено, поскольку оболочка не будет знать, где искать rm
.0
Использовать -e лучше всего с -x — а то иногда не понятно что и где отвалилось.
А еще внимательно читать документацию на программы которые использутся, например банальный grep в конце пайпа(ов) (например: "
Или использование expr, казалось бы, что плохого в
В общем с "-e" нужно очень внимательно подходить к тому чего хочется достичь. Иногда лучше регулярно проверять код выхода чтобы выводить человеческие сообщения об ошибках, чем просто завершать скрипт по любому поводу.
А еще внимательно читать документацию на программы которые использутся, например банальный grep в конце пайпа(ов) (например: "
cat file | head -n 2 | grep smthn
") если ничего не нашел — вернет 1, и скрипт завершится. Или использование expr, казалось бы, что плохого в
res=$(expr 1 - 1)
, но expr
вернет 1 если результат операции будет 0.В общем с "-e" нужно очень внимательно подходить к тому чего хочется достичь. Иногда лучше регулярно проверять код выхода чтобы выводить человеческие сообщения об ошибках, чем просто завершать скрипт по любому поводу.
+2
Насчет правила написания «скриптов». Я бы сказал так, что «правила написания скриптов» НЕ должны особенно отличаться от «правил написания программ»:
1) Ваш скрипт/программа принимает какие-то параметры? Предусмотрите штатный способ получения информации о том, какие это параметры и что они означают, без необходимости лазить в исходник скрипта/программы. Т.е. например выдавать «usage()» по -р/--help. Вы же не лезете каждый раз в исходник tar если не помните навскидку каким ключом можно задать список «exclude files»?
2) Ваш скрипт/программма может произвести «деструктивное» действие? Обьект над которым проводиться это действие — должен задаваться исключительно в качестве параметра, и ни в коем случае, не «по умолчанию». Обратите внимание на то, как это работает: Например «недеструктивная» комманда ls имеет «обьект по умолчанию» — текущую директорию. А представьте какой «адский песец» был бы, если бы программа mkfs «по умолчанию» использовала бы, например /dev/sda1. Или rm безпараметров бы вычищал текущую директорию?
3) Для скрипта/программы exit-код обязателен! Можно даже без «детализации причин». Обязательное правило: Минимальная возвращаемая информация — это 0/1, сигнализирующая о том, что «да, запрашиваемое действие успешно выполнено» или «нет, запрашиваниемое действие не выполнено». Это даст возможность использовать ваш скрипт/программу из других скриптов/программ.
4) Для скриптов/программ имеющих возможность работать в пакетном режиме, должна быть возможность работы в полностью пакетном режиме. Т.е. НЕ надо настаивать на лишней интерактивности там, где она не является необходимой. Это к вопросу, по поводу «Вы уверенны [y/n]?». Самый лучший пример: программа rm, у которой есть ключ "-i" заставляющий спрашивать подтверждения длействия, а также ключ "-f" заставляющий ее продолжить пакетную работу даже если возникли проблемы с удалением конкретного файла. Если бы интерактивность rm была бы всегда, ее бы просто выкинули на помойку сразу после первой же необходимости прочистить директорию с несколькими тысячами файлов.
1) Ваш скрипт/программа принимает какие-то параметры? Предусмотрите штатный способ получения информации о том, какие это параметры и что они означают, без необходимости лазить в исходник скрипта/программы. Т.е. например выдавать «usage()» по -р/--help. Вы же не лезете каждый раз в исходник tar если не помните навскидку каким ключом можно задать список «exclude files»?
2) Ваш скрипт/программма может произвести «деструктивное» действие? Обьект над которым проводиться это действие — должен задаваться исключительно в качестве параметра, и ни в коем случае, не «по умолчанию». Обратите внимание на то, как это работает: Например «недеструктивная» комманда ls имеет «обьект по умолчанию» — текущую директорию. А представьте какой «адский песец» был бы, если бы программа mkfs «по умолчанию» использовала бы, например /dev/sda1. Или rm безпараметров бы вычищал текущую директорию?
3) Для скрипта/программы exit-код обязателен! Можно даже без «детализации причин». Обязательное правило: Минимальная возвращаемая информация — это 0/1, сигнализирующая о том, что «да, запрашиваемое действие успешно выполнено» или «нет, запрашиваниемое действие не выполнено». Это даст возможность использовать ваш скрипт/программу из других скриптов/программ.
4) Для скриптов/программ имеющих возможность работать в пакетном режиме, должна быть возможность работы в полностью пакетном режиме. Т.е. НЕ надо настаивать на лишней интерактивности там, где она не является необходимой. Это к вопросу, по поводу «Вы уверенны [y/n]?». Самый лучший пример: программа rm, у которой есть ключ "-i" заставляющий спрашивать подтверждения длействия, а также ключ "-f" заставляющий ее продолжить пакетную работу даже если возникли проблемы с удалением конкретного файла. Если бы интерактивность rm была бы всегда, ее бы просто выкинули на помойку сразу после первой же необходимости прочистить директорию с несколькими тысячами файлов.
+6
Нет, я понимаю, что тут не принято критиковать подобные посты, но всё же.
1. Unix никогда не скажет «пожалуйста». У этого есть причина. Покажите в багтрекере баша баг вроде «cd должен спрашивать подтверждения перед переходом в каталог». Написанные пользователями windows программы, ведущие диалог с пользователем, бесят хотя бы из-за сложности скриптования (пример — ntpasswd). Да, скрипты используются наравне со всеми UNIX-командами и точно так же могут быть в любом месте конвеера. Не заставляйте пользователей выкусывать бесполезный выхлоп. Мусорить \n в stderr тоже нехорошо.
3. Не прикасайтесь к /usr/bin руками без серьёзной причины. Там работает пакетный менеджер. Да и бэкапить отдельные файлы из него неудобно. Библиотеке функций место где-нибудь в (сюрприз) ~, куда пользователь может писать. В произвольном дотфайле, включенном в ~/.$SHELLrc, поскольку в повседневной работе (не все же пользуются mc) функции тоже нужны, не зря же их писали.
4. Если сообщение кажется лишним и ему не место в выводе — оно лишнее (вообще можно сделать $DEBUG, если сильно хочется). Если оно критично — оно должно быть в stdout, чтобы его мог протать следующий скрипт в пайпе. В чём смысл озвучивания test(1)? ЕМНИП, на хабре уже был топик о плохих сообщениях об ошибках, тут — каноничный пример.
5. Не организуйте диалог с пользователем велосипедными средствами. Во-первых, пользователь может оказаться пайпом. Во-вторых, есть dialog(1). И да, curPath=$(basename $BASH_SOURCE).
Скрипт — это программа, пусть и написанная для себя и для конкретной машины/группы машин. Не надо ненавидеть себя, ухудшая юзабилити. Хотя пользователям mc сойдёт.
1. Unix никогда не скажет «пожалуйста». У этого есть причина. Покажите в багтрекере баша баг вроде «cd должен спрашивать подтверждения перед переходом в каталог». Написанные пользователями windows программы, ведущие диалог с пользователем, бесят хотя бы из-за сложности скриптования (пример — ntpasswd). Да, скрипты используются наравне со всеми UNIX-командами и точно так же могут быть в любом месте конвеера. Не заставляйте пользователей выкусывать бесполезный выхлоп. Мусорить \n в stderr тоже нехорошо.
3. Не прикасайтесь к /usr/bin руками без серьёзной причины. Там работает пакетный менеджер. Да и бэкапить отдельные файлы из него неудобно. Библиотеке функций место где-нибудь в (сюрприз) ~, куда пользователь может писать. В произвольном дотфайле, включенном в ~/.$SHELLrc, поскольку в повседневной работе (не все же пользуются mc) функции тоже нужны, не зря же их писали.
4. Если сообщение кажется лишним и ему не место в выводе — оно лишнее (вообще можно сделать $DEBUG, если сильно хочется). Если оно критично — оно должно быть в stdout, чтобы его мог протать следующий скрипт в пайпе. В чём смысл озвучивания test(1)? ЕМНИП, на хабре уже был топик о плохих сообщениях об ошибках, тут — каноничный пример.
5. Не организуйте диалог с пользователем велосипедными средствами. Во-первых, пользователь может оказаться пайпом. Во-вторых, есть dialog(1). И да, curPath=$(basename $BASH_SOURCE).
Скрипт — это программа, пусть и написанная для себя и для конкретной машины/группы машин. Не надо ненавидеть себя, ухудшая юзабилити. Хотя пользователям mc сойдёт.
+15
Насчет Пункта 3. не все хабраюзеры знакомы «со стандартами», поэтому позволю себе «развернуть данный пункт»:
* /usr/bin — для тех программ, которые установленны из вашего дистрибутива. туда они ставятся, оттуда удаляются, там обновляются пакетным менеджером. И таки да, что-то самому туда класть — надо иметь серьезную причину.
* ~/bin — для тех программ, которые пользователем предполагаются для использования для самого себя. Т.е. это те скрипты, которыми пользователь автоматизирует свою работу над своими файлами.
* /usr/local/bin — программы, существующие/установленные/написанные для локально конкретной машины/группы машин. Все то, что не является частью дистрибутива, а установленно/написанно админом руками. Сами пакетные менеджеры дистрибутивов никогда туда ничего не кладут. Все что там есть — установил локально админ.
* /opt/[product-name]/bin — бинарники «больших» опциональных «программных продуктов». Если у вас такой массивный, тесно связанный программный продукт, то велкам туда.
P.S.#1: таки-да, некоторых товарищей, активно проталкивающих самые худшие практики из мира windows в мир unix, хочется пристрелить.
P.S.#2: насчет «mc юзеров» — мы же пониманием, что те mc юзеры о которых вы говорите, они же его просто «не умеют правильно готовить» (одни макроподстановки многого стоят, не говоря уже о прочей кастомизации)
* /usr/bin — для тех программ, которые установленны из вашего дистрибутива. туда они ставятся, оттуда удаляются, там обновляются пакетным менеджером. И таки да, что-то самому туда класть — надо иметь серьезную причину.
* ~/bin — для тех программ, которые пользователем предполагаются для использования для самого себя. Т.е. это те скрипты, которыми пользователь автоматизирует свою работу над своими файлами.
* /usr/local/bin — программы, существующие/установленные/написанные для локально конкретной машины/группы машин. Все то, что не является частью дистрибутива, а установленно/написанно админом руками. Сами пакетные менеджеры дистрибутивов никогда туда ничего не кладут. Все что там есть — установил локально админ.
* /opt/[product-name]/bin — бинарники «больших» опциональных «программных продуктов». Если у вас такой массивный, тесно связанный программный продукт, то велкам туда.
P.S.#1: таки-да, некоторых товарищей, активно проталкивающих самые худшие практики из мира windows в мир unix, хочется пристрелить.
P.S.#2: насчет «mc юзеров» — мы же пониманием, что те mc юзеры о которых вы говорите, они же его просто «не умеют правильно готовить» (одни макроподстановки многого стоят, не говоря уже о прочей кастомизации)
+7
Подводя все вышесказанное. Все ваши скрипты должны лежать в ~/scripts. Всегда. Пофиг на хороший тон, главное — удобство.
Туда может писать пользователь
Туда не нужны права доступа
Каталог с пользовательскими скриптами бекапится наравне с пользовательскими данными, и при этом не надо помнить — тот скрипт в /bin мой, а этот нет.
Если в PATH вы установите каталог выше системного, вы можете заменить системные программы, не влияя на остальную систему — rm -> rm -i(да, я знаю что это лучше сделать алиасом, но это пример, большие скрипты в алиасы оборачивать трудно и ненаглядно. и вызвать их не из сеанса нельзя)
Можно добавить папку в ~/.$SHELLrc, можно просто в скрипте логина PATH=/home/vvzvlad/scripts;$PATH
Туда может писать пользователь
Туда не нужны права доступа
Каталог с пользовательскими скриптами бекапится наравне с пользовательскими данными, и при этом не надо помнить — тот скрипт в /bin мой, а этот нет.
Если в PATH вы установите каталог выше системного, вы можете заменить системные программы, не влияя на остальную систему — rm -> rm -i(да, я знаю что это лучше сделать алиасом, но это пример, большие скрипты в алиасы оборачивать трудно и ненаглядно. и вызвать их не из сеанса нельзя)
Можно добавить папку в ~/.$SHELLrc, можно просто в скрипте логина PATH=/home/vvzvlad/scripts;$PATH
+4
Поддержу вышеотписавшихся, правило номер 1 из области вредных советов. Обычно консольные программы наоборот делают своё дело тихо, без лишних вопросов. Правда большинству консольных утилит необходимо передать некие параметры, например имя файла, или ключи. Без параметров программа, которой они обязательно нужны должна выводить некий мануал по использованию себя.
Но правило номер 1 разве что будет уместно, если скрипт пишется только для себя, когда обычно лениво(или нет времени) делать ключи, вместо этого данные хардкодятся в самом скрипте, тогда действительно полезно напомнить пользователю что делает скрипт.
Но правило номер 1 разве что будет уместно, если скрипт пишется только для себя, когда обычно лениво(или нет времени) делать ключи, вместо этого данные хардкодятся в самом скрипте, тогда действительно полезно напомнить пользователю что делает скрипт.
+1
Выводить запросы полезно при распространении скриптов с чем-либо, а не как самостоятельных утилит. Например, я пользуюсь запросы и case-ы
Для себя, как раз, быстрее и проще сохранить одну команду с кучей параметров, а для скрипта, решающего единственную задачу лучше действия пользователя ограничить сценарием, где можно прописать кучу правил.
С последней ситуацией в консоле поможет справиться zsh, но не все им пользуются.
zenity
для создания сценариев работы с git-репозиториями, там же и размещая.Для себя, как раз, быстрее и проще сохранить одну команду с кучей параметров, а для скрипта, решающего единственную задачу лучше действия пользователя ограничить сценарием, где можно прописать кучу правил.
С последней ситуацией в консоле поможет справиться zsh, но не все им пользуются.
0
Я бы рекомендовал сделать функцию log/message для сообщений консоли и сообщений в лог и по соответствующим параметрам командной строки вести вывод в консоль/лог(если пайп или планировщик) — все что вывелось на консоль при вызове из планировщика уйдет письмом на root@.
библиотеки хранить в ~/bin — в системные каталоги лучше не лезть — как пить дать забудете, а скопировав ~ — все переехало.
а вообще это все дело здравой логики — я, например когда написал свои скрипты по обработке видео от вебкамер, про сервер вообще забыл, только потому что предусмотрел максимальное количество проблем сразу — уход в даун самба шары на сервере бекапов, очистку места на локальном разделе, куда складывается архив от камер. Я последний раз зашел на сервер перед увольнением закрыть сессии и обновить — скрипты работали как часы. у меня одна из публикаций на хабре как раз про них.
PS — да, у меня даже проверялось наличие зависимостей инсталляционным скриптом.
библиотеки хранить в ~/bin — в системные каталоги лучше не лезть — как пить дать забудете, а скопировав ~ — все переехало.
а вообще это все дело здравой логики — я, например когда написал свои скрипты по обработке видео от вебкамер, про сервер вообще забыл, только потому что предусмотрел максимальное количество проблем сразу — уход в даун самба шары на сервере бекапов, очистку места на локальном разделе, куда складывается архив от камер. Я последний раз зашел на сервер перед увольнением закрыть сессии и обновить — скрипты работали как часы. у меня одна из публикаций на хабре как раз про них.
PS — да, у меня даже проверялось наличие зависимостей инсталляционным скриптом.
0
Не стоит ничего закидывать системные директории руками без веской на то причины, ибо такое действие может породить трудноуловимые баги (типа внезапно сменившейся локали, $PATH и так далее). Предлагаю так:
Выкидываем bash, берем любой скриптовый язык типа перла, руби или питона. Можете считать это личным мнением, но не вижу смысла интенсивно использовать sh скрипты, когда есть более мощные (и, субъективно, с менее крышесносящим синтаксисом) языки типа перла, где в большинстве случаев написание скрипта сведется к написанию cli-интерфейса к какому-нибудь модулю с cpan.
Пишем установочный скрипт, кидаем все в гит-репозиторий. Установщик должен определять, запущен ли он с повышенными привилегиями (и тогда ставить основной скрипт в /usr/local/bin) или нет (скрипт отправляется в $HOME/bin, эта же директория добавляется в $PATH). Тогда на целевых машинах делаем curl path/to/raw/installer.script | [sudo] sh. Можно хранить в отдельном репозитории бандлы — наборы адресов к инсталлерам, и тогда можно будет одной командой развертывать десятки скриптов.
Выкидываем bash, берем любой скриптовый язык типа перла, руби или питона. Можете считать это личным мнением, но не вижу смысла интенсивно использовать sh скрипты, когда есть более мощные (и, субъективно, с менее крышесносящим синтаксисом) языки типа перла, где в большинстве случаев написание скрипта сведется к написанию cli-интерфейса к какому-нибудь модулю с cpan.
Пишем установочный скрипт, кидаем все в гит-репозиторий. Установщик должен определять, запущен ли он с повышенными привилегиями (и тогда ставить основной скрипт в /usr/local/bin) или нет (скрипт отправляется в $HOME/bin, эта же директория добавляется в $PATH). Тогда на целевых машинах делаем curl path/to/raw/installer.script | [sudo] sh. Можно хранить в отдельном репозитории бандлы — наборы адресов к инсталлерам, и тогда можно будет одной командой развертывать десятки скриптов.
-1
Интересная схема, как-то сам не додумывался. Практикуете такое или это был теоретический подход?
+2
Частично. Пока есть разнесенные по машинам организованные таким образом скрипты. Все, что мне нужно — залить их на гитхаб, заодно можно навести порядок в .dot файлах. Пришла в голову собрать все именно таким способом только сейчас.
На гитхабе некоторые проекты практикуют такую схему установки. Например:
— github.com/kraih/mojo
— github.com/nvie/gitflow/wiki/Linux
На гитхабе некоторые проекты практикуют такую схему установки. Например:
— github.com/kraih/mojo
— github.com/nvie/gitflow/wiki/Linux
0
Совет 1 — не пользуйтесь mc, лучше настраивайте окружение что бы не требовалось бегать по путям лишний раз. А привычка работать просто в командной строке вам поможет если сервер будет в перегрузке.
Совет 2 — прежде чем что-то вещать, читайте и гуглите. Есть много вещей, которые в общем называются unix way, жаль я не видел их более-менее оформленными как например в питоне. Одна из таких вещей — утилиты и скрипты должны делаться атомарными, на одно действие, но достаточно полными, уметь работать с потоками io и так далее. Для стандартных действий всегда можно найти уже рабочий и отлаженный скрипт или утилиту.
Совет 3 — для того что бы пользоваться ем-нить надо неделя-месяц, что бы стать более-менее опытным в чем либо надо полгода-год. Уровень эксперта — 2-3 года и уровень мастера 5-7 лет ( пресловутые 10к часов ). Каждый из пройденных этапов можно явно почувствовать улучшением эффективности в критичной на этот момент работе, что вызывает обычно небольшую эйфорию и желание поделиться своей мудростью. Воздерживайтесь по мере сил от этого, пока не станете мастером.
Совет 2 — прежде чем что-то вещать, читайте и гуглите. Есть много вещей, которые в общем называются unix way, жаль я не видел их более-менее оформленными как например в питоне. Одна из таких вещей — утилиты и скрипты должны делаться атомарными, на одно действие, но достаточно полными, уметь работать с потоками io и так далее. Для стандартных действий всегда можно найти уже рабочий и отлаженный скрипт или утилиту.
Совет 3 — для того что бы пользоваться ем-нить надо неделя-месяц, что бы стать более-менее опытным в чем либо надо полгода-год. Уровень эксперта — 2-3 года и уровень мастера 5-7 лет ( пресловутые 10к часов ). Каждый из пройденных этапов можно явно почувствовать улучшением эффективности в критичной на этот момент работе, что вызывает обычно небольшую эйфорию и желание поделиться своей мудростью. Воздерживайтесь по мере сил от этого, пока не станете мастером.
+3
И это в плюсе?! Ужс.
Собственно, конкретно bash'а я тут и не увидел(впрочем, код смотрел по диагонали).
Вы работаете под рутом?
Собственно к каждому скрипту надо делать usage(), а не эту хрень спрашивающую почём зря неадекватные вопросы. Как вы этот скрипт будете запускать на 100 серверов? Писать второй на expect?
Использовать глобальную переменную для этого плохо, ибо тогда их нужно создавать по одной на каждую функцию. Обычно вместо этого используют printf или передачу имени переменной назначения через параметр + eval.
Автору: сходи-ка ты почитай хороший sh, например, svn.freebsd.org/base/head/etc/rc.subr
Приемы написания скриптов в Bash
Собственно, конкретно bash'а я тут и не увидел(впрочем, код смотрел по диагонали).
Вы вдруг нажали не на тот скрипт, то с системой может произойти все что угодно.
Вы работаете под рутом?
Ты уверен, что хочешь запустить это (y/[a])
Собственно к каждому скрипту надо делать usage(), а не эту хрень спрашивающую почём зря неадекватные вопросы. Как вы этот скрипт будете запускать на 100 серверов? Писать второй на expect?
В Bash не очень хорошо обстоят дела с возвратом значения из функции
Использовать глобальную переменную для этого плохо, ибо тогда их нужно создавать по одной на каждую функцию. Обычно вместо этого используют printf или передачу имени переменной назначения через параметр + eval.
Автору: сходи-ка ты почитай хороший sh, например, svn.freebsd.org/base/head/etc/rc.subr
+6
Совет 0. Ваш sh-скрипт должен занимать максимум 2-4 экрана в редакторе. Если скрипт слишком большой — перепишите его на нормальном языке программирования. Perl и Python сейчас есть практически везде (embedded-гусары, молчать!).
Если Вы не можете написать простой и лаконичный скрипт, то это не скрипт. Либо напишите его и никому не показывайте (.bashrc — отличное место, где можно делать всё, что Вам угодно).
Противники этого совета могут попробовать взять на поддержку пачку унаследованных связанных друг с другом sh-скриптов хотя бы в 2 тысячи строк размером и 5 лет возрастом и поделиться ощущениями.
Если Вы не можете написать простой и лаконичный скрипт, то это не скрипт. Либо напишите его и никому не показывайте (.bashrc — отличное место, где можно делать всё, что Вам угодно).
Противники этого совета могут попробовать взять на поддержку пачку унаследованных связанных друг с другом sh-скриптов хотя бы в 2 тысячи строк размером и 5 лет возрастом и поделиться ощущениями.
+2
Для пущего эффекта снабдить скрипт кучей объёмных неформатированных sed и awk вставок без единого комментария. Например таких:
echo 0|sed 's909=bO%3g)o19;s0%0aob)]vO0;s()(0eh}=(;s%}%r1="?0^2{%;
s)")@l2h3%"@$);sw%wh]r()$o%!w;sz(z^+.z;sa+a !z" a;sxzxi?v{a)ax;:b;
s/\(\(.\).\)\(\(..\)*\)\(\(.\).\)\(\(..\)*%.*\6.*\2.*\)/\5\1\3\7/;
tb;s/%.*//;s/.\(.\)/\1/g'
+3
К сожалению ваш код не портабельный :) POSIX sed сломался на цикле, вот этот должен работать и не на gnu sed:
(метка в данном случае будет b; так как отсекается по концу строки а не разделителю)
echo 0|sed 's909=bO%3g)o19;s0%0aob)]vO0;s()(0eh}=(;s%}%r1="?0^2{%;
s)")@l2h3%"@$);sw%wh]r()$o%!w;sz(z^+.z;sa+a !z" a;sxzxi?v{a)ax;:b;
s/\(\(.\).\)\(\(..\)*\)\(\(.\).\)\(\(..\)*%.*\6.*\2.*\)/\5\1\3\7/;
tb;
s/%.*//;s/.\(.\)/\1/g'
(метка в данном случае будет b; так как отсекается по концу строки а не разделителю)
+4
Совет -1. Если вы пользуйтесь скриптами для автоматизации каких-либо процессов, которые должны проходить без участия пользователя, то не пользуйтесь Советом 1.
Ваш кэп.
Ваш кэп.
+6
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Приемы написания скриптов в Bash