Linux Tools: shells, ash #1 - ash startup and arguments

linux linux-tools shell ash

ash - это минималистичный shell, который предоставляет меньше удобств по сравнению с bash, но по функционалу для скриптинга совместим с bash.

Первая статья: Linux Tools: shells - историческая часть

Следующая статья: Linux Tools: shells, , ash #2 - ash syntax, simple commands

В первой статье серии немного рассмотрели историю развития шеллов, на практике в статье “Linux First: Загрузка ядра” мы уже использовали ash в качестве login shell и пришло время разобраться подробнее с режимами запуска и аргументами.

Документации на ash в busybox нет, поэтому смотреть можно доку на dash — https://man7.org/linux/man-pages/man1/dash.1.html, тем более что сейчас в busybox за основу взята именно эта версия.

Interactive shell

Шелл может быть запущен в интерактивным и неинтерактивном режимах. По умолчанию ash запускается в интерактивном режиме, принудительно можно включить режим опцией -i. В этом режиме команды ожидаются из stdin - стандартного input потока.

Пара слов про потоки (streams), каждый linux-процесс имеет три потока: stdin, stdout, stderr.

Подробнее с потоками и дескрипторами разбираться будем в серии Linux First.

Интерактивный режим позволяет вводить, редактировать и выполнять команды снова, видеть ошибки выполнения команд, в общем напрямую взаимодействовать с системой.

Запуск shell-скриптов - non-interactive shell

Противоположность интерактивному режиму - запуск скриптов с помощью ash, это режим включается при указании пути к скрипту или аргумента -c

$ ash ./test.sh

$ ash -c 'echo 100500'

С этим режимом связано довольно много аргументов ash, помогающих разрабатывать скрипты.

noexec - аргумент -n

Проверка скрипта без выполнения команд. Работает только при выполнении файла-скрипта, но не работает при указании команд через -c.

$ cat test.sh
echo 123 && exit 0

$ ash test.sh
123

$ ash -n test.sh

У последней команды не будет никакого вывода, потому что указан аргумент -n и команды echo и exit не будет выполнены, но в случае именно ошибки синтаксиса выведется текст ошибки и ненулевой exit code.

$ cat test.sh
& echo 123 && exit 0

# '&' в начале это ошибка в shell-скрипте

$ ash -n test.sh
./test.sh: line 1: syntax error: unexpected "&"

Конечно этот режим не проверяет наличие самих команд, но для проверки синтаксиса удобно.

verbose - аргумент -v

В stderr будет записано все что ash читает в процессе работы.

Например, в login-режиме (про него далее) читается файл $HOME/.profile и выполняются команды из него – с опцией -v все содержимое .profile будет записано в stderr для отладки.

xtrace - аргумент -x

С этим аргументом каждая выполняемая команда будет записано в stderr

$ cat test.sh
echo 123 && exit 0

$ ash -x test.sh
+ echo 123
123
+ exit 0

Вообще все опции включатся через - , а выключаются через + // кажется что нелогично и должно быть наоборот

В интерактивном режиме тоже можно включать опции с помощью builtin-команды set

$ set -x

# xtrace ВКЛючен

$ set +x

# xtrace ВЫКЛючен

errexit - аргумент -e

С -e все непротестированные команды (без проверки exit-кода через if, elif) будут приводить к завершению скрипта.

Для примера рассмотрим скрипт с листингом несуществующей директории.

$ cat test.sh
ls /none; echo 'good'

$ ash test.sh
ls: /none: No such file or directory
good
$ echo $?
0

При обычном запуске команды ls и echo выполняются независимо друг от друга и echo будет выполнено после ls // конечно в данном случае нужно использовать &&, но об этом в следующих статьях

С аргументом -e выход из скрипта произойдет после ls и скрипт завершится с ненулевым exit-кодом.

$ ash -e test.sh
ls: /none: No such file or directory
$ echo $?
1

Еще один полезный момент — передача параметров при запуске скрипта. Все аргументы после указания пути к скрипту считаются позиционными аргументами и могут быть почитаны в скрипте из переменных $1, $2

$ cat test.sh
echo $1
echo $11

$ ash test.sh 1 2 3 4 5 6 7 8 9 10 11
1
11

Отдельно стоит отметить $0 - это переменная содержит путь к скрипту

$ cat test.sh
echo $0

$ ash ./test.sh
./test.sh

login shell

Еще одним режимом запуска является login, включается опцией -l или передачей первым аргументом символа -.

$ ash -l

$ ash -

Работает в interactive и non-interactive режимах.

Смысл режима инициализировать окружение для пользователя. В login-режиме ash ищет и выполняет shell-скрипты /etc/profile и $HOME/.profile. Если в этих файлах указать и экспортировать переменную ENV, в которой указать путь к файлу, его содержимое также будет обработано и выполнено как shell-скрипт на этапе запуска.

ENV=$HOME/.shinit; export ENV

 

Arguments

Для полноты картины пройдемся по всем аргументам команды bash

 

-a

allexport

Экспорт env-переменных // не увидел разницы с обычным режимом, все назначенные переменные окружения и так видны внутри shell при запуске

$ env -i TEST=100 ash -c 'echo $TEST'
100

$ env -i TEST=100 ash -a -c 'echo $TEST'
100

-c

Режим выполнения команд, выполняет команды указанные после аргумента

$ ash -c 'echo 100500'
100500

-C

noclobber // не колошматить 😃

тут речь про оператор > при перенаправление потока в файл, по умолчанию этот оператор создает или перезаписывает содержимое файла, аргумент -C меняет это поведение — если файл уже существует, произойдет ошибка.

# скрипт записывает значение первого аргумента в файл tmp.txt
$ cat ./test.sh
echo $1 > tmp.txt

# выполняем
$ ash ./test.sh 100

# в файл записано 100
$ cat tmp.txt
100

# выполняем еще раз
$ ash ./test.txt 101

# файл перезаписан со значением 101
$ cat tmp.txt
101

# выполняем c аргументом -C - получаем ошибку
$ ash -C ./test.txt 102
test.sh: line 1: can't create test.txt: File exists

-e

errexit

Этот аргумент рассмотрели выше — выход из скрипта, если команда завершается с ненулевым exit-кодом и не обработана условиями типа if

-f

noglob

В шеллах существует прекрасная штука - file globbing - это возможность указывать путь к файлам не полностью, а, например, через wildcard — cat *.txt — вывести на экран все файлы с расширением txt.

Так вот опция -f отключает file globbing для выполняемого скрипта.

$ cat test.sh
# this is script
cat *.sh

# выводит все файлы с расширением sh
$ ash test.sh
# this is script
cat *.sh

file globbing отключен - *.sh интерпретируется как имя файла
$ ash -f test.sh
cat: can't open '*.sh': No such file or directory

-n

noexec

Не выполняет команды, удобно для проверки синтаксиса, подробнее рассмотрели выше

-u

nounset

Завершать скрипт с ошибкой если происходит обращение к переменной, которая не определена.

$ cat test.sh
echo $SOME

# скрипт успешно выполнен, хотя переменная SOME не определена
$ ash test.sh

# с аргументом -u присходит ошибка
$ ash -u test.sh
test.sh: line 1: SOME: parameter not set

-v

verbose

Выводит в stderr все shell-файлы, которые ash читает и выполняет

-x

xtrace

Выводит в stderr все команды, которые ash выполняет

-I

ignoreeof

Игнорирует EOF (символы конца строки) из stdin

// Пока не очень понятно зачем это нужно, но работает так

# echo передает EOF (/n) после строки и скрипт выводит содержимое файла скриптов
$ echo 'cat *.sh' | ash
echo $SOME

# с -I конец строки игнорируется и будет ошибка
$ echo 'cat *.sh' | ash -I
Use "exit" to leave shell.

Use "exit" to leave shell.

...

-i

interactive

принудительно включается интерактивный режим

-l

login

Включает login-режим

-m

monitor

включает job control, автоматически включается в интерактивном режиме, видимо позволяет включать работу с jobs в скриптах // рассмотрим позже, но уже интересно — можно запустить задачу фоном в скрипте, а потом проконтролировать ее и завершить скрипт

-s

stdin

читать скрипт из stdin. Если не указан путь к скрипту, то включено.

$ echo 'date' | ash
Fri Dec 24 00:38:31 UTC 2020

# идентично c -s
$ echo 'date' | ash -s
Fri Dec 24 00:38:31 UTC 2020

# но не работает если указан скрипт
$ echo 'date' | ash -s test.sh
# test script commands

# при этом выполняются обе команды с -c и -s
$ echo 'date' | ash -s -c 'date'
Fri Dec 24 00:38:31 UTC 2020
Fri Dec 24 00:38:31 UTC 2020

 

Итого

Сегодня разобрали запуск ash, режимы и аргументы, в следующих статьях начнем разбирать возможности скриптов, синтаксис и команды.

Следующая статья: Linux Tools: shells, ash #2 - ash syntax, simple commands

 

Ссылки


Все статьи серии “Linux Tools”