Лекция №20 Интерпретатор bash

Начиная с этой лекции мы будем говорить о командном интерпретаторе bash (”баш“), который является потомком самого первого интерпретатора - sh или shell (”шелл“). Иногда говоря shell подразумевают bash, а говоря bash подразумевают shell. Разница между этими названиями иногда весьма условная.Мы же будем говорить именно о bash (Bourne again Shell).

Все это время мы работали в системе через командный интерпретатор bash. Или другими словами, мы взаимодействовали с системой через интерпретатор bash. Это так называемый интерактивный режим работы с системой. Кроме этого можно взаимодействовать с системой с помощью скриптов. Скрипт - представляет собой текстовый файл, в котором последовательно выполняются какие либо действия (программы, команды, другие скрипты). Если необходимо каждый день выполнять какие либо действия (например архивацию данных и копирование их на резервный сервер), то удобно записать такие действия в виде скрипта и затем вызывать только имя скрипта (или автоматизировать работу с помощью демона cron).

Каким образом bash понимает, что перед ним скрипт, а не простой текстовый файл? Если помните, то в Linux нет понятия расширения файла, и хотя для удобства некоторые называют файлы скриптов в виде *.sh, для интерпретатора это не имеет никакого значения. Основной указатель находится внутри файла. Когда вы запускаете программу, выполняете команду или скрипт, bash начинает анализировать первые символы файла в первой строке. Если bash встречает в начале символы ELF (Executable and Linkable Format), то это значит, что файл является скомпилированным файлом программой (аналог exe-файлов в Windows). Если первые символы в файле будут #!, то bash делает следующее. Берет остальные символы после #! и до конца строки (символа перевода на новую строку), через пробел добавляет имя последней команды (то есть имя скрипта) и выполняет полученную команду. Возможно сразу сложно разложить по полочкам, поэтому давайте на примере (нам понадобятся две консоли).

Наберите в текстовом редакторе следующий текст:

#!/bin/bash
sleep 100

Сохраните файл допустим с именем sleep.sh и не забудьте сделать его исполняемым (установить бит x):

igor@ubuntu:~/linux$ chmod u+x sleep.sh

Теперь запустим этот файл на исполнение:

igor@ubuntu:~/linux$ ./sleep.sh

Теперь во второй консоли выполните команду:

igor@ubuntu:~$ ps ax | grep bash
4861 pts/0 Ss 0:00 bash
4955 pts/1 Ss 0:00 bash
5011 pts/0 S+ 0:00 /bin/bash ./sleep.sh

Посмотрите на примере на процесс с PID 5011 - /bin/bash ./sleep.sh. bash взял символы первой строки после #!, а это /bin/bash и через пробел добавил имя последней команды - ./sleep.sh и запустил полученную конструкцию /bin/bash ./sleep.sh в виде отдельного процесса.

Чтобы стало еще понятнее измените содержание файла sleep.sh на следующее:

#!/bin/ls -l

и выполните скрипт:

igor@ubuntu:~/linux$ ./sleep.sh
-rwxr–r– 1 igor igor 13 2009-12-15 22:04 ./sleep.sh

Надеюсь, вам понятно почему именно такой результат выполнения полученного скрипта.

В большинстве случаев после #! указывается полный пусть к интерпретатору для которого написан скрипт. Например, если текст содержащийся в скрипте написан на языке perl, то первая строка будет выглядеть как #!/usr/bin/perl . Так как мы изучаем bash, то в наших примерах эта строка будет такой как в первом примере: #!/bin/bash . В зависимости от дистрибутива у вас могут быть установлены и другие интерпретаторы (например sh, dash, csh и т.д.). Интерпретатор sh является более старым, более простым и считается, что более быстрым чем bash. Конфигурационные скрипты системы могут начинаться со строки #!/bin/sh и если в системе не установлен интерпретатор sh, создают символическую ссылку в каталоге /bin с именем sh, которая ссылается на существующий интерпретатор (например тот же bash). Делается это для того, чтобы не переписывать первую строку #!/bin/sh у всех существующих в системе скриптов.

Чтобы определить некоторую информацию об исполняемом файле интерпретатора (и не только интерпретатора) можно воспользоваться следующими тремя командами: type, file и ldd. Команда type покажет где bash находит исполняемый файла той или иной команды, file покажет тип файла (скрипт, ELF и т.д.), ldd - покажет какие библиотеки необходимы для работы ELF-файла.

igor@ubuntu:~/linux$ type bash
bash является /bin/bash

igor@ubuntu:~/linux$ file /bin/bash
/bin/bash: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped

igor@ubuntu:~/linux$ ldd /bin/bash
linux-gate.so.1 => (0×00375000)
libncurses.so.5 => /lib/libncurses.so.5 (0×00db1000)
libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0×00ba8000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0×00210000)
/lib/ld-linux.so.2 (0×001f3000)

А вот пример с символической ссылкой:

SLES:~ # type sh
sh is /bin/sh

SLES:~ # file /bin/sh
/bin/sh: symbolic link to `bash’

Как раз тот случай, когда sh, это bash.

Теперь поговорим о потоках ввода/вывода.
Далее на лекции был разговор о потоках ввода/вывода. Вопрос этот не простой, преподаватель много говорил, рисовал схемы, все записать не успевал, поэтому, чтобы не терять время на восстановление этой темы предлагаю прочесть очень хорошее описание потоков в этой статье (автору - спасибо). Хотя достаточно будет прочесть раздел “Потоки и файлы” (это как раз то, что нам рассказывали на лекции), но рекомендую ознакомиться со статей полностью.

На следующей лекции продолжим знакомство с bash уже как с языком программирования и начнем рассматривать его основные конструкции.

Читать другие лекции по курсу Администратор ПК с Linux

Статьи и новости схожей тематики:

Один комментарий

  1. Dimon:

    кстати “#!” называется “sha-bang”

    Ответить

Оставьте свой отзыв