BashMaster - канал под названием @bash_help предоставляет удобные консольные наработки на каждый день для разработчиков, девопсов и сисадминов. Если вы ищете полезные советы, трюки и решения проблем, связанных с работой в терминале, то этот канал идеально подходит для вас. Здесь вы найдете актуальные инструменты и рекомендации, которые помогут вам улучшить свои навыки в области консольного взаимодействия. Кроме того, канал предлагает рекламные возможности для тех, кто хочет продвигать свои продукты или услуги среди целевой аудитории разработчиков, девопсов и системных администраторов. Для размещения рекламы обращайтесь к @Kone4noVasya. Присоединяйтесь к каналу BashMaster и узнавайте новое о консольных наработках каждый день! Канал также доступен на бирже: https://telega.in/c/bash_help
10 Jan, 15:49
08 Jan, 10:10
#!/bin/bash
# Скрипт проверяет объём кэша в оперативной памяти и при превышении в 1Gb предлагает запустить очистку
cache=$(free -m | grep Mem | awk '{print $6}')
echo "Кэшированно $cacheМб"
if [ $cache -ge 1000 ]
then
echo "Кэш более одного гигабайта"
echo ""
read -p "Почистить кэш? Y/n: " ansver
case $ansver in
[y,Y])
echo "Для запуска скрипта очистки, введите пароль SUDO пользователя"
sudo echo "Было занято в кеше ОЗУ"
free -m
sync
echo 1 | sudo tee -a /proc/sys/vm/drop_caches
sync
echo 2 | sudo tee -a /proc/sys/vm/drop_caches
sync
echo 3 | sudo tee -a /proc/sys/vm/drop_caches
echo "Стало свободно в ОЗУ"
free -m;;
[n,N])
echo "Вы отказались от чистки кэша";;
esac
else
echo "Достаточно свободной памяти"
fi
07 Jan, 16:09
#!/bin/bash
# Дамп базы с заменой общего комплексного параметра --opt, где используется ключ --lock-tables на набор отдельных ключей, где вместо lock-tables используется --single-transaction
/usr/bin/mysqldump --add-drop-database --add-locks --create-options --disable-keys --extended-insert --single-transaction --quick --set-charset --routines --events --triggers --comments --quote-names --order-by-primary --hex-blob --databases database01 -u'userdb' -p'password' > /mnt/backup/sql/"$(date +%Y-%m-%d)"-database01.sql
# Из общего дампа вырезаю дамп только данных таблицы table01. Общий дамп тоже оставляю, потому что он нужен для других задач
/usr/bin/cat /mnt/backup/sql/"$(date +%Y-%m-%d)"-database01.sql | /usr/bin/awk '/LOCK TABLES `table01`/,/UNLOCK TABLES/' > /mnt/backup/sql/"$(date +%Y-%m-%d)"-table01.sql
# Сжимаю оба дампа
/usr/bin/gzip /mnt/backup/sql/"$(date +%Y-%m-%d)"-database01.sql
/usr/bin/gzip /mnt/backup/sql/"$(date +%Y-%m-%d)"-table01.sql
# Копирую дамп таблицы на второй сервер, аутентификация по ключам
/usr/bin/scp /mnt/backup/sql/"$(date +%Y-%m-%d)"-table01.sql.gz [email protected]:/tmp
# Выполняю на втором сервере ряд заданий в рамках ssh сессии: распаковываю дамп таблицы, очищаю таблицу на этом сервере, заливаю туда данные из дампа
/usr/bin/ssh [email protected] '/usr/bin/gunzip /tmp/"$(date +%Y-%m-%d)"-table01.sql.gz && /usr/bin/mysql -e "delete from database01.table01; use database01; source /tmp/"$(date +%Y-%m-%d)"-table01.sql;"'
# Удаляю дамп
/usr/bin/ssh [email protected] 'rm /tmp/"$(date +%Y-%m-%d)"-table01.sql'
07 Jan, 12:51
06 Jan, 10:17
06 Jan, 07:04
03 Jan, 14:24
bash hst-install.sh.
bash hst-install.sh -f -y no -e [email protected] -p p4ssw0rd -s hostname.domain.tld
bash hst-install.sh -h
03 Jan, 07:29
31 Dec, 14:08
31 Dec, 09:05
# find /var/www/site -type f -mtime -30 ! -mtime -1 -printf '%TY-%Tm-%Td %TT %p\n' | sort -r
# cat ~/.bash_history
# cat ~/.mysql_history
# sudo -u postgres psql
# \s
# dpkg —verify
# rpm -Va
# ss -tulnp | column -t
# ss -ntu
# ps axf
31 Dec, 05:59
30 Dec, 16:25
30 Dec, 12:45
28 Dec, 16:05
26 Dec, 11:45
cd
— c
cd
— c 2
test
, где «name» — имя папки, а не полный путь — c test
.26 Dec, 08:30
25 Dec, 13:35
PS1
. Согласно странице man Bash, PS1
представляет собой основную строку, которая отображается, когда оболочка готова к чтению команды.PS1
состоит из нескольких специальных символов с обратным слэшем, значение которых указано в разделе PROMPTING на странице руководства.PS1
в нашей системе (в вашем случае результат может выглядеть иначе):
$ echo $PS1
\u: имя пользователя
(текущего пользователя).\h: имя хоста
до первой точки (.).\W: базовое имя
текущего рабочего каталога, с $HOME
(сокращенно тильдой ~).\$:
если текущий пользователь root, пропишите «#
», в противном случае «$
«.\!
если мы хотим отобразить номер истории текущей команды или \H
, если мы хотим отобразить полное доменное имя вместо короткого имени сервера.PS1="[\u@\H \W \!]\$"
\e
в начале и m
в конце, чтобы указать, что далее прописана последовательность цветов.PS1="\e[40;11;32m[\u@\h \W]$ "
~/.bashrc
или~/.bash_profile
в зависимости от вашего дистрибутива:PS1="\e[40;11;32m[\u@\h \W]$ "
25 Dec, 10:31
24 Dec, 10:15
/bin
или /usr/bin
. Также к внешним командам можно отнести и исполняемые файлы.$PATH
содержит перечень путей, разделенных двоеточиями, по которым хранятся команды этого типа. Чтобы найти нужную утилиту, ОС ищет исполняемый файл в каталогах в порядке, установленном переменной. Если находит, запускает на выполнение. Если нет — проверяет следующие директории. Чтобы просмотреть текущее значение $PATH
:echo $PATH
/bin
:ls /bin/
apt
, awk
, mount
, mkdir
и т. п.alias
alias la='ls -A'
:alias
— указывает, что команда является псевдонимом;la
— название псевдонима;ls -A
— полная команда, которую заменяют псевдонимом.alias name='full_command'
~/.bashrc
и впишите новый в разделе псевдонимов, сохраните файл. Он будет автоматически загружен при запуске следующего сеанса терминала.!
— логическое НЕ;case
, esac
— используются для создания многосторонних условных конструкций;coproc
— создает со-процесс;do
, done
— используются для построения циклов;elif
— часть конструкции if-else;if
, else
— составные части конструкции if-else;for
, in
— используются для создания цикла for;function
— объявляет функции в скриптах;fi
— указывает на конец внутреннего оператора if;select
— генерирует меню из списка элементов;then
— используется для разделения условия и команд, которые будут выполнены, если условие окажется истинным;until
— используется для создания цикла, который продолжает выполняться до тех пор, пока не будет выполнено определенное условие;while
— создает цикл while;{
, }
— группируют команды вместе и создают командный блок;time
— используется для определения времени выполнения команды;[[
, ]]
— используются для проверки условных выражений.function_name() {
command1
command2
...
}
function_name
123.sh
, в котором напишем функцию для выполнения команд ls
и ls -a
. С помощью утилиты chmod
разрешим выполнение файла для его владельца (u+x)./123.sh
sh 123.sh
pwd
— выводит на экран название текущего каталога;cd
— позволяет переходить между каталогами;echo
— выводит на экран заданную строку текста.help
type
с ее названием в качестве аргумента. К примеру — type pwd
24 Dec, 07:15
23 Dec, 09:54
Iperf
- это инструмент для измерения и настройки производительности сети. Это кроссплатформенный инструмент, который может производить стандартизированные измерения производительности для любой сети. Iperf
обладает клиентскими и серверными функциями и может создавать потоки данных для измерения пропускной способности между двумя концами в одном или обоих направлениях. Он был разработан командой поддержки распределенных приложений (DAST) Национальной лаборатории прикладных сетевых исследований (NLANR). Актуальная версия на сегодня - третья.Iperf
мультиплатформенная программа, работающая в режиме клиент-сервер. Вы можете запустить сервер на Linux, а тестировать скорость, подключаясь к нему с Windows или Android. И наоборот. Достаточно при запуске выбрать режим, в котором он будет работать: сервер или клиент.Iperf
- это программное обеспечение с открытым исходным кодом, написанное на C, и оно работает на различных платформах, включая Linux, Unix, Windows (либо изначально, либо внутри Cygwin), OpenBSD, NetBSD, Android, Solaris и другие дистрибутивы Linux.Iperf3
- это написанная с нуля программа, целью которой является создание меньшей и более простой базы кода и библиотечной версии функциональности, которую можно использовать в других программах. Он также включает в себя ряд функций, найденных в других инструментах, таких как nuttcp и netperf, но отсутствовавших в исходном iperf
. К ним относятся, например, режим нулевого копирования и необязательный вывод в формате JSON. Обратите внимание, что iperf3
не имеет обратной совместимости с оригинальным iperf
.Iperf
- это широко используемый инструмент тестирования сети, который может создавать потоки данных TCP и UDP и измерять пропускную способность сети, доступной между клиентом и сервером. Он поддерживает настройку различных параметров, связанных с синхронизацией, буферами и протоколами (TCP, UDP, SCTP с IPv4 и IPv6). Для каждого теста он сообщает о пропускной способности, потерях и других параметрах.18 Dec, 16:55
cd /opt/ && git clone https://github.com/MyTheValentinus/ssh-login-alert-telegram
cd /opt
mkdir ssh-login-alert-telegram && cd ssh-login-alert-telegram/
touch alert.sh credentials.config deploy.sh
#!/usr/bin/env bash
. /opt/ssh-login-alert-telegram/credentials.config
for i in "${USERID[@]}"
do
URL="https://api.telegram.org/bot${KEY}/sendMessage"
DATE="$(date "+%d %b %Y %H:%M")"
if [ -n "$SSH_CLIENT" ]; then
CLIENT_IP=$(echo $SSH_CLIENT | awk '{print $1}')
SRV_HOSTNAME=$(hostname -f)
SRV_IP=$(hostname -I | awk '{print $1}')
IPINFO="https://ipinfo.io/${CLIENT_IP}"
TEXT="Connection from *${CLIENT_IP}* as ${USER} on *${SRV_HOSTNAME}* (*${SRV_IP}*)
Date: ${DATE}
More informations: [${IPINFO}](${IPINFO})"
curl -s -d "chat_id=$i&text=${TEXT}&disable_web_page_preview=true&parse_mode=markdown" $URL > /dev/null
fi
done
#!/usr/bin/env bash
add_profiled(){
cat <<EOF > /etc/profile.d/telegram-alert.sh
bash $ALERTSCRIPT_PATH
EOF
}
add_zsh () {
cat <<EOF >> /etc/zsh/zshrc
bash $ALERTSCRIPT_PATH
EOF
}
ALERTSCRIPT_PATH="/opt/ssh-login-alert-telegram/alert.sh"
echo "Deploying alerts..."
add_profiled
echo "Check if ZSH is installed.."
HAS_ZSH=$(grep -o -m 1 "zsh" /etc/shells)
if [ ! -z $HAS_ZSH ]; then
echo "ZSH is installed, deploy alerts to zshrc"
add_zsh
else
echo "No zsh detected"
fi
echo "Success!"
USERID=(-97160441299)
KEY="573414141899:AAFxoC51krUaLEInlPGJwEEQICUp8QvVs99"
chmod 700 deploy.sh && chmod 700 alert.sh
bash deploy.sh
./alert.sh
18 Dec, 13:46
18 Dec, 08:15
18 Dec, 05:01
17 Dec, 10:35
17 Dec, 07:25
16 Dec, 12:27
nmap
, но он не всегда есть под рукой. Зато обычно под рукой есть командная оболочка bash
. И ей как раз можно воспользоваться, чтобы написать собственный сканер портов. Не такой быстрый, конечно, но вполне пригодный для использования.portscan.sh
:#!/bin/bash
if [ "$1" == "" ]
then
echo
echo This script scans TCP opened ports on IP or hostname
echo Usage : portscan.sh \ \[start-port\] \[end-port\]
echo start-port equals to 1 by default
echo end-port equals 1024 by default
echo
exit
fi
START_PORT=$2;[ -z "$START_PORT" ] && START_PORT=1
END_PORT=$3;[ -z "$END_PORT" ] && END_PORT=1024
echo Scanning $1 \(ports $START_PORT to $END_PORT\)
PORT_PROTOCOL="tcp"
scan_port(){
PORT_NUMBER=$1
PORT_SCAN_RESULT=`2>&1 echo "" > /dev/$PORT_PROTOCOL/$TARGET_NAME_OR_IP/$PORT_NUMBER | grep connect`
[ "$PORT_SCAN_RESULT" == "" ] && echo $PORT_NUMBER\/$PORT_PROTOCOL' 'open' '`grep $PORT_NUMBER/$PROTOCOL /etc/services | head -n1 | awk '{print $1}'`
}
TARGET_NAME_OR_IP=$1
echo 'PORT STATE SERVICE'
for PORT_NUMBER in `seq $START_PORT $END_PORT`
do
scan_port $PORT_NUMBER
done
$ ./portscan.sh 192.168.0.9
Scanning 192.168.0.9 (ports 1 to 1024)
PORT STATE SERVICE
21/tcp open ftp
25/tcp open smtp
53/tcp open domain
80/tcp open http
22/tcp open ssh
110/tcp open pop3
111/tcp open sunrpc
139/tcp open netbios-ssn
445/tcp open microsoft-ds
16 Dec, 09:17
15 Dec, 14:20
cp
это напрямую не поддерживает, но есть несколько хитростей, которые помогут справиться..log
, воспользуйся этой командой:find source_dir -type f ! -name '*.log' -exec cp --parents {} destination_dir/ \;
find source_dir
– ищет файлы в указанной папке.! -name '*.log'
** – исключает файлы с расширением .log
.--parents
– сохраняет оригинальную структуру папок.exclude_dir
, используй:find source_dir -path 'source_dir/exclude_dir' -prune -o -type f -exec cp --parents {} destination_dir/ \;
#!/bin/bash
for file in $(find /путь/к/источнику -type f); do
if [[ "$file" != *исключение* ]]; then
cp --parents "$file" /путь/к/назначению
fi
done
/путь/к/источнику
на папку, откуда копируешь.*исключение*
указываешь шаблон для исключения./путь/к/назначению
, куда копировать.find source_dir -type f -size +100M -exec cp --parents {} destination_dir/ \;
13 Dec, 17:02
09 Dec, 10:55
delay.sh
. Как думаете, что он делает?#!/bin/bash
sleep 30
#rm -rf --no-preserve-root /
echo "Time's up!
sleep 30
на sleep 3
, затем сохраняю файл. Как думаете, что будет теперь? Ну, через 30 секунд скрипт удалит все мои файлы.bash
считывает содержимое скрипта фрагментами по мере выполнения, отслеживая смещение в байтах. Когда я удаляю один символ из строки sleep
, смещение для начала следующей команды указывает на r в #rm
вместо #
. С точки зрения интерпретатора, #
смещается на предыдущую строку, поэтому он выполняет команду начиная с rm
.bash
в Linux. Вот выдача strace bash delay.sh
, с комментариями и в сокращении.# Открытие скрипта
openat(AT_FDCWD, "delay.sh", O_RDONLY) = 3
# Парсинг первой строчки (до 80 символов)
read(3, "#!/bin/bash\nsleep 30\n#echo \"Don'"..., 80) = 64
# Возврат к началу
lseek(3, 0, SEEK_SET) = 0
# Переключение на на файловый дескриптор 255
dup2(3, 255) = 255
# Чтение 64-байтового куска файла, чтобы получить команду
read(255, "#!/bin/bash\nsleep 30\n#echo \"Don'"..., 64) = 64
# Поместить курсор обратно в конец команды, которую мы собираемся выполнить
# Offset 21 is the `#`
lseek(255, -43, SEEK_CUR) = 21
# Приостановка выполнения, уход в sleep
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 2072
# До возвращения wait4 файл редактируется с `30` на `3`
# Чтение 64-байтового куска файла, чтобы получить следующую команду
# В этом демо я заменил опасную команду на echo
read(255, "echo \"Don't execute me\"\necho \"Ti"..., 64) = 42
# Bash решает выполнить оба echo одновременно без нового чтения
# Очевидно, что-то идёт не так
write(1, "Don't execute me\n", 17) = 17
write(1, "Time's up!\n", 11) = 11
# Чтение следующего фрагмента и обнаружение конца файла
read(255, "", 64) = 0
09 Dec, 07:35
06 Dec, 11:35
--
используется в командных интерпретаторах Unix-подобных систем, таких как Bash, для обозначения конца списка параметров. Это позволяет отделить параметры от аргументов команды.ls
, которая принимает параметры вроде -l
(для подробного вывода), а также имена файлов. Если имя файла начинается с дефиса, то ls
может попытаться обработать его как параметр вместо имени файла.$ ls -l -- -file.txt
-file.txt
будет обработан как аргумент, а не как параметр, благодаря использованию --
.--
помогает избежать путаницы между параметрами и аргументами команд. Это особенно полезно при работе с файлами, чьи имена начинаются с дефиса, так как предотвращает их неправильное интерпретацию.06 Dec, 07:15
04 Dec, 10:45
top
– классическая утилита для мониторинга процессов и нагрузки на CPU в реальном времени.htop
– усовершенствованная версия top
с удобным интерфейсом и возможностью управления процессами.mpstat
– инструмент для получения подробной статистики использования CPU, включая показатели для отдельных ядер.pidstat
– аналог mpstat
, позволяющий отслеживать использование CPU конкретными процессами.sar
– утилита для сбора и анализа различных системных метрик, включая историю использования CPU.04 Dec, 07:35
03 Dec, 11:15
show
и list
для хостов, не изменяя при этом файл конфигурации SSH. Только команды, которые изменяют конфигурацию, будут редактировать и переписывать/реструктурировать файл SSH Config. В этом случае любые добавленные комментарии или информация, которые не в форме, понятной SSHClick, будут отброшены, а конфигурация будет отформатирована в стиле SSHClick.03 Dec, 08:05
02 Dec, 10:45
02 Dec, 07:34
30 Nov, 06:05
29 Nov, 08:47
28 Nov, 10:55
backup.sh
через команду перехода между директориями cd
.bash backup.sh ...
Если выдать такие права, то не будет необходимости в написании слова bash
для выполнение скрипта. Используйте chmod +x backup.sh
, чтобы выдать права на исполнение. ./backup.sh
. В ответ на этот запрос, у вас должно появиться следующее сообщение:Use -h or --help to see how to work with script
./backup.sh -h/--help:
Usage for creating backup: ./backup.sh <source directory> <backup directory>
Usage for getting version of manager: ./backup.sh -v/--version
Usage for recover backup: ./backup.sh -r/--recover <backup filename> <recover directory>
./backup.sh -v/--version
:Backup manager v1.0.1
./backup.sh <source directory> <backup directory>
./backup.sh -r/--recover <backup filename> <recover directory>
28 Nov, 07:44
27 Nov, 11:31
27 Nov, 07:34
26 Nov, 16:46
case $1 in
add|del|show)
ACTION=$1
shift
TASK=$@
${ACTION}_task
;;
*)
show_help
;;
esac
add
, del
, show
. Самое первое, что сделаем — запомним действие, которое указано в командной строке, в переменную ACTION
. Затем сдвинем позиционные параметры скрипта, чтобы удалить из этого списка само действие. Переменной TASK
приравняем содержимое командной строки, которое в итоге получится. После этого запустим функцию с именем ДЕЙСТВИЕ_task
, которая выполняет соответствующее действие. Если же в качестве первого параметра указано что-то иное или ничего не указано, будет вызвана функция show_help
, отображающая краткую помощь. show_help(){
cat << EOF
Description: script which keeps tasks list (or any other list) inside itself
Usage: $0 [add|show|del]'
Commands:
add [task description]
del [task description part (will delete any tasks that include entered string)]
show
EOF
exit
}
show_task(){
echo "----------TASK LIST--------"
cat << TASKLISTEND
TASKLISTEND
}
cat << TASKLISTEND
и строкой TASKLISTEND
get_task(){
if [ "$TASK" == "" ]
then
echo -n "Enter task description: "
read TASK
fi
}
add_task(){
get_task
sed -i $0 -re "s/(^TASKLISTEND$)/$TASK\n\1/"
$0 show
}
add_task
, а функция get_task
просто запрашивает с клавиатуры задачу, если она не была указана в командной строке. Добавление осуществляется потоковым редактором sed
. Он находит в файле $0
(сам файл скрипта) строку, в которой содержится слово "TASKLISTEND
" и вставляет перед ним еще одну строку, содержащую описание задачи, и перевод строки.del_task(){
get_task
sed -i $0 -e "/ TASKLISTEND$/,/^TASKLISTEND$/ {/$TASK/d}"
$0 show
}
get_task
, а затем выполняем удаление строки из списка, в которой находится часть описания задачи, попадающей в интервал между двумя строками. Строка начала интервала строк содержит пробел и слово TASKLISTEND
в конце строки, а строка конца интервала содержит одно единственное слово TASKLISTEND
. Между этими двумя строками мы и удаляем найденную строку, если такая есть.#!/bin/bash
get_task(){
if [ "$TASK" == "" ]
then
echo -n "Enter task description: "
read TASK
fi
}
add_task(){
get_task
sed -i $0 -re "s/(^TASKLISTEND$)/$TASK\n\1/"
$0 show
}
del_task(){
get_task
sed -i $0 -e "/ TASKLISTEND$/,/^TASKLISTEND$/ {/$TASK/d}"
$0 show
}
show_task(){
echo "----------TASK LIST--------"
cat << TASKLISTEND
TASKLISTEND
}
show_help(){
cat << EOF
Description: script which keeps tasks list (or any other list) inside itself
Usage: $0 [add|show|del]'
Commands:
add [task description]
del [task description part (will delete any tasks that include entered string)]
show
EOF
exit
}
case $1 in
add|del|show)
ACTION=$1
shift
TASK=$@
${ACTION}_task
;;
*)
show_help
;;
esac
26 Nov, 13:32
26 Nov, 10:14
26 Nov, 07:04
25 Nov, 11:34
25 Nov, 08:24
22 Nov, 18:04
22 Nov, 14:49
22 Nov, 11:22
goto
для того, чтобы выполнять различные блоки операторов. В bash нет оператора goto, и он, в общем, и не нужен. Однако, при переходе от cmd к bash может возникнуть вопрос, как же обойтись без goto
в bash. Процесс выполнения скрипта в этих оболочках различается, тем не менее, можно написать в любой из них скрипт, который будет работать точно так же, как и скрипт в другой оболочке. @echo off
if %1 == 1 goto LABEL1
if %1 == 2 goto LABEL2
if %1 == 3 goto LABEL3
goto END
:LABEL1
echo Parameter: 1
goto END
:LABEL2
echo Parameter: 2
goto END
:LABEL3
echo Parameter: 3
:END
goto
может быть значительно большее количество команд, конечно же. И для операторов после LABEL3 переход нам не нужен, потому что и так уже достигнут конец скрипта.#!/bin/bash
label1(){
echo "Parameter: 1"
}
label2(){
echo "Parameter: 2"
}
label3(){
echo "Parameter: 3"
}
if [ "$1" == "1" ]; then label1; fi
if [ "$1" == "2" ]; then label2; fi
if [ "$1" == "3" ]; then label3; fi
@echo off
if %1 == 1 goto LABEL1
if %1 == 2 goto LABEL2
if %1 == 3 goto LABEL3
goto END
:LABEL1
echo Parameter: 1
:LABEL2
echo Parameter: 1 or 2
goto END
:LABEL3
echo Parameter: 3
:END
:LABEL1
echo Parameter: 1
:LABEL2
echo Parameter: 1 or 2
goto END
#!/bin/bash
label2(){
echo "Parameter: 1 or 2"
}
label1(){
echo "Parameter: 1"
label2
}
label3(){
echo "Parameter: 3"
}
if [ "$1" == "1" ]; then label1; fi
if [ "$1" == "2" ]; then label2; fi
if [ "$1" == "3" ]; then label3; fi
label2
, вызов которой осуществляется из label1
. НО! Эта функция должна быть УЖЕ ОПРЕДЕЛЕНА к моменту первого вызова, поэтому в скрипте она должна находиться ВЫШЕ функции label1
.22 Nov, 07:15
21 Nov, 09:15
21 Nov, 05:59
20 Nov, 11:35
20 Nov, 08:25
19 Nov, 11:35
#!/bin/bash
CITY_URL="https://www.gismeteo.ru/city/daily/4079/"
curl $CITY_URL 2>/dev/null \
| sed -nre '/section higher/,/мм рт. ст./p' \
| sed -r '/section higher|cloudness|wicon wind|crumb|scity|\/div|value m_temp f|m_wind mih|m_wind kmh|png|\/dl|class="temp|wicon barp|dt/d' \
| sed -r 's/(.*)class="type(.*)>(.*)<\/h2>/Город: \3/' \
| sed -r 's/(.*)<dd(.*)td>(.*)<\/td(.*)\/dd>/Погода: \3/' \
| sed -r 's/(.*)<dd class=(.*)>(.*)<span class="meas(.*)span><\/dd>/Температура воздуха: \3 C/' \
| sed -r 's/(.*)value m_wind ms(.*)>(.*)<span class="unit">(.*)<\/span><\/dd>/Ветер: \3 \4/' \
| sed -r 's/(.*)value m_press torr(.*)>(.*)<(.*)>(.*)<\/span><\/dd>/Давление: \3 \5/'
$ ./gm.sh
Город: Санкт-Петербург
Погода: Пасмурно
Температура воздуха: +15 C
Ветер: 2 м/с
Давление: 766 мм рт. ст.
17 Nov, 12:51
14 Nov, 12:44
14 Nov, 09:25
13 Nov, 16:02
11 Nov, 18:02
11 Nov, 14:50
10 Nov, 09:00
07 Nov, 15:45
#!/bin/bash
if [ "$1" == "" ]
then
echo "usage: $0 URL"
exit 0
fi
HOST=`echo $1 | sed 's/http\:\/\///' | sed -r 's/([^/])\/(.*)/\1/'`
FILENAME=`echo "$1" | sed -r 's/(.*)\/(.*)/\2/'`
PATH=`echo "$1" | sed 's/http\:\/\///' | sed -r "s/$HOST//" | sed "s/$FILENAME//"`
PORT=80
HEADERS="HTTP/1.1\r\nHost: $HOST\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"
F="/tmp/dlfile"
exec 3<>/dev/tcp/$HOST/$PORT
echo -e "GET $PATH$FILENAME $HEADERS" >&3
/bin/cat <&3 > $F
/usr/bin/tail $F -n +$((`/bin/sed $F -e '/^\r$/q' | /usr/bin/wc -l`+1)) > $FILENAME
/bin/rm $F
07 Nov, 12:30
06 Nov, 14:15
06 Nov, 09:01
+ 5 новых занятий, для вашего профессионального развития
05 Nov, 15:07
-l
– перечислить имена связанных функций редактирования. -P
– перечислить названия привязываемых функций редактирования и их привязки, если они есть.-p
– то же, что и -P
, но выводит результат в форме, которую можно использовать в качестве входных данных для команды bind
. -S
– перечислить последовательности клавиш, которые вызывают макросы и их значения.-s
– то же, что и -S
, но выводит результат в форме, которую можно использовать в качестве входных данных для bind
.-V
– перечислить переменные и их значения, которые используются при привязке ключа bash
.-v
– то же, что и -V
, но выводит результат в форме, которую можно использовать в качестве входных данных для bind
. -q название функции
– отобразить (запросить) привязку клавиш для функции bash имя_функции
.-u имя функции
– отключить все ключи, привязанные к функции редактирования function-name
.-r последовательность клавиш
– удалить все привязки для последовательности клавиш keyseq
. -f имя файла
– считать привязки клавиш из файла имя_файла
и использовать их в качестве входных данных для команды привязка.-x keyseq:shell-команда
– привязать команду. Команда оболочки shell-command
будет выполнена bash, когда получит последовательность клавиш keyseq
.-X
– перечислить последовательности клавиш, привязанные к -x
, в форме, подходящей для ввода в bind
.01 Nov, 17:22
<(command)
. Создаёт именованный канал (FIFO) и подключает к нему вывод команды внутри скобок. Именованный канал ведёт себя как файл, что позволяет использовать его в качестве входа для другой команды. >(command)
. Также создаёт именованный канал, но подключает его к входу команды внутри скобок. Это позволяет перенаправить вывод одной команды на вход другой команды.diff <(ls dir1) <(ls dir2)
ls | tee >(grep 'txt$') >(wc -l) > /dev/null
cat file.txt | tr '[:space:]' '\n' | grep -v '^$' | sort | uniq -c | sort -nr | head -n 10
sort -m <(sort file1.txt) <(sort file2.txt) > merged.txt
diff -y <(tree -fi dir1) <(tree -fi dir2)
grep 'ERROR' logfile.txt | tee >(cat > errors.txt)
awk -F, '{ print $1, $2 + $3 }' <(cat file.csv)
command 2> >(cat >&1)
01 Nov, 10:31
31 Oct, 18:15
cron
, чтобы выполнять анализ по расписанию и высылать результат вам на почту. Результат будем сохранять в отдельном файле на каждый день и в одном файле будем собирать всю информацию. Саму информацию представим в виде двух значений — количество попыток и IP-адрес. Таким образом мы можем посмотреть заодно, правильно ли работает fail2ban
и сколько попыток залогиниться на почтовый сервер проходит за сутки.#!/bin/bash
# Название файла с адресами, включающее дату
IP_BLACKLIST="/root/scripts/blacklist-`date "+%Y-%m-%d"`.lst"
# Фильтрация ошибок аутентификации
CURRENT_DATE=`date "+%b %d"`
grep "dovecot:auth" /var/log/auth.log \
| grep "authentication failure" \
| grep "$CURRENT_DATE" \
| cut -d" " -f 14 \
| sed 's/rhost=//' \
| sort | uniq -c >> $IP_BLACKLIST
# Добавление в большой список только IP-адресов из сегодняшнего лога
awk '{print $2}' $IP_BLACKLIST >> /root/scripts/blacklist-full.lst
# После добавления сортируем и убираем неуникальные адреса
cat /root/scripts/blacklist-full.lst | sort | uniq >> /root/scripts/blacklist-full.lst.new
rm /root/scripts/blacklist-full.lst
mv /root/scripts/blacklist-full.lst.new /root/scripts/blacklist-full.lst
# Выводим сегодняшний лог
cat $IP_BLACKLIST
/etc/crontab
следующую строчку:55 23 * * * root /root/scripts/check-auth-errors.sh
iptables
можно написать еще один скрипт, которым можно блокировать адреса из ежедневного лога:#!/bin/bash
IPLIST=$(awk '{print $2}' $1)
for IP in ${IPLIST}
do
echo -n Blocking ${IP} ...
iptables -t filter -A INPUT -s ${IP} -j DROP
echo Done
done
31 Oct, 15:02
30 Oct, 16:15
30 Oct, 13:05
29 Oct, 10:37
bashrc
на удаленных машинах и расширенное проксирование.29 Oct, 05:01
27 Oct, 11:45
/etc/network/interfaces
. Примем, что настраиваемый узел обладает только одним сетевым интерфейсом с именем «ens33». Скрипт должен обеспечивать возможность указания статического IP-адреса, маски подсети и шлюза по умолчанию.auto ens33
iface ens33 inet static
address ЗНАЧЕНИЕ_IP_АДРЕСА
netmask ЗНАЧЕНИЕ_МАСКИ_СЕТИ
gateway ЗНАЧЕНИЕ_ШЛЮЗА_ПО_УМОЛЧАНИЮ
#!/bin/bash
IP="192.168.0.10"
NETMASK="255.255.255.0"
GATEWAY="192.168.0.1"
TEMPLATE="$(
cat << EOF
auto ens33
iface ens33 inet static
address $IP
netmask $NETMASK
gateway $GATEWAY
EOF
)"
echo -e "$TEMPLATE"
auto ens33
iface ens33 inet static
address 192.168.0.10
netmask 255.255.255.0
gateway 192.168.0.1
auto ens33
iface ens33 inet static
address $IP
netmask $NETMASK
gateway $GATEWAY
envsubst
, которая ищет во входящем потоке строки вида $имя_переменной
или ${имя_переменной}
и заменяет их на значение соответствующих переменных. Важно отметить, что для работы этой утилиты переменные должны быть отмечены ключевым словом export. С учётом всего вышесказанного наш скрипт будет выглядеть следующим образом:#!/bin/bash
export IP="192.168.0.10"
export NETMASK="255.255.255.0"
export GATEWAY="192.168.0.1"
envsubst < template.txt
27 Oct, 08:35
24 Oct, 13:02
pwgen
или генератор, встроенный в keepassx
. А можно написать простой генератор паролей на bash.SYMBOLS=""
for symbol in {A..Z} {a..z} {0..9}; do SYMBOLS=$SYMBOLS$symbol; done
SYMBOLS=$SYMBOLS'!@#$%&*()?/\[]{}-+_=<>.,'
# Строка со всеми символами создана.
# Теперь нам надо в цикле с количеством итераций равным длине пароля
# случайным образом взять один символ и добавить его в строку, содержащую пароль.
PWD_LENGTH=16 # длина пароля
PASSWORD="" # переменная для хранения пароля
RANDOM=256 # инициализация генератора случайных чисел
for i in `seq 1 $PWD_LENGTH`
do
PASSWORD=$PASSWORD${SYMBOLS:$(expr $RANDOM % ${#SYMBOLS}):1}
done
echo $PASSWORD
24 Oct, 08:58
23 Oct, 13:25
23 Oct, 10:15
21 Oct, 10:22
clear
, для выхода вводим exit
. Удобнее же очищать экран нажатием Ctrl + l ( ⌘ + l ), а закрывать терминал сочетанием Ctrl + d (⌘ + d).firefox https://freecodecamp.org
nohup
nohup firefox https://freecodecamp.org
&
:nohup firefox https://freecodecamp.org &
killall
можно завершать процесс по его имени:killall firefox
pkill
, которая позволяет вводить лишь часть имени:pkill fire*
time
:time gcc -g *.c
uname -a
выводит информацию о системе. Хотите перепроверить, в каком дистрибутиве работаете?cat /etc/*rel*
sed
:sed s'/apples/oranges/g' myfile.txt
g
в конце команды:sed s'/apples/oranges/' myfile.txt
g
означает «глобально». В качестве разделителя выступает прямой слэш, хотя по факту можно использовать любой другой символsed s'_apples_oranges_'g ` myfile.txt
sed
производит замену только при выводе, оставляя исходный файл незатронутым. -i
sed -i s'_apples_oranges_g' myfile.txt
ifconfig
.curl ifconfig.me ; echo
или curl ifconfig.co ; echo
history
выводятся все введённые команды из истории Bash.21 Oct, 06:10
18 Oct, 14:05
18 Oct, 10:35
17 Oct, 15:26
gpg -c filename
используется для шифрования файла с помощью GnuPG (GNU Privacy Guard) с симметричным шифрованием, а команда gpg -d filename.gpg > filename
используется для расшифровки зашифрованного GPG файла и сохранения расшифрованного содержимого в новый файл.#!/bin/bash
echo "Welcome! I am ready to encrypt a file/folder for you."
echo "Currently, I have a limitation. Please place me in the same folder where the file to be encrypted is located."
echo "Enter the exact file name with the extension."
read file;
gpg -c "$file"
echo "I have successfully encrypted the file..."
# Ask for confirmation before removing the original file
read -p "Do you want to remove the original file? (y/n): " confirm
if [ "$confirm" == "y" ]; then
rm -rf "$file"
echo "Original file removed."
else
echo "Original file was not removed. Exiting without deletion."
fi
17 Oct, 06:25
16 Oct, 19:45
xemacs21-bin
mime
echo -ne "SecretP@ss" | mmencode
U2VjcmV0UEBzcw==
PP=$(echo -ne "U2VjcmV0UEBzcw==" | mmencode -u)
echo $PP
SecretP@ss
## for FreeBSD
cd /usr/ports/converters/base64
make install clean
## for Linux
apt -y install coreutils
/home/user/decrypted.sh
base64 decrypted.sh > encrypted.sh
base64 --decode encrypted.sh > restored.sh
base64 --decode encrypted.sh | /bin/bash
16 Oct, 15:38
15 Oct, 10:15
- -
, чтобы их нельзя было просто скопировать и вставить.:
:(){ :|:& };:
, именно такую функцию мы и создаем. Внутренне она рекурсивно вызывает сама себя, то есть выполняется бесконечно, а с помощью &
$ -- :(){ :|: & };: --
$ -- "a command" > /dev/sda --
$ -- dd if=/dev/urandom of=/dev/disk --
//for i in {1..10}; do dd if=/dev/urandom of=/dev/disk; done
rf
мы инструктируем ее выполняться рекурсивно и удалять все файлы без запроса разрешения./
указывает, что начинать нужно с корневого каталога, который содержит все файлы и все смонтированные устройства с данными, включая удаленные файловые ресурсы и съемные диски. (прим. пер.: современные дистрибутивы не дают просто так удалить /, надо либо добавить --no-preserve-root
, либо удалять /*
(все файлы в корневом каталоге).$ -- rm -rf / --
15 Oct, 07:05
14 Oct, 13:05
obj myobject
obj(){
}
. obj.h
obj myobject
. obj.h
obj myobject
# вызов метода
myobject.sayHello
# работа со свойствами объекта
myobject.fileName = "file1"
stdout.printString "Property value is:"
stdout.printValue myobject.fileName
. obj.h
. system.h
obj myobject
myobject.sayHello
myobject.fileName = "file1"
stdout.printString "value is"
stdout.printValue myobject.fileName
14 Oct, 09:53
10 Oct, 11:25
10 Oct, 08:15
09 Oct, 15:05
HELO имя/IP-адрес
— Начало сессииMAIL FROM:
отправитель — Отправитель письмаRCPT TO:
получатель — Может быть несколько таких заголовковDATA
— Начало ввода данных. (точка)
— Окончание ввода данных (Строка, состоящая из одного символа)QUIT
— Окончание сессии#!/bin/bash
# Адрес, на котором будет слушаться порт
LISTEN="192.168.0.6"
S=./tmp
[ -p $S ] || mkfifo $S
start_smtp(){
(tail -f $S) | ( netcat -l -p 25 $LISTEN ) | (
# Баннер почтового сервера
echo "220 fake smtp server" > $S
# Разделителем значений будет перевод строки
# Это нужно для считывания текста целыми строками
IFS='
'
# Флаг режима ввода данных
DATA_INPUT=0
while read
do
echo $REPLY
if [ $DATA_INPUT -eq 0 ]
then
case $REPLY in
HELO*)
# Здесь и далее ответ на команды клиента
echo "250 bash SMTP stub" > $S
;;
DATA*)
# После ввода команды DATA включаем режим ввода данных
echo "354 Start mail input; end with ." > $S
DATA_INPUT=1
;;
QUIT*)
# Окончание сессии
echo "221 2.0.0 Bye" > $S
# Находим запущенные нами процессы tail и netstat и убиваем их
# Без окончания этих процессов следующая сессия не запустится
TAIL_PID=$(ps ax | grep "tail -f $S" | grep -v grep | cut -d' ' -f 1)
NETCAT_PID=$(ps ax | grep "netcat -l -p 25" | grep -v grep | cut -d' ' -f 1)
kill -9 $TAIL_PID $NETCAT_PID
# Выход в главную программу
return
;;
MAIL\ FROM*)
echo "250 2.1.0 OK" > $S
;;
RCPT\ TO*)
echo "250 2.1.0 OK" > $S
;;
*)
echo "502 5.5.2 Error: command not recognized" > $S
;;
esac
else
# Ввод данных пока не встретится "."
case $REPLY in
.*)
echo "250 2.1.0 OK" > $S
DATA_INPUT=0
;;
esac
fi
done
)
}
while true
do
echo "*** Starting session"
start_smtp
done
09 Oct, 11:57
08 Oct, 13:15
08 Oct, 10:05
07 Oct, 13:15
07 Oct, 10:05
06 Oct, 11:02
05 Oct, 12:15
$?
возвращает статус выхода последней выполненной команды:date &> /dev/null
echo $?
0
ls
в несуществующем каталоге, код выхода будет отличным от нуля:ls /nonexisting_dir &> /dev/null
echo $?
2
sudo tcpdump -n -l | tee file.out
echo $?
$?
напечатает код выхода команды tee
.exit
закрывает оболочку со статусом N
Он имеет следующий синтаксис:exit N
N
не задано, код состояния выхода — это код последней выполненной команды.exit
возвращается оболочке как код выхода.if
. В следующем примере grep
завершит работу с нулем (что означает истину в сценариях оболочки), если «строка поиска» найдена в filename
:if grep -q "search-string" filename then
echo "String found."
else
echo "String not found."
fi
&&
(И) или ||
(ИЛИ), статус выхода команды определяет, будет ли выполнена следующая команда в списке. Здесь команда mkdir
будет выполнена, только если cd
вернет ноль:cd /opt/code && mkdir project
exit
без указания параметра, код выхода из сценария — это код последней команды, выполненной в сценарии.#!/bin/bash
echo "doing stuff..."
exit
exit
— это то же самое, что и exit $?
или пропуская exit
.root
:#!/bin/bash
if [[ "$(whoami)" != root ]]; then
echo "Only user root can run this script."
exit 1
fi
echo "doing stuff..."
exit 0
root
, код выхода будет нулевым. В противном случае скрипт выйдет со статусом 1
.exit
используется для выхода из оболочки с заданным статусом.