И то, и другое — интерпретаторы командной строки в линуксе. То есть если вы откроете командную строку и введете любую команду, да хоть:

cd /home

То именно интерпретатор ее расшифрует и скажет компьютеру «он хочет перейти в директорию /home». Компьютер ведь не понимает команды на русском / английском языке. Ему нужны байтики. Этим и занимается интерпретатор — переводом с «нашего» на «компьютерный» язык.

Так что «cd /home» — это shell-команда! Или bash. Смотря какой интерпретатор установлен в вашей системе. В каждой операционной системе установлен интерпретатор по умолчанию. У них есть какие-то различия, но есть и набор базовых команд, которые понимают все: cd, mv, cp, ls… (в винде эти команды немного другие)

А что такое shell-скрипт тогда? Это просто текстовый документ, внутри которого написан набор команд! Это не обязательно должны быть «сложные» команды, которые делают что-то супер-навороченное. Это любые команды, которые вы выполняете в консоли.

См также:

Основные linux-команды для новичка — что можно выполнять в консоли

Например, создадим скриптик, который создаст директорию и в ней файлик:

mkdir /home/test

cd /home/test

touch test.txt

Так, команды записали, осталось сохранить их в файлик. Скрипты хранят в файлах с расширением .sh, поэтому назовем файл first_script.sh. Но есть нюанс — линуксу плевать на ваше расширение файла. Его может вообще не быть, и все равно скрипт останется скриптом. Почему? Потому что у любого скрипта в первой строке должен содержаться путь к интерпретатору. Например:

#!/bin/bash

или

#!/bin/sh

Весь файл целиком:

#!/bin/bash

mkdir /home/test

cd /home/test

touch test.txt

И даже если у такого файла не будет расширения вовсе, его можно будет запустить как скрипт:

sh first_script
# Проверяем директорию /home — там появилась папка test с файлом test.txt внутри.

Расширение .sh ставится для понимания человеком. Зашел в директорию:

— Ага, что тут у нас? Файлы sh, скрипты какие-то лежат...

Скрипты могут быть простые, а могут быть сложные. Вот, например, в одном проекте мы вначале вручную обновляли тестовые платформы. Для обновления надо:

  1. Остановить сервис.

  2. Переподложить war-файл с приложением (лежат они в директории /opt)

  3. Запустить сервис

Сервиса два, допустим это test и cloud. Так что шагов уже 6.

Когда обновлять вручную надоело, мы положили на все линукс машины простой скриптик:

#!/bin/bash

service test stop
cp test.war /opt/jboss-test/bin
service test start

service cloud stop
cp cloud.war /opt/jboss-cloud/bin
service cloud start

Собираешь приложение, подкладываешь к скриптику и запускаешь 1 команду вместо 6. Удобно! Это называется «автоматизация рутины» =)

Другой пример с того же проекта — мы делали серверное приложение. И во время установки приложения на сервере linux нужно выполнить пункты по настройке самой системы. Например, увеличить параметр max_map_count — сколько максимум памяти может использовать процесс.

Приложение в пике работы требует много памяти. Если не настроить параметр, то «тяжеловесная» задача просто упадет с ошибкой «Не хватает памяти». И если мы видим такую ошибку, то в первую очередь идем проверять настройки системы.

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

Мы написали скрипт по проверке настройки окружения (символ «#» в начале строки означает, что это комментарий):

#!/bin/sh
#
# check sysctl
#
if [ -f /proc/sys/vm/max_map_count ] && [ $(cat /proc/sys/vm/max_map_count) -ge 16777216  ]; then
echo "vm.max_map_count: ok"
else
echo "vm.max_map_count: failed"
fi

if [ -f /proc/sys/vm/overcommit_memory ] && [ $(cat /proc/sys/vm/overcommit_memory) -eq 2  ]; then
echo "vm.overcommit_memory: ok"
else
echo "vm.overcommit_memory: failed"
fi

if [ -f /proc/sys/vm/overcommit_ratio ] && [ $(cat /proc/sys/vm/overcommit_ratio) -eq 100  ]; then
echo "vm.overcommit_ratio: ok"
else
echo "vm.overcommit_ratio: failed"
fi

if [ -f /proc/sys/vm/swappiness ] && [ $(cat /proc/sys/vm/swappiness) -le 10  ]; then
echo "vm.swappiness: ok"
else
echo "vm.swappiness: failed"
fi

В итоге админы настраивают окружение, а потом мы даем им скрипт, просим запустить его и прислать результаты. Я запустила скрипт на «голой» системе, где, разумеется, параметры настроены не были, и вот ответ:

Видим, что все проверки провалились, статус failed. Если и от админов приходит похожая картина, направляем их в документацию по настройке системы. Если к нам приходят с проблемой падения из-за нехватки памяти, снова просим выполнить скрипт. Так проще локализовать ошибку: это в приложении косяк, или окружение настроено плохо?

Просить других людей выполнить 10 команд не очень хорошо. Потому что часть команд может «потеряться» при выполнении — плохо скопировал, забыл выполнить проверку, которую дали сообщением позже... Гораздо проще сделать 1 скрипт и попросить выполнить именно его.

Когда надо писать скрипт?

  • Когда надо выполнить больше 3 команд за раз — проще выполнить одну, запустить скрипт.

  • Когда одну и ту же команду надо выполнять чаще 3 раз — лучше автоматизировать эту работу.

По сути своей, bash-скрипты — это та же автоматизация. А когда нужна автоматизация? Когда мы хотим избавиться от рутины, от постоянного выполнения одного и того же действия вручную. Повторяете одно и то же каждый день / неделю? Напишите скрипт. Даже если он на 2-3 строчки будет, это правда удобнее. Поверьте, сама делала небольшие скрипты =)

См также по bash:

Википедия

Что такое shell и зачем он нужен

Основы BASH. Часть 1 (Хабр) — цикл статей о том, как писать скрипты

Bash-скрипты: начало — цикл статей по скриптам

См также другие статьи из цикла «Что такое...»:

Что такое API

Что такое клиент-серверная архитектура

Что такое CI (Continuous Integration)

Что такое транзакция

Что такое XML

Что такое регулярные выражения (regexp)

PS — больше полезных статей ищите в моем блоге по метке «полезное». А полезные видео — на моем youtube-канале