Основы Bash-скриптинга для непрограммистов
Статья рассчитана на тех, кто не имеет или имеет мало опыта работы с командной строкой Unix/Linux, но желает научиться с ней эффективно взаимодействовать и разрабатывать скрипты для выполнения своих задач. Приведенные примеры справедливы для выполнения в командной оболочке bash операционной системы Ubuntu/Debian, но могут быть использованы и в других оболочках и ОС с учетом их специфики.
1. Командные оболочки
Существует множество дистрибутивов(форков) операционных систем(ОС) семейства Linux, наиболее известные среди них: Ubuntu, Debian, CentOS, Red Hat, Fedora, SuSE, FreeBSD, Mint.
Здесь есть большая схема со всеми форками Linux.
В каждой ОС существуют различные командные оболочки (shell), их назначение одинаково (администрирование, автоматизация, вычисления, мониторинг и т.д.), как и большинство основных команд, но реализация может отличаться. В таблице ниже приведено сравнение, в котором видно, что некоторые возможности поддерживаются не всеми оболочками.
Feature
Bourne
C
TC
Korn
Bash
Редактор командной строки
Расширенные шаблоны файлов
Автозавершение имени файла
Стеки директорий (pushd and popd)
Исправление ошибок в командах
Формат приглашения командной строки
Список доступных командных оболочек можно получить командой
При необходимости можно установить нужную командную оболочку командой sudo apt install . Например, для установки ksh нужно выполнить
2. Настройка тестовой среды
Если у вас уже есть виртуальная/реальная машина с установленным Linux, или вы знаете, как её настроить, то можно пропустить информацию из спойлера ниже. Если есть доступ по ssh к какому-либо серверу, то Вы также можете использовать его shell для тренировок. Используйте имеющийся доступ с осторожностью, не тренируйтесь на продуктовых(промышленных) серверах и других критичных окружениях. Если вы не хотите развертывать виртуальную машину(ВМ), то для тестов можно воспользоваться онлайн-терминалами, но нужно знать и учитывать их особенности и ограничения. Примеры онлайн-терминалов:
https://cocalc.com/app?anonymous=terminal
https://www.tutorialspoint.com/execute_bash_online.php
https://rextester.com/l/bash_online_compiler
Развертывание виртуальной машины
VirtualBox – ПО для виртуализации, позволяющее запускать одну ОС «внутри» другой. Разумеется, существуют и другие способы развертывания ВМ, здесь мы рассмотрим лишь один из них. В данном случае, предполагается, что у вас ПК под управлением Windows или Mac. Для начала нужно скачать VirtualBox отсюда и установить его.
Также нужно скачать образ ВМ с установленной ОС Ubuntu отсюда. Качайте самую новую версию, убедитесь, что скачиваемый образ имеет формат VirtualBox (VDI).
Создадим виртуальную машину. Сначала создаем на локальном диске папку для размещения в ней ВМ и их файлов (у меня C:\vmachines). Распакуем скачанный образ диска ВМ в созданную папку:
Для распаковки потребуется архиватор 7zip или другой, поддерживающий формат .7z. Далее запускаем VirtualBox и выбираем меню «Машина -> Создать…»:
В открывшемся окне указываем имя ВМ (тип и версия в большинстве случаев подтягиваются автоматически, если это понятно из имени), а также созданную нами папку. Объем оперативной памяти устанавливается автоматически, 1Гб достаточно для выполнения тестов. Выбираем «Использовать существующий виртуальный жесткий диск», нажимаем значок выбора образа жесткого диска, в открывшемся окне нажимаем «Добавить», выбираем распакованный ранее файл образом ВМ и нажимаем «Открыть»:
И нажимаем «Создать»:
Выбираем в списке созданную ВМ и нажимаем «Запустить»:
После запуска ВМ появится окно для входа в ОС:
Выбираем учетную запись osboxes.org и вводим пароль osboxes.org. После входа в систему нажимаем Ctrl+Alt+T, у нас откроется окно терминала, в котором можно выполнять тесты:
Для удобства можно развернуть окно виртуальной машины на весь экран, окно терминала также будет развернуто. Для того, чтобы можно было вставлять данные из буфера в терминал ВМ и копировать их, можно включить в настройках ВМ общий буфер обмена в меню «Устройства -> Общий буфер обмена -> Двунаправленный»:
Создадим тестового пользователя.
Для создания пользователя нам понадобятся права суперпользователя (root). Для их получения выполним команду sudo su — , указав пароль текущего пользователя (osboxes.org). Далее создадим пользователя test командой adduser test . Также выдадим пользователю test права на повышение привилегий при необходимости, выполнив команду usermod -aG sudo test :
На данном этапе уже можно использовать тестовую среду, выполняя команды в терминале (Ctrl+Alt+T). Дополнительно можно настроить подключение по ssh клиентом (например, PuTTY), мы рассмотрим это отдельно.
3. Первые команды
Итак, мы подключились к терминалу и находимся в shell. Давайте сориентируемся в пространстве. Чтобы узнать имя машины(сервера), на которой мы находимся, введем hostname и нажмем Enter:
Имя пользователя, под которым мы подключены, как правило отображается в приглашении командной строки (test@osboxes:
$). Если имя текущего пользователя не отображается (например, если задан другой формат приглашения), то его можно получить командой whoami , или id (также отображает группы пользователя):
Чтобы узнать, в какой оболочке мы находимся, нужно выполнить команду echo $SHELL :
Разберем, что произошло. Команда echo выводит значение параметра, переданного ей, в нашем случае мы передали $SHELL. Знак $ означает, что мы обращаемся к переменной, т.е. $SHELL возвращает значение переменной SHELL, заданной в окружении. Список значений всех переменных можно получить командой env . Таким образом, отобразив значение переменной, мы видим, что мы находимся в оболочке bash. Оболочка конкретного пользователя указана в файле /etc/passwd, содержимое которого можно получить так:
Команда cat выводит содержимое файла (часть строк в приведенном выводе пропущена и заменена на …). Из файла видим, что для пользователя test указана оболочка /bin/dash. Изменить оболочку текущего пользователя, которая будет загружаться по умолчанию, можно следующей командой(chsh – сокращенное от change shell):
Теперь давайте проверим, в каком каталоге мы находимся, для этого выполним команду pwd :
Для получения списка файлов текущей директории используем команду ls . По соглашению, скрытые файлы начинаются с точки. Для отображения их с помощью команды ls нужно добавить ключ –a. Чтобы отобразить список в расширенном формате, добавим ключ –l. Таким образом команда и её вывод будут выглядеть так:
Для команды ls с параметрами может быть задан синоним (alias), что упрощает её ввод. Список уже заданных синонимов можно получить командой alias :
Видим, что команда ll является синонимом команды ls -alF . Синонимы могут ссылаться на другие синонимы. Так, в приведенном выше примере команда ll выполняет команду ls -alF , в которой ls в свою очередь также является синонимом команды ls —color=auto . Для любой команды с целью упрощения её ввода при частом использовании можно задать синоним. В синонимах также можно использовать переменные среды. Например, чтобы иметь возможность из любой директории получить список файлов домашней директории, можно задать синоним командой alias lshome=’ls -alF $HOME’ , таким образом, можно выполнить:
Здесь командой cd /tmp мы перешли в директорию /tmp, и, находясь в ней, выполнили команду lshome , которая вывела список файлов директории /home/test. При этом в синониме мы ссылаемся на переменную $HOME, в которой содержится путь к домашней директории текущего пользователя.
Алиасы задаются в файле
) означает домашнюю директорию пользователя. В нашем случае /home/test. Также можно задать их в файле
/.bashrc. Здесь нужно сказать пару слов об этих файлах.
При запуске bash в качестве оболочки, сначала выполняется файлы (в случае их наличия), в которых могут быть заданы различные настройки профиля и выполнены различные действия в процессе входа до появления командной строки: сначала выполняется файл /etc/profile, далее bash последовательно ищет и выполняет первый из найденных файлов в следующем порядке:
/.profile. Из указанных файлов могут вызываться и другие.
Так, например, из файла
./profile вызывается файл
/.bashrc, из которого, в свою очередь, в числе прочих, вызывается файл .bash_aliases при его наличии. А файл /etc/profile выполняет также все файлы .sh, находящиеся в директории etc/profile.d.
В bash существуют внутренние команды, их список можно получить командой help. Помощь по конкретной внутренней команде можно получить с помощью команды help , например:
Некоторые внутренние команды bash дублированы в виде исполняемых файлов. Это сделано, чтобы скрипты можно было корректно выполнять в оболочках, в которых не реализованы эти команды. Например, существует исполняемый файл /usr/bin/echo, который реализует функционал внутренней команды echo. Команда help echo выведет справку по внутренней команде, а команда /usr/bin/echo –help выведет справку для соответствующего исполняемого файла. Вывод справки для этих команд отличается, но в целом они реализуют идентичный функционал.
Таким образом, если в оболочке не реализована внутренняя команда echo, скрипт, содержащий вызов echo, сможет успешно выполниться, т.к. для обработки вызова будет использован исполняемый файл /usr/bin/echo. Для поиска выполненных ранее команд можно использовать клавиши «Вверх» и «Вниз», команды из истории можно редактировать и повторно выполнять. В конце статьи приведен список полезных команд.
Если данный материал интересен, то в продолжении статьи я расскажу про скрипты и их параметры, права доступа к файлам, операторы условного выполнения, выбора и циклы, функции и планировщик заданий.
Источник
What do the scripts in /etc/profile.d do?
I am reading about basic shell scripting from Linux Command Line and Shell Scripting Bible.
It says that the /etc/profile file sets the environment variables at startup of the Bash shell. The /etc/profile.d directory contains other scripts that contain application-specific startup files, which are also executed at startup time by the shell.
Why are these files not a part of /etc/profile if they are also critical to Bash startup ?
If these files are application-specific startup files not critical to Bash startup, then why are they part of the startup process ? Why are they not run only when the specific applications, for which they contain settings, are executed ?
3 Answers 3
Why are these files not a part of /etc/profile if they are also critical to Bash startup ?
If you mean, «Why are they not just combined into one giant script?», the answer is:
- Because that would be a maintenance nightmare for the people who are responsible for the scripts.
- Because having the scripts loaded as independent modules makes the whole system more dynamically adjustable — individual scripts can be added and removed without affecting the others. Etc.
- Because they are loaded via /etc/profile which makes them a part of the bash «profile» in the same way anyway.
If these files are application-specific startup files not critical to Bash startup, then why are they part of the startup process ? Why are they not run only when the specific applications, for which they contain settings, are executed ?
That seems to me like a broader design philosophy question that I’ll split into two. The first question is about the value and appropriateness of using the shell environment. Does it have positive value? Yes, it is useful. Is it the best solution to all configuration issues? No, but it is very efficient for managing simple parameters, and also widely recognized and understood. Contrast that to say, deciding to configure such things heterogeneously, perhaps $PATH could be managed by a separate independent tool, preferred tools such as $EDITOR could be in an sqlite file somewhere, $LC lang stuff could be in a text file with a custom format somewhere else, etc — doesn’t just using env variables and /etc/profile.d suddenly seem simpler? You probably already know what an env variable is, how they work and how to use them, vs. learning 5 completely different mechanisms for 5 different ubiquitous aspects of what is appropriately named «the environment».
The second question is, «Is startup the appropriate time for this?», which begs the objection that it is not very efficient (all that data which may or may not get used, etc). But:
- Realistically, it is not all that much data, partially because no one in their right mind would use it for more than a few simple parameters (since there are other means of configuring an application).
- If it is used wisely, with regard to things that are commonly invoked, then setting, eg, default $CFLAGS from a file somewhere every time you invoke gcc would be less efficient. Keep in mind that the amount of memory involved is, again, infinitesimal.
- It can involve systemic things which more than one application may be involved with, and the shell is a common ground.
More could be added to that list, but hopefully this gives you some idea about the pros and cons of the issue — the major ‘pro’ and the major ‘con’ being that it is a global namespace.
Источник
Problem
I have an Ubuntu 11.04 Virtual Machine and I wanted to set up my Java development environment. I did as follows
- sudo apt-get install openjdk-6-jdk
Added the following entries to
Save the changes and exit
Open up a terminal again and typed the following
Nothing happened, like if the export of JAVA_HOME and it’s addition to the PATH were never done.
Solution
/.bashrc and add the following entry towards the end of file
Questions
- Why did I have to do that? I thought bash_profile, bash_login or profile in absence of those two get executed first before bashrc.
- Was in this case my terminal a non-login shell?
- If so, why when doing su after the terminal and putting the password it did not execute profile where I had also set the exports mentioned above?
7 Answers 7
/.bash_profile is only sourced by bash when started in login mode. That is typically when you log in at the console ( Ctrl + Alt + F1 .. F6 ), connect via ssh, or use sudo -i or su — to run commands as another user.
When you log in graphically,
/.profile will be specifically sourced by the script that launches gnome-session (or whichever desktop environment you’re using). So
/.bash_profile is not sourced at all when you log in graphically.
When you open a terminal, the terminal starts bash in (non-login) interactive mode, which means it will source
The right place for you to put these environment variables is in
/.profile , and the effect should be apparent next time you log in.
/.bashrc is the wrong solution. It’s supposed to be the other way around;
/.bash_profile should source
See DotFiles for a more thorough explanation, including some history of why it is like it is.
(On a side note, when installing openjdk via apt, symlinks should be set up by the package, so that you don’t really need to set JAVA_HOME or change PATH )
/.profile file is not loaded.
You can check if your Bash shell is started as a login-shell by running:
If the reply is off you are not running a login shell.
Read the Bash manual’s invocation section on how Bash reads (or does not read) different configuration files.
Excerpt from man bash :
When bash is invoked as an interactive login shell, or as a non-interactive shell with the —login option, it first reads and executes commands from the file /etc/profile , if that file exists. After reading that file, it looks for
/.profile , in that order, and reads and executes commands from the first one that exists and is readable.
su on the other hand also does not start a login shell by default, you have to tell it to do so by using the —login option.
I think it is worth mentioning that you can change the default of gnome-terminal to use a login shell (ie. bash -l) by editing the profile preferences.
go to Edit -> Profile Preferences -> Title and Command tab check the «Run command as a login shell» option
/.bash_profile is evaluating really quickly, which is probably the case. A good thing to check is to chase out any calls to other processes that are usually quite costly.
If you open a terminal or run su the shell is not executed as a login shell but as a normal interactive shell. So it reads
/.bash_profile . You can run su with the -l option to make it run your shell as a login shell.
When you are working with a GUI the shell is usually never run as a login shell so it’s usually fine to put all yout stuff in
TL;DR
In classical recommended ubuntu setup,
/.bash_profile gets evaluated only in specific occasions. And it makes sense.
Put your stuff in
/.bashrc , it’ll get evaluated everytime.
Ok, I want to understand, why does this make sense ?
Keypoints to understand what is going on:
- all processes on linux have and uses environment variables
- environment variables are inherited
- thus setting them once on the father of all your process is enough (especially if it requires some computation time.)
- the father of all your process is typically launched after you log in on your device (give your credentials).
- there are things you might want to do only once when you log in on your computer (check for new mail for instance. ).
So «login» time is typically:
- In console mode, when you login (with Ctrl-Alt F1) or through ssh , as the shell will be the father of all process, it’ll load your
/.bash_profile .
.profile .
Ok, so where to put my stuff ?
It’s rather complex, the full story is here. But here is a run down that is pretty common for ubuntu users. So considering that:
- you use bash shell,
- you have a
/.bash_profile and follow the recommendation to add the loading of
/.bash_profile so as to get at least one file that gets evaluated whatever is the invocation mecanism.
This is a quick suggestion of where to put things.
/.bashrc (Gets evaluated in all occasion, provided you follow the recommendation)
For fast-evaluation environment variable and code for your user-only and bash-only command-line usage (aliases for instance). bashism are welcome.
It gets loaded on itself upon:
- make a new shell window/pane in graphical sessions.
- calling bash
- screen new pane or tab. (not tmux !)
- any bash instance in a graphical console client ( terminator / gnome-terminal . ) if you don’t tick option «run command as login shell».
And it will get loaded in all the other occasion thanks to the prior recommendation.
/.bash_profile (Gets evaluated in specific occasion only)
For slow-evaluation environment variable and code for your user-only and console-session processes. bashism are welcome. It gets loaded on:
- console login (Ctrl-Alt F1),
- ssh logins to this machine,
- tmux new pane or windows (default settings), (not screen !)
- explicit calls of bash -l ,
- any bash instance in a graphical console client ( terminator / gnome-terminal . ) only if you tick option «run command as login shell».
/.profile (Gets evaluated only in graphical-session)
For slow-evaluation environment variables and with no-bashism for your user-only and all graphical-session processes. It gets loaded upon login in your graphical UI.
Источник