Вчера в комментариях к заметке со скриптом речь зашла про шебанг (shebang). Слово какое-то непонятное. Я первые года и Unix админил, и скрипты писал, и слова такого не знал, пока случайно не услышал.
Шебанг - это то, с чего начинается практически любой скрипт:
или так
Интуитивно и так было понятно, для чего это. Конструкцию с
Хотя указывать его можно не только так. Но абсолютно во всех дистрибутивах, с которыми я работал, по
Тем не менее, шебанг можно указать и более точно без привязки к конкретному пути в файловой системе:
Расположение bash будет взято из окружения, в котором будет запускаться скрипт. Так писать дольше, поэтому я такую конструкцию не использую.
Вообще, шебанг просто помогает понять, в какой оболочке запускать скрипт. Если его не писать, то эту оболочку придётся явно указывать при запуске скрипта:
А если не указать явно, то будет использована оболочка по умолчанию. Большая часть скриптов, с которыми я работаю, успешно отработает и в sh, и в bash. Именно эти оболочки наиболее распространены, остальное экзотика для серверов. Есть ещё dash, но, насколько я помню, она полностью совместима с sh.
В шебанге можно указать какие-то нюансы интерпретатора. В основном это актуально для python. Он как минимум может быть разных версий на одной и той же системе. Особенно это было актуально во времена перехода с python2 на python3. Когда был только python2 в шебангах могли указать python и скрипт выполнялся 2-й версией, так как именно она была в системе по умолчанию. Когда в системах стала появляться 3-я версия, для старых скриптов надо было отдельно ставить 2-ю и явно её указывать, либо редактируя шебанги в скриптах, либо запуская нужную версию явно:
Из экзотического применения шебангов можно привести примеры с awk или ansible:
И awk, и ansible-playbook являются интерпретаторами кода, так что для простого и быстрого запуска скриптов, написанных для них, можно использовать соответствующие шебанги, чтобы сразу запускать скрипт по аналогии с башем:
На практике я такое применение ни разу не встречал, хотя почему бы и нет. Но лично я всегда всё, что не bash, явно указываю в консоли. Это актуально и для php, код которого не так уж и редко приходится исполнять в консоли сервера.
Строки с шебангом могут содержать дополнительные аргументы, которые передаются интерпретатору (см. пример для awk -f выше). Однако, обработка аргументов может различаться, для переносимости лучше использовать только один аргумент без пробелов внутри. Теоретически это можно обойти в env, но на практике я не проверял. Увидел сам вчера в комментариях:
#bash
Шебанг - это то, с чего начинается практически любой скрипт:
#!/bin/bash
или так
#!/bin/sh
Интуитивно и так было понятно, для чего это. Конструкцию с
sh
я использовал, когда работал с FreeBSD. Перейдя на Linux, стал использовать bash
. Причём именно в таком виде:#!/bin/bash
Хотя указывать его можно не только так. Но абсолютно во всех дистрибутивах, с которыми я работал, по
/bin/bash
был именно bash либо в явном виде, либо символьной ссылкой на него. Так что если не хотите лишний раз забивать себе голову новой информацией, то пишите так же. Вероятность, что что-то пойдёт не так, очень мала. У меня ни разу за всю мою карьеру с таким шебангом проблем на Linux с bash скриптами не было. Исключение - контейнеры. Там отсутствие bash - обычное дело. Но там тогда и скрипты не будут нужны.Тем не менее, шебанг можно указать и более точно без привязки к конкретному пути в файловой системе:
#!/usr/bin/env bash
Расположение bash будет взято из окружения, в котором будет запускаться скрипт. Так писать дольше, поэтому я такую конструкцию не использую.
Вообще, шебанг просто помогает понять, в какой оболочке запускать скрипт. Если его не писать, то эту оболочку придётся явно указывать при запуске скрипта:
# bash script.sh
А если не указать явно, то будет использована оболочка по умолчанию. Большая часть скриптов, с которыми я работаю, успешно отработает и в sh, и в bash. Именно эти оболочки наиболее распространены, остальное экзотика для серверов. Есть ещё dash, но, насколько я помню, она полностью совместима с sh.
В шебанге можно указать какие-то нюансы интерпретатора. В основном это актуально для python. Он как минимум может быть разных версий на одной и той же системе. Особенно это было актуально во времена перехода с python2 на python3. Когда был только python2 в шебангах могли указать python и скрипт выполнялся 2-й версией, так как именно она была в системе по умолчанию. Когда в системах стала появляться 3-я версия, для старых скриптов надо было отдельно ставить 2-ю и явно её указывать, либо редактируя шебанги в скриптах, либо запуская нужную версию явно:
# python2 script.py
Из экзотического применения шебангов можно привести примеры с awk или ansible:
#!/usr/bin/awk -f
#!/usr/bin/env ansible-playbook
И awk, и ansible-playbook являются интерпретаторами кода, так что для простого и быстрого запуска скриптов, написанных для них, можно использовать соответствующие шебанги, чтобы сразу запускать скрипт по аналогии с башем:
# ./my-playbook.yaml
На практике я такое применение ни разу не встречал, хотя почему бы и нет. Но лично я всегда всё, что не bash, явно указываю в консоли. Это актуально и для php, код которого не так уж и редко приходится исполнять в консоли сервера.
Строки с шебангом могут содержать дополнительные аргументы, которые передаются интерпретатору (см. пример для awk -f выше). Однако, обработка аргументов может различаться, для переносимости лучше использовать только один аргумент без пробелов внутри. Теоретически это можно обойти в env, но на практике я не проверял. Увидел сам вчера в комментариях:
#!/usr/bin/env -S python3 -B -E -s
#bash
Пройдусь немного по важной теории по поводу работы в консоли bash. Я в разное время всё это затрагивал в заметках, но информация размазана через большие промежутки в публикациях. Имеет смысл повторить базу.
Покажу сразу очень наглядный пример:
В первом случае ключ не сработал, а во втором сработал, хотя запускал вроде бы одно и то же. А на самом деле нет. В первом примере я запустил echo из состава оболочки bash, а во втором случае - это бинарник в файловой системе. Это по факту разные программы. У них даже ключи разные.
Узнать, что конкретно мы запускаем, проще всего через type:
В первом случае прямо указано, что echo - встроена в оболочку.
И ещё один очень характерный пример:
Очень часто ls это не утилита ls, а алиас с дополнительными параметрами.
Когда вы вводите команду в терминал, происходит следующее:
1️⃣ Проверяются алиасы. Если команда будет там найдена, то поиск остановится и она исполнится.
2️⃣ Далее команда проверяется, встроена в ли она в оболочку, или нет. Если встроена, то выполнится именно она.
3️⃣ Только теперь идёт поиск бинарника в директориях, определённых в
У последнего варианта тоже есть свои нюансы. У вас может быть несколько исполняемых файлов в разных директориях с одинаковым именем. Ситуация нередкая. Можно столкнуться при наличии разных версий python или php в системе. Поиск бинарника ведётся по порядку следования этих директорий в переменной слева направо.
Что раньше будет найдено в директориях, определённых в этой строке, то и будет исполнено.
И ещё важный нюанс по этой теме. Есть привычные команды из оболочки, которых нет в бинарниках. Например, cd.
В выводе последней команды пусто, то есть бинарника
А вот если вы cd используете в юните systemd, то ничего не заработает:
Вот так работать не будет. Systemd не будет запускать автоматом оболочку. Надо это явно указать:
То есть либо явно указывайте bash, либо запускайте скрипт, где bash будет прописан в шебанге.
❗️В связи с этим могу дать совет, который вам сэкономит кучу времени на отладке. Всегда и везде в скриптах, в кронах, в юнитах systemd и т.д. пишите полные пути до бинарников. Команда, в зависимости от пользователя, прав доступа и многих других условий, может быть запущена в разных оболочках и окружениях. Чтобы не было неожиданностей, пишите явно, что вы хотите запустить.
#bash #terminal
Покажу сразу очень наглядный пример:
# echo --version
--version
# /usr/bin/echo --version
echo (GNU coreutils) 9.1
В первом случае ключ не сработал, а во втором сработал, хотя запускал вроде бы одно и то же. А на самом деле нет. В первом примере я запустил echo из состава оболочки bash, а во втором случае - это бинарник в файловой системе. Это по факту разные программы. У них даже ключи разные.
Узнать, что конкретно мы запускаем, проще всего через type:
# type echo
echo is a shell builtin
# type /usr/bin/echo
/usr/bin/echo is /usr/bin/echo
В первом случае прямо указано, что echo - встроена в оболочку.
И ещё один очень характерный пример:
# type ls
ls is aliased to `ls --color=auto'
Очень часто ls это не утилита ls, а алиас с дополнительными параметрами.
Когда вы вводите команду в терминал, происходит следующее:
1️⃣ Проверяются алиасы. Если команда будет там найдена, то поиск остановится и она исполнится.
2️⃣ Далее команда проверяется, встроена в ли она в оболочку, или нет. Если встроена, то выполнится именно она.
3️⃣ Только теперь идёт поиск бинарника в директориях, определённых в
$PATH
.У последнего варианта тоже есть свои нюансы. У вас может быть несколько исполняемых файлов в разных директориях с одинаковым именем. Ситуация нередкая. Можно столкнуться при наличии разных версий python или php в системе. Поиск бинарника ведётся по порядку следования этих директорий в переменной слева направо.
# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Что раньше будет найдено в директориях, определённых в этой строке, то и будет исполнено.
И ещё важный нюанс по этой теме. Есть привычные команды из оболочки, которых нет в бинарниках. Например, cd.
# type cd
cd is a shell builtin
# which cd
В выводе последней команды пусто, то есть бинарника
cd
нет. Если вы будете использовать cd в скриптах, то проблем у вас не будет, так как там обычно в шебанге указан интерпретатор. Обычно это bash или sh, и там cd присутствует.А вот если вы cd используете в юните systemd, то ничего не заработает:
ExecStart=cd /var/www/ ....... && .........
Вот так работать не будет. Systemd не будет запускать автоматом оболочку. Надо это явно указать:
ExecStart=/usr/bin/bash -с "cd /var/www/ ......."
То есть либо явно указывайте bash, либо запускайте скрипт, где bash будет прописан в шебанге.
❗️В связи с этим могу дать совет, который вам сэкономит кучу времени на отладке. Всегда и везде в скриптах, в кронах, в юнитах systemd и т.д. пишите полные пути до бинарников. Команда, в зависимости от пользователя, прав доступа и многих других условий, может быть запущена в разных оболочках и окружениях. Чтобы не было неожиданностей, пишите явно, что вы хотите запустить.
#bash #terminal
На всех серверах на базе Linux, а раньше и не только Linux, которые настраиваю и обслуживаю сам, изменяю параметры хранения истории команд, то есть history. Настройки обычно добавляю в файл
✅ Для того, чтобы сразу же сохранять в историю введённую команду, использую переменную bash - PROMPT_COMMAND. Содержимое этой переменной выполняется как обычная команда Bash непосредственно перед тем, как Bash отобразит приглашение. Соответственно, команда
✅ Сохранение метки времени вместе с самой командой и вывод её в определённом формате (2024-09-25 16:39:30):
✅ Увеличение числа строк в файле с историей. По умолчанию хранится вроде бы только 500 последних команд, более старые удаляются. Я увеличиваю этот размер до 10000 строк. Ни разу не было, чтобы этого не хватило:
✅ Некоторые команды не сохраняю в истории, так как они не представляют какой-то ценности, только отвлекают и занимают место. Вы можете свой список таких команд вести:
✅ Если я не хочу, чтобы команда попала в историю, то ставлю в консоли перед ней пробел. За это поведение отвечает соответствующий параметр:
Для применения настроек можно выполнить:
Посмотреть свои применённые параметры для истории можно вот так:
Если вы хотите, чтобы эти параметры применялись для всех пользователей сервера, то создайте отдельный файл с настройками, к примеру,
❗️Для поиска по истории нажмите сочетание клавиш Ctrl+r и начните вводить команду. Для перебора множественных совпадений продолжайте нажимать Ctrl+r, пока не найдёте то, что ищите. Я лично привык просто грепать, а не искать в истории:
Тут сразу всё перед глазами, можно быстро либо найти, то, что надо, либо скопировать команду.
⚡️Расскажу про один нюанс, связанный HISTIGNORE, который не раз меня подставлял. У меня в исключениях, к примеру, есть команда htop. Она в историю не попадает. Бывало такое, что я перезагружал сервер командой reboot. Потом загружался и первым делом вводил команду htop, что-то смотрел, закрывал htop. Потом нужно было запустить htop снова. Я на автомате нажимаю стрелку вверх, чтобы запустить последнюю команду, там выскакивает reboot, потому что htop не сохранился, и я тут же жму enter. И сокрушаюсь, что на автомате выполнил не ту команду. Реально много раз на это попадался, правда без последствий. В основном это во время какой-то отладки бывает, там и так перезагрузки идут.
#linux #terminal #bash
🦖 Selectel — дешёвые и не очень дедики с аукционом!
~/.bashrc
. Постоянно обращаюсь к истории команд, поэтому стараюсь, чтобы они туда попадали и сохранялись. Покажу свои привычные настройки:✅ Для того, чтобы сразу же сохранять в историю введённую команду, использую переменную bash - PROMPT_COMMAND. Содержимое этой переменной выполняется как обычная команда Bash непосредственно перед тем, как Bash отобразит приглашение. Соответственно, команда
history -a
сохраняет историю команд этого сеанса в файл с историей.PROMPT_COMMAND='history -a'
✅ Сохранение метки времени вместе с самой командой и вывод её в определённом формате (2024-09-25 16:39:30):
export HISTTIMEFORMAT='%F %T '
✅ Увеличение числа строк в файле с историей. По умолчанию хранится вроде бы только 500 последних команд, более старые удаляются. Я увеличиваю этот размер до 10000 строк. Ни разу не было, чтобы этого не хватило:
export HISTSIZE=10000
✅ Некоторые команды не сохраняю в истории, так как они не представляют какой-то ценности, только отвлекают и занимают место. Вы можете свой список таких команд вести:
export HISTIGNORE="ls:history:w:htop:pwd:top:iftop"
✅ Если я не хочу, чтобы команда попала в историю, то ставлю в консоли перед ней пробел. За это поведение отвечает соответствующий параметр:
export HISTCONTROL=ignorespace
Для применения настроек можно выполнить:
# source ~/.bashrc
Посмотреть свои применённые параметры для истории можно вот так:
# export | grep -i hist
Если вы хотите, чтобы эти параметры применялись для всех пользователей сервера, то создайте отдельный файл с настройками, к примеру,
history.sh
и положите его в директорию /etc/profile.d
. Скрипты из этой директории выполняются при запуске шелла пользователя. ❗️Для поиска по истории нажмите сочетание клавиш Ctrl+r и начните вводить команду. Для перебора множественных совпадений продолжайте нажимать Ctrl+r, пока не найдёте то, что ищите. Я лично привык просто грепать, а не искать в истории:
# history | grep 'apt install'
Тут сразу всё перед глазами, можно быстро либо найти, то, что надо, либо скопировать команду.
⚡️Расскажу про один нюанс, связанный HISTIGNORE, который не раз меня подставлял. У меня в исключениях, к примеру, есть команда htop. Она в историю не попадает. Бывало такое, что я перезагружал сервер командой reboot. Потом загружался и первым делом вводил команду htop, что-то смотрел, закрывал htop. Потом нужно было запустить htop снова. Я на автомате нажимаю стрелку вверх, чтобы запустить последнюю команду, там выскакивает reboot, потому что htop не сохранился, и я тут же жму enter. И сокрушаюсь, что на автомате выполнил не ту команду. Реально много раз на это попадался, правда без последствий. В основном это во время какой-то отладки бывает, там и так перезагрузки идут.
#linux #terminal #bash
Please open Telegram to view this post
VIEW IN TELEGRAM
Пробую в ежедневной рутине использовать в качестве помощника ИИ. В данном случае я имею ввиду Openchat-3.5-0106, которым пользуюсь. Как я уже отмечал ранее, там, где нужно выдать какую-то справочную информацию или скомбинировать известную информацию, он способен помочь. А где надо немного подумать и что-то написать новое, то уже не очень.
У меня возникла простая задача. В запросах к API на выборку данных нужно указывать год, номер месяца, дни месяца. Это нетрудно сделать с помощью bash. Решил сразу задать вопрос боту и посмотреть результат. Сформулировал запрос так:
Напиши bash скрипт, который будет показывать текущую дату, номер текущего месяца, текущий год, первый и последний день текущего месяца, прошлого месяца и будущего месяца.
Получил на выходе частично работающий скрипт. Текущий год, месяц и дату показывает, первые дни нет. Вот скрипт, который предложил ИИ.
Гугл первой же ссылкой дал правильный ответ на stackexchange. Идею я понял, немного переделал скрипт под свои потребности. То есть сделал сразу себе мини-шпаргалку, заготовку. Получилось вот так:
Можете себе забрать, если есть нужда работать с датами. Иногда это нужно для работы с бэкапами, которые по маске с датой создаются. Директории удобно по месяцам и годам делать. Потом оттуда удобно забирать данные или чистить старое. То же самое с API. К ним часто нужно указывать интервал запроса. Года, месяцы, даты чаще всего отдельными переменными идут.
Проверять подобные скрипты удобно с помощью faketime:
Я в своей деятельности пока не вижу какой-то значимой пользы от использования ИИ. Не было так, что вот задал ему вопрос и получил готовый ответ.
#bash #script
У меня возникла простая задача. В запросах к API на выборку данных нужно указывать год, номер месяца, дни месяца. Это нетрудно сделать с помощью bash. Решил сразу задать вопрос боту и посмотреть результат. Сформулировал запрос так:
Напиши bash скрипт, который будет показывать текущую дату, номер текущего месяца, текущий год, первый и последний день текущего месяца, прошлого месяца и будущего месяца.
Получил на выходе частично работающий скрипт. Текущий год, месяц и дату показывает, первые дни нет. Вот скрипт, который предложил ИИ.
Гугл первой же ссылкой дал правильный ответ на stackexchange. Идею я понял, немного переделал скрипт под свои потребности. То есть сделал сразу себе мини-шпаргалку, заготовку. Получилось вот так:
#!/bin/bash
CUR_DATE=$(date "+%F")
CUR_YEAR=$(date "+%Y")
CUR_MONTH=$(date "+%m")
DAY_CUR_START_FULL=$(date +%Y-%m-01)
DAY_CUR_START=$(date "+%d" -d $(date +'%Y-%m-01'))
DAY_CUR_END_FULL=$(date -d "`date +%Y%m01` +1 month -1 day" +%Y-%m-%d)
DAY_CUR_END=$(date "+%d" -d "$DAY_CUR_START_FULL +1 month -1 day")
LAST_MONTH_DATE=$(date "+%F" -d "$(date +'%Y-%m-01') -1 month")
LAST_MONTH_YEAR=$(date "+%Y" -d "$(date +'%Y-%m-01') -1 month")
LAST_MONTH=$(date "+%m" -d "$(date +'%Y-%m-01') -1 month")
DAY_LAST_START=$(date "+%d" -d "$(date +'%Y-%m-01') -1 month")
DAY_LAST_START_FULL=$(date "+%Y-%m-01" -d "$(date +'%Y-%m-01') -1 month")
DAY_LAST_END=$(date "+%d" -d "$LAST_MONTH_DATE +1 month -1 day")
DAY_LAST_END_FULL=$(date -d "$LAST_MONTH_DATE +1 month -1 day" +%Y-%m-%d)
echo -e "\n"
echo "Полная текущая дата: $CUR_DATE"
echo "Текущий год: $CUR_YEAR"
echo "Номер текущего месяца: $CUR_MONTH"
echo "Первый день этого месяца: $DAY_CUR_START_FULL, $DAY_CUR_START"
echo "Последний день этого месяца: $DAY_CUR_END_FULL, $DAY_CUR_END"
echo -e "\n"
echo "Начало прошлого месяца: $LAST_MONTH_DATE"
echo "Год прошлого месяца: $LAST_MONTH_YEAR"
echo "Номер прошлого месяца: $LAST_MONTH"
echo "Первый день прошлого месяца: $DAY_LAST_START_FULL, $DAY_LAST_START"
echo "Последний день прошлого месяца: $DAY_LAST_END_FULL, $DAY_LAST_END"
echo -e "\n"
Можете себе забрать, если есть нужда работать с датами. Иногда это нужно для работы с бэкапами, которые по маске с датой создаются. Директории удобно по месяцам и годам делать. Потом оттуда удобно забирать данные или чистить старое. То же самое с API. К ним часто нужно указывать интервал запроса. Года, месяцы, даты чаще всего отдельными переменными идут.
Проверять подобные скрипты удобно с помощью faketime:
# apt install faketime
# faketime '2024-01-05' bash date.sh
Я в своей деятельности пока не вижу какой-то значимой пользы от использования ИИ. Не было так, что вот задал ему вопрос и получил готовый ответ.
#bash #script
Небольшая практическая шпаргалка, которая с большой долей вероятности пригодится, если работаете с текстом в консоли Linux или каких-то других редакторах. Я взял для примера VSCode и Notepad++, с которыми сам работаю. Последний по старой памяти. Особой нужды в нём нет, но он, как и Total Commander, навечно прописался в моём компьютере.
Добавить в конец каждой строки переход на новую строку
🟡 С помощью sed:
Заменили анкор
🟡 С помощью VSCode:
Открываем окно поиска и замены через Ctrl + H. В строке поиска пишем
🟡 С помощью Notepad++:
Открываем окно поиска через Ctrl + F, переходим на вкладку замена. Ищем
По аналогии можно добавить в конец любой другой символ. Я взял переход на новую строку как наиболее сложный вариант замены.
Добавить символы в начало каждой строки
🟢 С помощью sed:
Добавили фразу +7 в начало каждой строки.
🟢 С помощью VSCode:
Открываем окно поиска и замены через Ctrl + H. В строке поиска пишем
🟢 С помощью Notepad++:
Открываем окно поиска через Ctrl + F, переходим на вкладку замена. Ищем
Оба упомянутых анкора
Отобразили конфиг без строк, начинающихся с # , ; и пустых строк.
Кстати, я первый вопрос с sed решил задать chatgpt. И на удивление, он мне дал неправильный ответ на такой простой вопрос. Добавил лишнее экранирование. Не понимаю, как он некоторым программировать помогает или шаблоны для Zabbix пишет. Я как не обращусь к нему, регулярно получаю ошибки. Если ты не в теме, то эти ошибки сложно исправлять.
По этой теме у меня уже была ранее заметка, только с акцентом на grep, а не изменение данных. Если не видели, рекомендую посмотреть и сохранить. Там много примеров из моей практики.
❗️Если заметка вам полезна, не забудьте 👍 и забрать в закладки.
#bash
Добавить в конец каждой строки переход на новую строку
🟡 С помощью sed:
# sed 's/$/\n/' file.txt > new_file.txt
Заменили анкор
$
, означающий конец строки на специальный символ \n
- новая строка.🟡 С помощью VSCode:
Открываем окно поиска и замены через Ctrl + H. В строке поиска пишем
$
и жмём кнопку .*, что означает использование регулярных выражений. В качестве замены указываем /n
и жмём заменить всё.🟡 С помощью Notepad++:
Открываем окно поиска через Ctrl + F, переходим на вкладку замена. Ищем
\r
, заменяем на \n
. Режим поиска ставим Расширенный. По аналогии можно добавить в конец любой другой символ. Я взял переход на новую строку как наиболее сложный вариант замены.
Добавить символы в начало каждой строки
🟢 С помощью sed:
# sed 's/^/+7/' file.txt > new_file.txt
Добавили фразу +7 в начало каждой строки.
🟢 С помощью VSCode:
Открываем окно поиска и замены через Ctrl + H. В строке поиска пишем
^
и жмём кнопку .*, что означает использование регулярных выражений. В качестве замены указываем +7
и жмём заменить всё.🟢 С помощью Notepad++:
Открываем окно поиска через Ctrl + F, переходим на вкладку замена. Ищем
^
, заменяем на +7
. Режим поиска ставим Регулярные выражения.Оба упомянутых анкора
^$
вместе означают пустую строку. Можно так же заменять или удалять пустые строки. Актуально для больших конфигов, которые хочется почистить. Примерно так:# sed '/^#\|^;\|^$/d' php.ini
# grep -E -v '^#|^;|^$' php.ini
Отобразили конфиг без строк, начинающихся с # , ; и пустых строк.
Кстати, я первый вопрос с sed решил задать chatgpt. И на удивление, он мне дал неправильный ответ на такой простой вопрос. Добавил лишнее экранирование. Не понимаю, как он некоторым программировать помогает или шаблоны для Zabbix пишет. Я как не обращусь к нему, регулярно получаю ошибки. Если ты не в теме, то эти ошибки сложно исправлять.
По этой теме у меня уже была ранее заметка, только с акцентом на grep, а не изменение данных. Если не видели, рекомендую посмотреть и сохранить. Там много примеров из моей практики.
❗️Если заметка вам полезна, не забудьте 👍 и забрать в закладки.
#bash
Для тех, кому в консоли достаточно обычного bash, могу порекомендовать ресурс, с помощью которого можно быстро настроить себе prompt. Для тех, кто не знает, что это такое, поясню. Promt – это информация, которая отображается в командной строке перед полем с вводом своей команды. Его называют приглашением командной строки.
Стандартный promt чаще всего
Из того, что обычно добавляют, отмечу следующие вещи:
- отображение IP адреса сервера
- подсветка промта разными цветами на разных серверах
- подсветка промта красным цветом при работе от root
- вывод времени
Немного поигрался в конструкторе и собрал следующий промт:
Теперь эту команду надо добавить в
В данном случае мы настроили promt у конкретного пользователя. Я цвет имени пользователя сделал красным, потому что это root. Для остальных пользователей promt можно вообще не менять, либо задать индивидуальный. Общие же настройки для всех пользователей живут в системном файле
Если у вас какой-то прикольный и необычный promt, поделитесь, пожалуйста, информацией.
❗️Если заметка вам полезна, не забудьте 👍 и забрать в закладки.
#terminal #bash
Стандартный promt чаще всего
user@host-name:current-directory#
. С помощью сайта bash-prompt-generator.org можете легко его изменить, просто собрав как в конструкторе те элементы, что вам нужны. И тут же на сайте видно, как будет выглядеть приглашение командной строки. Из того, что обычно добавляют, отмечу следующие вещи:
- отображение IP адреса сервера
- подсветка промта разными цветами на разных серверах
- подсветка промта красным цветом при работе от root
- вывод времени
Немного поигрался в конструкторе и собрал следующий промт:
[username@hostname.com|192.168.1.100] 20:32:03 (~/bin)$ █
PROMPT_COMMAND='PS1_CMD1=$(ip route get 1.1.1.1 | awk -F"src " '"'"'NR == 1{ split($2, a," ");print a[1]}'"'"')'; PS1='[\[\e[38;5;196m\]\u\[\e[0m\]@\H|${PS1_CMD1}] \t (\[\e[4m\]\w\[\e[0m\])\$ '
Теперь эту команду надо добавить в
~/.bashrc
и применить изменения:# source ~/.bashrc
В данном случае мы настроили promt у конкретного пользователя. Я цвет имени пользователя сделал красным, потому что это root. Для остальных пользователей promt можно вообще не менять, либо задать индивидуальный. Общие же настройки для всех пользователей живут в системном файле
/etc/bash.bashrc
. Если у вас какой-то прикольный и необычный promt, поделитесь, пожалуйста, информацией.
❗️Если заметка вам полезна, не забудьте 👍 и забрать в закладки.
#terminal #bash
Небольшой практический совет во время отладки в консоли Linux. Иногда хочется узнать, в каком окружении работает то или иное приложение. Поти вся информация о процессах в Linux живёт в
Всё в одну строчку. Не воспринимается глазами вообще. Можно ещё вот так посмотреть:
Тоже не очень наглядно. Так как у нас консоль и bash, то вывод можно как угодно обрабатывать, чтобы было удобно. Проще всего взять
или то же самое, но немного по-другому:
Я уже болен cat-офилией и привык везде её использовать. Уже даже не пытаюсь переучиться. Вместо
На выходе получаем аккуратный список окружения процесса, где можно увидеть нужные нам нюансы быстрее и нагляднее, чем где-то в другом месте. И запоминать особо не надо, конструкция несложная. Главное ключ
❗️Если заметка вам полезна, не забудьте 👍 и забрать в закладки.
#linux #bash
/proc/<pid>
, в том числе и об его окружении. Посмотреть можно так:# cat /proc/816/environ
LANG=en_US.UTF-8PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/binHOME=/var/lib/zabbixLOGNAME=zabbixUSER=zabbixSHELL=/sbin/nologinCONFFILE=/etc/zabbix/zabbix_agentd.conf
Всё в одну строчку. Не воспринимается глазами вообще. Можно ещё вот так посмотреть:
# ps e -ww -p 816
Тоже не очень наглядно. Так как у нас консоль и bash, то вывод можно как угодно обрабатывать, чтобы было удобно. Проще всего взять
xargs
, так как у него есть ключ --null
, который позволяет разделять строку, используя разделителем так называемый NULL character. Я уже как-то раз писал про него. Иногда его удобно использовать, в том числе в find
с ключом -print0
.# cat /proc/816/environ | xargs --null --max-args=1
или то же самое, но немного по-другому:
# xargs --null --max-args=1 echo < /proc/816/environ
LANG=en_US.UTF-8
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
HOME=/var/lib/zabbix
LOGNAME=zabbix
USER=zabbix
SHELL=/sbin/nologin
CONFFILE=/etc/zabbix/zabbix_agentd.conf
Я уже болен cat-офилией и привык везде её использовать. Уже даже не пытаюсь переучиться. Вместо
grep
постоянно делаю cat | grep
. Вы выбирайте, что вам легче запоминается.На выходе получаем аккуратный список окружения процесса, где можно увидеть нужные нам нюансы быстрее и нагляднее, чем где-то в другом месте. И запоминать особо не надо, конструкция несложная. Главное ключ
--null
запомнить.❗️Если заметка вам полезна, не забудьте 👍 и забрать в закладки.
#linux #bash
Покажу небольшой bash трюк, который поможет грепнуть информацию, когда обычный способ не работает. Демонстрирую сразу на примере, с которым сам постоянно сталкиваюсь.
Вам нужно узнать, есть ли необходимый модуль в составе Nginx. По идее всё просто:
На выходе портянка, в которой глазами трудно что-то найти. Пробуем грепнуть:
Вообще ноль изменений. И причины тут на самом деле не одна, а сразу две:
1️⃣ nginx -V выводит информацию не в стандартный поток с данными stdout, с которым работает grep и прочие консольные утилиты, а в stderr;
2️⃣ все модули перечислены одной строкой, так что грепнуть её содержимое не получится.
Показываю решение обоих проблем:
Видим нужный нам модуль. Я сначала через
В принципе, можно обойтись без разбивки одной строки на несколько, так как grep скорее всего подсветит найденную фразу, но это зависит от различных настроек. Где-то может и не подсветить. Если всё же разбить, то будет нагляднее.
❗️Если заметка вам полезна, не забудьте 👍 и забрать в закладки.
#bash
Вам нужно узнать, есть ли необходимый модуль в составе Nginx. По идее всё просто:
# nginx -V
На выходе портянка, в которой глазами трудно что-то найти. Пробуем грепнуть:
# nginx -V | grep http_realip_module
Вообще ноль изменений. И причины тут на самом деле не одна, а сразу две:
Показываю решение обоих проблем:
# nginx -V 2>&1 | tr ' ' '\n' | grep http_realip_module
--with-http_realip_module
Видим нужный нам модуль. Я сначала через
2>&1
направил поток stderr в stdout, чтобы с ним можно было работать консольными утилитами, а затем с помощью tr
заменил все пробелы символами перехода на новую строку \n
. В итоге у нас весь вывод nginx -V разбился на отдельные фразы, каждая в новой строке и после этого успешно грепнулся.В принципе, можно обойтись без разбивки одной строки на несколько, так как grep скорее всего подсветит найденную фразу, но это зависит от различных настроек. Где-то может и не подсветить. Если всё же разбить, то будет нагляднее.
❗️Если заметка вам полезна, не забудьте 👍 и забрать в закладки.
#bash
Please open Telegram to view this post
VIEW IN TELEGRAM
Искал на днях материалы на тему Playwright. Это фреймворк для веб тестирования и автоматизации, более современный аналог Selenium. Последний я немного учил, но он довольно замороченный, с полтычка не освоишь. Playwright показался немного попроще в каких-то базовых вещах.
Рассказать сегодня хотел не об этом. Я попал на сайт к какому-то девопсу, где были материалы по Playwright. Я немного походил по нему и набрёл на раздел DevTools. Он там собрал то ли свои, то ли просто open source инструменты для решения простых прикладных задач. Вроде ничего особенного, но некоторые вещи я просто не знал, что вообще существуют. Всегда их делал вручную.
Покажу сразу на примерах, что мне показалось полезным:
- Docker Run to Docker Compose Converter
Отправляем в форму однострочник с
- Docker Compose to Docker Run Converter
И соответственно в обратную сторону преобразование из docker compose в однострочник для
- Bash Command Formatter
Эта штука тоже очень понравилась. Она длинный однострочник разбивает на строки с переходами через \ То есть вот такую колбасу:
Нарезает на кусочки:
Я тоже всегда это вручную делал, особенно для публикации сюда. Можно упростить себе задачу.
- URL Extractor
Просто кидаешь сюда любой текст, а на выходе получаешь набор ссылок, если они в нём присутствуют.
Там много всяких конвертеров и анализаторов синтаксиса для json, yaml, toml, csv. Не стал обращать на них внимание, так как их существует десятки. Обычно просто в гугле ищут что-то подобное, когда надо преобразовать. Посмотрите список, может вам что-то ещё приглянётся. Меня впечатлили только эти четыре штуки.
#devops #docker #bash
Рассказать сегодня хотел не об этом. Я попал на сайт к какому-то девопсу, где были материалы по Playwright. Я немного походил по нему и набрёл на раздел DevTools. Он там собрал то ли свои, то ли просто open source инструменты для решения простых прикладных задач. Вроде ничего особенного, но некоторые вещи я просто не знал, что вообще существуют. Всегда их делал вручную.
Покажу сразу на примерах, что мне показалось полезным:
- Docker Run to Docker Compose Converter
Отправляем в форму однострочник с
docker run
и получаем файл для docker compose. Вроде мелочь, но я всегда это делал вручную. Не думал, что кому-то придёт в голову написать конвертер.- Docker Compose to Docker Run Converter
И соответственно в обратную сторону преобразование из docker compose в однострочник для
docker run
. Не припоминаю, чтобы мне приходилось такие преобразования делать, но в тему к первому упоминаю.- Bash Command Formatter
Эта штука тоже очень понравилась. Она длинный однострочник разбивает на строки с переходами через \ То есть вот такую колбасу:
curl -v --url "smtp://mail.server.ru:25" --mail-from "root@server.ru" --mail-rcpt "user@gmail.com" --user 'root@server.ru:password123' --upload-file ~/mail.txt
Нарезает на кусочки:
curl -v \
--url "smtp://mail.server.ru:25" \
--mail-from "root@server.ru" \
--mail-rcpt "user@gmail.com" \
--user 'root@server.ru:password123' \
--upload-file ~/mail.txt
Я тоже всегда это вручную делал, особенно для публикации сюда. Можно упростить себе задачу.
- URL Extractor
Просто кидаешь сюда любой текст, а на выходе получаешь набор ссылок, если они в нём присутствуют.
Там много всяких конвертеров и анализаторов синтаксиса для json, yaml, toml, csv. Не стал обращать на них внимание, так как их существует десятки. Обычно просто в гугле ищут что-то подобное, когда надо преобразовать. Посмотрите список, может вам что-то ещё приглянётся. Меня впечатлили только эти четыре штуки.
#devops #docker #bash
Существует удобный и функциональный инструмент для добавления интерактива в shell скрипты под названием Gum. Я посмотрел несколько примеров, в том числе на ютубе, как люди решают те или иные задачи с его помощью. Синтаксис очень простой, особо разбираться не надо. Можно сходу брать и писать скрипт.
Я для примера решил сделать поиск по директории с выводом топ 10 самых больших файлов, из которых можно какие-то выбрать и удалить. Сделал просто в лоб на bash – сформировал список, отправил его в gum и добавил действие для выбранных файлов:
Понял, что всё получилось и решил как-то это усложнить и сделать более удобным. Дай, думаю, попрошу Chatgpt что-то написать. На самом деле не рассчитывал на успех, так как это не особо популярный инструмент. Откуда ему взять навык написания скриптов для gum? Вряд ли их много в интернете можно найти.
Отправил ему адрес репозитория и попросил сделать 2 списка: один с самыми большими файлами, второй – с самыми старыми. Причём вывести их вместе на один экран, в списках отобразить размер файлов и их даты.
Задача не сильно сложная, но немного муторная, так как списки надо правильно сформировать, объединить, пункты выбора насытить дополнительной информацией в виде размера файлов и даты. Потом всё это надо очистить, чтобы передать на удаление только имя файла. Чтобы самому это сделать, надо потратить какое-то время.
Chatgpt меня удивил, когда практически сразу же выдал рабочее решение. Там были ошибки по части bash. Нужно было что-то экранировать, а что-то получше очистить. А вот в части непосредственно Gum он на удивление сразу же всё корректно оформил в соответствии с его возможностями. Я думал, что-то выдумает от себя нерабочее, но нет.
В итоге минут за 15-20 со всеми тестами я получил рабочий вариант скрипта. Реально, был очень удивлён. Не так давно его мучал конфигурациями Nginx, по которым море примеров в сети, но так и не добился того, что хотел. А тут какой-то Gum и сразу всё заработало.
☝️ Какое в итоге резюме. Gum – прикольная штука, которую можно приспособить под какие-то свои задачи. Например, выбор подключений по SSH, работа с ветками GIT, работа со списками файлов и т.д. Тут уж каждому своё. А второй момент – используйте ИИ для своих задач. Где-то он мимо советует, а где-то сразу рабочий вариант даёт. Причём в таких небольших прикладных задачах он нормально работает. На bash пишет уверенно. Есть проблемы, но поправить после него намного проще, чем написать самому, вспомнив все возможности и ключи консольных утилит.
⇨ Итоговый скрипт
Использовать:
❗️Если заметка вам полезна, не забудьте 👍 и забрать в закладки.
#bash #AI #script
Я для примера решил сделать поиск по директории с выводом топ 10 самых больших файлов, из которых можно какие-то выбрать и удалить. Сделал просто в лоб на bash – сформировал список, отправил его в gum и добавил действие для выбранных файлов:
#!/bin/bash
DIR="/tmp/backup"
files=$(find "$DIR" -type f -exec du -b {} + 2>/dev/null | sort -nr | head -n 10 | awk '{print $2}')
selected=$(echo "$files" | gum choose --no-limit)
delete=$(echo -e "$selected")
if [[ -z "$delete" ]]; then
echo "Ничего не выбрано."
exit 0
fi
gum confirm "Удалить выбранные файлы?" &&
echo "$delete" | xargs -d '\n' rm -f && echo "Выбранное удалено."
Понял, что всё получилось и решил как-то это усложнить и сделать более удобным. Дай, думаю, попрошу Chatgpt что-то написать. На самом деле не рассчитывал на успех, так как это не особо популярный инструмент. Откуда ему взять навык написания скриптов для gum? Вряд ли их много в интернете можно найти.
Отправил ему адрес репозитория и попросил сделать 2 списка: один с самыми большими файлами, второй – с самыми старыми. Причём вывести их вместе на один экран, в списках отобразить размер файлов и их даты.
Задача не сильно сложная, но немного муторная, так как списки надо правильно сформировать, объединить, пункты выбора насытить дополнительной информацией в виде размера файлов и даты. Потом всё это надо очистить, чтобы передать на удаление только имя файла. Чтобы самому это сделать, надо потратить какое-то время.
Chatgpt меня удивил, когда практически сразу же выдал рабочее решение. Там были ошибки по части bash. Нужно было что-то экранировать, а что-то получше очистить. А вот в части непосредственно Gum он на удивление сразу же всё корректно оформил в соответствии с его возможностями. Я думал, что-то выдумает от себя нерабочее, но нет.
В итоге минут за 15-20 со всеми тестами я получил рабочий вариант скрипта. Реально, был очень удивлён. Не так давно его мучал конфигурациями Nginx, по которым море примеров в сети, но так и не добился того, что хотел. А тут какой-то Gum и сразу всё заработало.
☝️ Какое в итоге резюме. Gum – прикольная штука, которую можно приспособить под какие-то свои задачи. Например, выбор подключений по SSH, работа с ветками GIT, работа со списками файлов и т.д. Тут уж каждому своё. А второй момент – используйте ИИ для своих задач. Где-то он мимо советует, а где-то сразу рабочий вариант даёт. Причём в таких небольших прикладных задачах он нормально работает. На bash пишет уверенно. Есть проблемы, но поправить после него намного проще, чем написать самому, вспомнив все возможности и ключи консольных утилит.
⇨ Итоговый скрипт
Использовать:
# ./cleanup-with-gum.sh /mnt/backup
❗️Если заметка вам полезна, не забудьте 👍 и забрать в закладки.
#bash #AI #script