🔥 Циклы в Bash: от каменного века до современности
Эй, мастер итераций!
Всё ещё пишешь
🦕 Каменный век:
🏛️ Античность (seq):
🏭 Индустриальная эра (Bash 3+):
🚀 Современность (C-style):
💥 Высший пилотаж — оператор запятая:
💡 Что выбрать:
- {1..10} — для простых диапазонов
- C-style — для сложной логики
- seq — для обратной совместимости
Все примеры выводят:
Больше никаких длинных перечислений! Используй современный синтаксис.
____________________
Дополнительный материал:
🧠 - Централизованное управление пользователями в Linux: Гармония преимуществ и вызовов
🧠 - Создание учетной записи пользователя в Linux: Пошаговое руководство
🧠 - Мастер-класс по созданию системных аккаунтов в Linux
#bash_guide #bash #loops #scripting #Linux #programming #for
Эй, мастер итераций!
Всё ещё пишешь
for i in 1 2 3 4 5? Покажу эволюцию циклов в Bash — от динозавров до современного синтаксиса!🦕 Каменный век:
for a in 1 2 3 4 5 6 7 8 9 10
do
echo -n "$a "
done
🏛️ Античность (seq):
for a in `seq 10`
do
echo -n "$a "
done
🏭 Индустриальная эра (Bash 3+):
for a in {1..10}
do
echo -n "$a "
done
🚀 Современность (C-style):
LIMIT=10
for ((a=1; a <= LIMIT; a++))
do
echo -n "$a "
done
💥 Высший пилотаж — оператор запятая:
# Инкремент двух переменных одновременно!
for ((a=1, b=1; a <= LIMIT; a++, b++))
do
echo -n "$a-$b "
done
# Вывод: 1-1 2-2 3-3 4-4 5-5...
💡 Что выбрать:
- {1..10} — для простых диапазонов
- C-style — для сложной логики
- seq — для обратной совместимости
Все примеры выводят:
1 2 3 4 5 6 7 8 9 10Больше никаких длинных перечислений! Используй современный синтаксис.
____________________
Дополнительный материал:
🧠 - Централизованное управление пользователями в Linux: Гармония преимуществ и вызовов
🧠 - Создание учетной записи пользователя в Linux: Пошаговое руководство
🧠 - Мастер-класс по созданию системных аккаунтов в Linux
#bash_guide #bash #loops #scripting #Linux #programming #for
Telegram
Linux Skill - Освой Linux c нуля до DevOps
🌐🔧 ""Централизованное управление пользователями в Linux: Гармония преимуществ и вызовов"" 🤝💼
Привет, администраторы Linux и строители цифровых сообществ! Сегодня мы поговорим о том, как централизованное управление пользователями в Linux открывает новые горизонты…
Привет, администраторы Linux и строители цифровых сообществ! Сегодня мы поговорим о том, как централизованное управление пользователями в Linux открывает новые горизонты…
👍17
🔥 Забудь про $1 $2 $3: умные опции через getopts
Привет, архитектор CLI!
Надоело парсить аргументы через позиционные параметры? Делаем профессиональные флаги как в настоящих утилитах!
🔧 Базовый шаблон с getopts:
💡 Как работает:
-
-
-
🚀 Примеры вызова:
📌 Бонус — импорт функций:
Теперь твои скрипты выглядят как настоящие Linux-утилиты!
____________________
Дополнительный материал:
🧠 - Командный центр Linux: Ваше руководство по базовым консольным программам
🧠 - Защитный барьер Linux: Как система обеспечивает безопасность пользователей и групп
🧠 - Мастер-класс по консольным программам Linux: Разбираемся с UID и GID
#bash_guide #bash #getopts #cli #scripting #Linux #arguments
Привет, архитектор CLI!
Надоело парсить аргументы через позиционные параметры? Делаем профессиональные флаги как в настоящих утилитах!
🔧 Базовый шаблон с getopts:
#!/bin/bash
# Проверка аргументов
if [ $# -eq 0 ]; then
echo "Usage: $(basename $0) -mnopqrs"
exit 1
fi
# Парсинг опций
while getopts ":mnopq:rs" Option; do
case $Option in
m ) echo "Опция -m активна";;
n|o ) echo "Опция -$Option активна";;
p ) echo "Опция -p активна";;
q ) echo "Опция -q с аргументом: $OPTARG";;
r|s ) echo "Опция -$Option";;
* ) echo "Неверная опция";;
esac
done
# Сдвиг к не-опциям
shift $(($OPTIND - 1))
💡 Как работает:
-
:mnopq:rs — строка опций (: после q = требует аргумент)-
$OPTARG — значение для опции с аргументом-
$OPTIND — индекс следующего аргумента🚀 Примеры вызова:
./script.sh -m -n
./script.sh -mn # можно слитно!
./script.sh -q "значение"
./script.sh -mnop -q test
📌 Бонус — импорт функций:
# Загружаем общие функции
source /path/to/common_functions.sh
# или
. ./config.sh
Теперь твои скрипты выглядят как настоящие Linux-утилиты!
____________________
Дополнительный материал:
🧠 - Командный центр Linux: Ваше руководство по базовым консольным программам
🧠 - Защитный барьер Linux: Как система обеспечивает безопасность пользователей и групп
🧠 - Мастер-класс по консольным программам Linux: Разбираемся с UID и GID
#bash_guide #bash #getopts #cli #scripting #Linux #arguments
Telegram
Linux Skill - Освой Linux c нуля до DevOps
🌟🐧 ""Командный центр Linux: Ваше руководство по базовым консольным программам"" 🛠️📚
В мире Linux, где каждая команда открывает новые возможности для управления и анализа системы, важно иметь под рукой надежный справочник. Вот почему было решено собрать все…
В мире Linux, где каждая команда открывает новые возможности для управления и анализа системы, важно иметь под рукой надежный справочник. Вот почему было решено собрать все…
👍13
🔧 20+ переменных Bash, которые ты точно не использовал
Привет, повелитель скриптов!
Видел скрипты, где пути и настройки вбиты намертво? А потом ломаешь голову, почему они не работают на другой машине. Bash уже всё придумал за тебя — используй зарезервированные переменные.
📂 Навигация и окружение
$DIRSTACK — Содержимое вершины стека каталогов
$OLDPWD — Прежний рабочий каталог
$PATH — Путь поиска программ
$HOME — Домашний каталог пользователя
👤 Информация о пользователе
$UID — Содержит реальный идентификатор, который устанавливается только при логине
$EUID — Эффективный UID. Если вы использовали программу su для выполнения команд от другого пользователя, то эта переменная содержит UID этого пользователя
$GROUPS — Массив групп к которым принадлежит текущий пользователь
🖥️ Информация о системе
$HOSTNAME — hostname машины
$HOSTTYPE — Архитектура машины
$OSTYPE — Тип ОС
⚙️ Работа со скриптами и функциями
$EDITOR — Текстовый редактор по-умолчанию
$FUNCNAME — Имя текущей функции в скрипте
$SECONDS — Время работы скрипта (в сек.)
$$ — PID самого скрипта
$PPID — Идентификатор родительского процесса
$! — PID последнего запущенного в фоне процесса
$? — Содержит код завершения последней команды
📝 Работа с параметрами
$# — Общее количество параметров переданных скрипту
$* — Все аргументы переданные скрипту (выводятся в строку)
$@ — Тоже самое, что и предыдущий, но параметры выводятся в столбик
🔍 Дополнительные переменные
$LC_CTYPE — Внутренняя переменная, которая определяет кодировку символов
🔖 Сохрани шпаргалку — пригодится в каждом скрипте!
#Linux_Mastery #bash #scripting #linux #automation #devops #sysadmin
Привет, повелитель скриптов!
Видел скрипты, где пути и настройки вбиты намертво? А потом ломаешь голову, почему они не работают на другой машине. Bash уже всё придумал за тебя — используй зарезервированные переменные.
📂 Навигация и окружение
$DIRSTACK — Содержимое вершины стека каталогов
$OLDPWD — Прежний рабочий каталог
$PATH — Путь поиска программ
$HOME — Домашний каталог пользователя
👤 Информация о пользователе
$UID — Содержит реальный идентификатор, который устанавливается только при логине
$EUID — Эффективный UID. Если вы использовали программу su для выполнения команд от другого пользователя, то эта переменная содержит UID этого пользователя
$GROUPS — Массив групп к которым принадлежит текущий пользователь
🖥️ Информация о системе
$HOSTNAME — hostname машины
$HOSTTYPE — Архитектура машины
$OSTYPE — Тип ОС
⚙️ Работа со скриптами и функциями
$EDITOR — Текстовый редактор по-умолчанию
$FUNCNAME — Имя текущей функции в скрипте
$SECONDS — Время работы скрипта (в сек.)
$$ — PID самого скрипта
$PPID — Идентификатор родительского процесса
$! — PID последнего запущенного в фоне процесса
$? — Содержит код завершения последней команды
📝 Работа с параметрами
$# — Общее количество параметров переданных скрипту
$* — Все аргументы переданные скрипту (выводятся в строку)
$@ — Тоже самое, что и предыдущий, но параметры выводятся в столбик
🔍 Дополнительные переменные
$LC_CTYPE — Внутренняя переменная, которая определяет кодировку символов
🔖 Сохрани шпаргалку — пригодится в каждом скрипте!
#Linux_Mastery #bash #scripting #linux #automation #devops #sysadmin
👍10🔥3
⚠️ Никогда не используй [ ] в Bash, пока не прочитаешь это
Привет, инженер! 👋
Сколько раз ты ловил binary operator expected или забывал экранировать > в условии? В Bash скобки — это не просто стиль, это разные инструменты с разной логикой.
Давай разложим всё по полочкам, чтобы твои скрипты работали предсказуемо.
📌 1. Одинарные квадратные [ ... ] — Классика (test)
Это синоним команды test. Она старая, POSIX-совместимая, но капризная.
Нюанс: Переменные нужно брать в кавычки "$var", иначе при пустом значении скрипт упадет.
Минус: Знаки > и < нужно экранировать (\>), иначе Bash решит, что это перенаправление ввода/вывода.
📌 2. Двойные квадратные [[ ... ]] — Расширенная проверка
Это ключевое слово самого Bash. Оно мощнее и безопаснее.
Плюс: Не нужно экранировать > и <.
Поддерживает логические && и || прямо внутри скобок.
Киллер-фича: Поддерживает регулярные выражения через оператор =~.
📌 3. Одинарные круглые ( ... ) — Подоболочка (Subshell)
Команды внутри запускаются в отдельном процессе.
Суть: Переменные, измененные внутри (), не меняются в основном скрипте.
Пример: (cd /tmp; rm *.log) — вы перейдете в папку только внутри скобок, основной скрипт останется в текущей директории.
📌 4. Двойные круглые (( ... )) — Арифметика
Специальная конструкция для математики в стиле Си.
Плюс: Можно не писать $ перед переменными.
Поддерживает инкременты var++ и тернарные операторы.
💡 Итог:
Пишешь на Bash? Всегда используй [[ ]] для условий и (( )) для математики. Оставь [ ] для совместимости со старым sh.
#Linux #Bash #DevOps #Scripting #Shell
Привет, инженер! 👋
Сколько раз ты ловил binary operator expected или забывал экранировать > в условии? В Bash скобки — это не просто стиль, это разные инструменты с разной логикой.
Давай разложим всё по полочкам, чтобы твои скрипты работали предсказуемо.
📌 1. Одинарные квадратные [ ... ] — Классика (test)
Это синоним команды test. Она старая, POSIX-совместимая, но капризная.
Нюанс: Переменные нужно брать в кавычки "$var", иначе при пустом значении скрипт упадет.
Минус: Знаки > и < нужно экранировать (\>), иначе Bash решит, что это перенаправление ввода/вывода.
if [ "$a" = "root" ]; then echo "Hi root"; fi
📌 2. Двойные квадратные [[ ... ]] — Расширенная проверка
Это ключевое слово самого Bash. Оно мощнее и безопаснее.
Плюс: Не нужно экранировать > и <.
Поддерживает логические && и || прямо внутри скобок.
Киллер-фича: Поддерживает регулярные выражения через оператор =~.
# Проверка регуляркой (без кавычек!)
if [[ "$ver" =~ ^3\. ]]; then echo "Version 3.x"; fi
📌 3. Одинарные круглые ( ... ) — Подоболочка (Subshell)
Команды внутри запускаются в отдельном процессе.
Суть: Переменные, измененные внутри (), не меняются в основном скрипте.
Пример: (cd /tmp; rm *.log) — вы перейдете в папку только внутри скобок, основной скрипт останется в текущей директории.
📌 4. Двойные круглые (( ... )) — Арифметика
Специальная конструкция для математики в стиле Си.
Плюс: Можно не писать $ перед переменными.
Поддерживает инкременты var++ и тернарные операторы.
(( a++ )) # Увеличить a на 1
b=$(( a + 5 )) # Записать результат в b
💡 Итог:
Пишешь на Bash? Всегда используй [[ ]] для условий и (( )) для математики. Оставь [ ] для совместимости со старым sh.
#Linux #Bash #DevOps #Scripting #Shell
👍16
🔥 Забудь про UptimeRobot: Свой мониторинг на коленке
printf "Hello\n"
Иногда разворачивать тяжелые комбайны мониторинга ради проверки пары узлов — это как стрелять из пушки по воробьям. Ты же знаешь силу командной строки: зачем тебе веб-интерфейс, если есть старый добрый Bash?
Можно написать простой скрипт, который будет проверять доступность хоста и сообщать статус. Это база, которая работает на любом утюге с Linux.
📌 Скрипт проверки доступности узла:
Разбор полетов:
Переменная HNAME хранит адрес цели.
ping -c 2 отправляет ровно два пакета (чтобы не ждать вечно).
Конструкция if [[ ... ]] проверяет код возврата команды ping. Если 0 (успех) — узел жив.
💡 Почему это круто:
Ты не зависишь от стороннего софта.
Работает даже на встраиваемых системах и роутерах.
Легко добавить отправку уведомления на почту или в Telegram прямо в блок else.
#Linux #Bash #DevOps #Scripting #Monitoring
printf "Hello\n"
Иногда разворачивать тяжелые комбайны мониторинга ради проверки пары узлов — это как стрелять из пушки по воробьям. Ты же знаешь силу командной строки: зачем тебе веб-интерфейс, если есть старый добрый Bash?
Можно написать простой скрипт, который будет проверять доступность хоста и сообщать статус. Это база, которая работает на любом утюге с Linux.
📌 Скрипт проверки доступности узла:
HNAME=news-15.net # Пресловутый спамер.
# HNAME=$HOST # Отладка: проверка локальной сети.
count=2 # Отсылаются только два пинга.
if [[ `ping -c $count "$HNAME"` ]]
then
echo ""$HNAME" все еще работает и рассылает спам."
else
echo ""$HNAME" Кажется выключен. Жаль."
fi
Разбор полетов:
Переменная HNAME хранит адрес цели.
ping -c 2 отправляет ровно два пакета (чтобы не ждать вечно).
Конструкция if [[ ... ]] проверяет код возврата команды ping. Если 0 (успех) — узел жив.
💡 Почему это круто:
Ты не зависишь от стороннего софта.
Работает даже на встраиваемых системах и роутерах.
Легко добавить отправку уведомления на почту или в Telegram прямо в блок else.
#Linux #Bash #DevOps #Scripting #Monitoring
👍6
🔧 Хватит писать как джун. 15 хардкорных идиом Bash для профи
Bash-скрипты кажутся простыми, пока не начинают молча ломать серверы из-за неэкранированных пробелов или проигнорированных ошибок в конвейерах. Держи 15 идиом, которые выведут твои скрипты на уровень Senior.
Жёсткая защита и отладка
Подстановки переменных (без sed и awk)
Логика и структуры
Потоки и дескрипторы
Внедряй эти идиомы, чтобы скрипты не зависели от внешних утилит и не падали на пустом месте.
❗️ ❗️ ❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #Bash #DevOps #Scripting #SysAdmin
Bash-скрипты кажутся простыми, пока не начинают молча ломать серверы из-за неэкранированных пробелов или проигнорированных ошибок в конвейерах. Держи 15 идиом, которые выведут твои скрипты на уровень Senior.
Жёсткая защита и отладка
# 1. Неофициальный строгий режим bash.
# Падение при первой ошибке (-e), при обращении к необъявленной переменной (-u), и ошибка внутри конвейера не проглатывается (pipefail).
set -euo pipefail
# 2. Массив PIPESTATUS.
# В конвейере обычный $? покажет статус только ПОСЛЕДНЕЙ команды.
# PIPESTATUS хранит коды всех команд — ОБРАЩАЙСЯ ПО ИНДЕКСУ: ${PIPESTATUS[0]}, [1]...
cat /etc/passwd | grep -q root
echo "Статус cat: ${PIPESTATUS[0]}, статус grep: ${PIPESTATUS[1]}"
# 3. Безопасная очистка через trap.
# Временные файлы удалятся при любом выходе, включая Ctrl+C.
TMP_FILE=$(mktemp)
trap 'rm -f "$TMP_FILE"' EXIT
Подстановки переменных (без sed и awk)
# 4. Значение по умолчанию, если TARGET не задана или пуста.
cd "${TARGET:-/tmp}"
# 5. Глобальная замена подстрок в памяти (все вхождения).
LOG="system error, network error"
echo "${LOG//error/warning}"
# 6. Косвенные ссылки: читаем переменную, имя которой лежит в другой переменной.
REAL_VAR="SecretData"
POINTER="REAL_VAR"
echo "${!POINTER}"
# 7. Обрезка префикса/суффикса (замена basename и dirname).
FILEPATH="/var/log/syslog.tar.gz"
echo "${FILEPATH##*/}" # всё до последнего слеша срезано: syslog.tar.gz
echo "${FILEPATH%/*}" # всё после последнего слеша срезано: /var/log
Логика и структуры
# 8. Регулярки прямо в условии (только в [[ ... ]], регулярку справа НЕ кавычим).
if [[ $1 =~ ^[0-9]+$ ]]; then
echo "Аргумент состоит только из цифр"
fi
# 9. Группировка команд в ТЕКУЩЕМ процессе через { ... } (переменные сохраняются).
[[ -d /tmp/app ]] || { echo "Каталог не найден"; exit 1; }
# 10. Встроенная арифметика вместо мёртвого expr.
# ОСТОРОЖНО: под 'set -e' выражение (( x++ )) возвращает код 1, когда старое значение 0, и убивает скрипт. Используй префиксную форму ++COUNT или добавляй '|| true'.
COUNT=5
(( ++COUNT ))
(( REMAINING = 100 - COUNT ))
Потоки и дескрипторы
# 11. Подстановка процессов: вывод команд туда, где ждут ИМЕНА файлов.
diff -u <(ls -l /dir1) <(ls -l /dir2)
# 12. Here String: строка на stdin без лишнего процесса echo.
grep "critical" <<< "$LOG_DATA"
# 13. Правильное построчное чтение.
# -r запрещает трактовать бэкслеши, пустой IFS= сохраняет ведущие пробелы.
while IFS= read -r line; do
echo "Прочитана строка: $line"
done < config.txt
# 14. Парсинг строки с локальной подменой IFS (только для этой команды read).
USER_INFO="root:x:0:0:root:/root:/bin/bash"
IFS=":" read -r user pass uid gid desc home shell <<< "$USER_INFO"
# 15. Совместное перенаправление stdout и stderr одним оператором.
/opt/scripts/backup.sh &> /var/log/backup.log
Внедряй эти идиомы, чтобы скрипты не зависели от внешних утилит и не падали на пустом месте.
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #Bash #DevOps #Scripting #SysAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥2
☠️ Твой скрипт не переживёт пробел в имени файла. 15 сниппетов для сеньоров
Замечал, как рабочий скрипт внезапно затирает данные из-за пустой переменной или ломается от кривого переноса строки? Чтобы не краснеть за код перед коллегами, перестань использовать устаревшие конструкции. Держи 15 жёстких приёмов для неубиваемых скриптов.
Защита от фатальных сбоев
Работа с переменными без sed и awk
Логика без костылей
Работа с файлами и потоками
❗️ ❗️ ❗️ Нравится формат? Ставь 👍
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #Bash #DevOps #Scripting #SysAdmin
Замечал, как рабочий скрипт внезапно затирает данные из-за пустой переменной или ломается от кривого переноса строки? Чтобы не краснеть за код перед коллегами, перестань использовать устаревшие конструкции. Держи 15 жёстких приёмов для неубиваемых скриптов.
Защита от фатальных сбоев
# 1. Неофициальный строгий режим. Падение при первой ошибке,
# обращении к пустой переменной и ошибке внутри конвейера.
set -euo pipefail
# 2. Безопасная очистка мусора. Сработает даже при Ctrl+C (SIGINT).
TMP_DIR=$(mktemp -d)
trap 'rm -rf "$TMP_DIR"' EXIT
# 3. Статусы в конвейере. Обычный $? покажет только последнюю команду.
# PIPESTATUS хранит массив — обращайся ПО ИНДЕКСУ: [0], [1]...
cat /etc/passwd | grep -q missing_user
echo "Статус cat: ${PIPESTATUS[0]}, статус grep: ${PIPESTATUS[1]}"
Работа с переменными без sed и awk
# 4. Значение по умолчанию. Защищает от rm по пустому пути.
# ВАЖНО: при set -u скрипт и так упадёт на пустой TARGET — двойная защита.
rm -rf "${TARGET:-/tmp/fallback}/"*
# 5. Глобальная замена подстроки в памяти.
LOG="error db, error net"
echo "${LOG//error/warning}"
# 6. Косвенная адресация: чтение переменной по имени из другой переменной.
REAL_VAR="SecretKey"
POINTER="REAL_VAR"
echo "${!POINTER}"
# 7. Нативная замена basename и dirname (без вызова внешних утилит).
FILE="/var/log/syslog.gz"
echo "${FILE##*/}" # syslog.gz (срезано всё до последнего слеша)
echo "${FILE%/*}" # /var/log (срезано всё после последнего слеша)
Логика без костылей
# 8. Регулярки нативно (только в [[ ]], регулярку справа НЕ кавычим).
if [[ $1 =~ ^[0-9]+$ ]]; then
echo "Передано число"
fi
# 9. Группа команд в текущем процессе (без subshell) — переменные сохраняются.
[[ -d /app ]] || { echo "Директории нет"; exit 1; }
# 10. Арифметика в стиле C. expr мёртв.
# ОСТОРОЖНО: под set -e постфиксный (( COUNT++ )) возвращает код 1, когда старое
# значение было 0, и убивает скрипт. Используй префиксную форму ++COUNT.
COUNT=5
(( ++COUNT ))
(( REMAINING = 100 - COUNT ))
Работа с файлами и потоками
# 11. Подстановка процессов: вывод команд туда, где ждут файлы.
diff -u <(ls -l /dir1) <(ls -l /dir2)
# 12. Here String: строка на stdin без лишнего echo | grep.
grep "critical" <<< "$LOG_DATA"
# 13. Эталонное построчное чтение: -r не трогает бэкслеши, IFS= хранит пробелы.
while IFS= read -r line; do
echo "Строка: $line"
done < config.txt
# 14. Разбивка строки на переменные с локальной подменой разделителя.
USER_DATA="admin:x:1000"
IFS=":" read -r user pass uid <<< "$USER_DATA"
# 15. Совместное перенаправление stdout и stderr одним оператором.
/opt/scripts/deploy.sh &> /var/log/deploy.log
👉 Рубрика: #шпаргалка@LinuxSkill
#Linux #Bash #DevOps #Scripting #SysAdmin
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
Обойти массив путей с пробелами и не получить вместо одной папки три несуществующих.
Перебрать элементы, не разорвав их по пробелам
Кавычки вокруг
Посчитать элементы
Нюанс:
Обойти разреженный массив
Нюанс: если удалить элемент через
Прочитать файл в массив
Нюанс:
Сделать словарь
Нюанс:
Общее у всех пяти: bash не ругается, а тихо делает не то. Поэтому
А вы конфиги в bash разбираете ассоциативными массивами или сразу отдаёте jq?
#Linux #Bash #Shell #Scripting #DevOps
Перебрать элементы, не разорвав их по пробелам
folders=("/var/log/nginx" "/var/log/app with space")
for d in "${folders[@]}"; do
ls -ld "$d"
done
Кавычки вокруг
${folders[@]} обязательны. Без них тот же цикл на моём тесте выдал четыре итерации вместо двух: путь распался на /var/log/app, with и space. И не путай @ с *: под кавычками "${folders[*]}" склеивает весь массив в одну строку.Посчитать элементы
echo "${#folders[@]}"
Нюанс:
${#folders} без [@] — это не размер массива, а длина первого элемента. У меня вернуло 8 вместо 3, и никакой ошибки.Обойти разреженный массив
for i in "${!sparse[@]}"; do
echo "$i = ${sparse[$i]}"
done
Нюанс: если удалить элемент через
unset, индексы останутся с дырками. Массив с индексами 0, 5, 9 имеет размер 3 — обход по seq 0 2 найдёт один элемент из трёх. Перебирать надо индексы через ${!arr[@]}, а не числа от нуля.Прочитать файл в массив
readarray -t lines < /var/log/app.log
readarray -t lines < <(grep -v '^$' /var/log/app.log)
Нюанс:
cat file | readarray -t lines не работает. Пайп запускает readarray в подоболочке, массив заполняется там и умирает вместе с ней. У меня получилось 0 элементов вместо 4, снова без ошибки. Нужен либо редирект, либо подстановка процесса < <(...).Сделать словарь
declare -A ports=([nginx]=80 [php-fpm]=9000)
Нюанс:
declare -A не формальность. Без него bash создаёт обычный индексный массив, все строковые ключи считаются нулём, и каждое присваивание перетирает предыдущее. Проверил: ${ports[nginx]} вернуло 9000 — значение от php-fpm.Общее у всех пяти: bash не ругается, а тихо делает не то. Поэтому
shellcheck на скриптах с массивами экономит больше времени, чем кажется.А вы конфиги в bash разбираете ассоциативными массивами или сразу отдаёте jq?
#Linux #Bash #Shell #Scripting #DevOps
👍2
Выкинуть из скрипта форки awk и cut и не нарваться на подстановку, которая молчит
Разобрать путь без basename и dirname
Замерил тысячу итераций в цикле:
Собрать файлы в массив вместо ls
Нюанс: без
Сравнить вывод двух команд без временных файлов
Задать дефолт и проверить обязательные переменные
Нюанс: двоеточие в
Собрать тайминги шагов скрипта
Нюанс: в подборках сюда пишут
А что вы чаще выносите из скриптов — cut и awk или всё-таки оставляете, потому что читается понятнее?
#Linux #Bash #Shell #Scripting #DevOps
Разобрать путь без basename и dirname
path="/var/log/nginx/access.log.tar.gz"
name="${path##*/}" # access.log.tar.gz
dir="${path%/*}" # /var/log/nginx
Замерил тысячу итераций в цикле:
basename — 1107 мс, подстановка — 5 мс. Разница в двести раз, и это не про скорость самой утилиты, а про форк процесса на каждый вызов.Собрать файлы в массив вместо ls
shopt -s nullglob
files=(/var/log/nginx/*.log)
cp -- "${files[@]}" /backup/logs/
Нюанс: без
nullglob массив по несуществующей маске не пустой. Проверил — в нём оказался один элемент, сама строка /var/log/nginx/*.nosuch, и cp уедет с несуществующим файлом. shopt -s nullglob заставляет пустой glob разворачиваться в ноль элементов.Сравнить вывод двух команд без временных файлов
diff <(ls -1 dir1) <(ls -1 dir2)
<(...) подставляет путь вида /dev/fd/63, за которым стоит обычный pipe — проверил через ls -l. Нюанс: код возврата команды внутри скобок теряется, diff его не увидит. И это только bash: в dash тот же синтаксис даёт Syntax error, так что для #!/bin/sh не годится.Задать дефолт и проверить обязательные переменные
: "${TIMEOUT:=30}"
: "${DB_USER:?не задана}"
Нюанс: двоеточие в
:? обязательно. Вариант ${DB_USER?...} из подборок срабатывает только когда переменная не объявлена вовсе — пустую строку он пропускает, и скрипт идёт дальше с пустым логином. С :? тот же случай падает с кодом 127. То же и с :-: он подставляет дефолт, но не присваивает, переменная остаётся пустой.Собрать тайминги шагов скрипта
PS4='+ ${EPOCHREALTIME} '
set -x
Нюанс: в подборках сюда пишут
PS4='+ $(date "+%s.%N") => ' — и это форк date на каждую строку трассировки, в посте про избавление от форков. Встроенная EPOCHREALTIME даёт то же время с микросекундами и без единого процесса.А что вы чаще выносите из скриптов — cut и awk или всё-таки оставляете, потому что читается понятнее?
#Linux #Bash #Shell #Scripting #DevOps
👍4🔥1
Собрать дерево каталогов одной строкой и не получить папку с фигурными скобками в имени.
Создать вложенную структуру
Нюанс: раскрытие скобок — фича bash, а не mkdir. В
Если скрипт начинается с
Вернуться в предыдущий каталог
Нюанс:
Ходить по каталогам стеком
Нюанс: лишний
Пройти сквозь симлинк
Проверил на своём симлинке: обычный
Снести пустую цепочку каталогов
Поднимается снизу вверх, пока каталоги пустые. Нюанс: наткнувшись на непустой, останавливается с
А вы по дереву каталогов ходите
#Linux #Bash #Terminal #Scripting #DevOps
Создать вложенную структуру
mkdir -p project/src/{configs,utils,tests}
Нюанс: раскрытие скобок — фича bash, а не mkdir. В
sh строка отработает буквально, создав каталог с именем {configs,utils,tests} — проверил, ошибки при этом никакой. То же будет от пробела после запятой и от одного элемента без запятой: {only} останется как есть.Если скрипт начинается с
#!/bin/sh, скобки не использовать.Вернуться в предыдущий каталог
cd -
Нюанс:
cd - печатает путь в stdout. В скрипте это мусор в выводе, а $(cd -) вообще бесполезен — подстановка уходит в подоболочку, и рабочий каталог самого скрипта не меняется. Для скриптов тише так:
cd "$OLDPWD"
Ходить по каталогам стеком
pushd /var/log >/dev/null
popd >/dev/null
Нюанс: лишний
popd возвращает directory stack empty и код 1. Под set -e скрипт на этом падает — а такое легко получить, если между pushd и popd стоит выход по ошибке. Перенаправление в /dev/null тоже нужно: обе команды печатают содержимое стека.Пройти сквозь симлинк
cd -P /var/run
Проверил на своём симлинке: обычный
cd оставляет PWD равным /tmp/dd/link, с -P он становится /tmp/dd/real. Нюанс не в самом переходе, а в том, что будет дальше. Из link/sub команда cd .. вернёт в link, а cd -P .. — в real. Скрипт, который ходит относительными путями через симлинк, легко уедет не туда. Заодно pwd -P показывает физический путь, когда pwd показывает логический.Снести пустую цепочку каталогов
rmdir -p a/b/c
Поднимается снизу вверх, пока каталоги пустые. Нюанс: наткнувшись на непустой, останавливается с
Directory not empty — но то, что успел удалить ниже, уже удалено. Возврата нет, так что для глубоких цепочек лучше сначала посмотреть find a -type d -empty.А вы по дереву каталогов ходите
pushd или всё-таки алиасами и cd -?#Linux #Bash #Terminal #Scripting #DevOps
👍6