[Перевод] Статический анализатор ShellCheck и улучшение качества скриптов в Linux и Unix
Написание shell-скриптов — занятие увлекательное. Скрипты командной строки помогают автоматизировать повседневные дела. Можно создать нечто прекрасное (или какую-нибудь гадость), однако, если уж что-то писать, хорошо бы точно знать, что код получается именно таким, каким он нужен программисту. Скрипт, написанный некачественно, может представлять опасность. Большинство новичков пишут скрипты, копируя фрагменты кода со StackOverflow, находя то, что им нужно, в Google, или пользуясь сайтами с вопросами и ответами по Linux. Такой подход к программированию выливается в некачественный код и в появление ошибок. Вот, например, команда rm
, выполнение которой приведёт к катастрофе, так как переменная VAR
не определена:
rm -rf "/$VAR/*"
Многие из проблем скриптов можно решить с помощью линтера, такого, как статический анализатор кода ShellCheck, который написан на Haskell. Он помогает искать ошибки в текстах скриптов и выводить отчёты о проведённых проверках. Это позволяет повысить производительность работы и качество кода. Сегодня мы расскажем о том, как установить и использовать ShellCheck в Linux и Unix-подобных операционных системах.
Установка
Самый простой способ локальной установки ShellCheck заключается в использовании применяемого в вашем дистрибутиве менеджера пакетов вроде apt/apt-get/yum и других.
▍Установка ShellCheck в Debian/Ubuntu Linux
Тут понадобится следующая команда apt / apt-get:
$ sudo apt install shellcheck
Вот пример реакции системы на эту команду:
[sudo] password for vivek:
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
shellcheck
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 1,841 kB of archives.
After this operation, 15.5 MB of additional disk space will be used.
Get:1 http://in.archive.ubuntu.com/ubuntu artful/universe amd64 shellcheck amd64 0.4.6-1 [1,841 kB]
Fetched 1,841 kB in 42s (43.4 kB/s)
Selecting previously unselected package shellcheck.
(Reading database ... 196100 files and directories currently installed.)
Preparing to unpack .../shellcheck_0.4.6-1_amd64.deb ...
Unpacking shellcheck (0.4.6-1) ...
Setting up shellcheck (0.4.6-1) ...
Processing triggers for man-db (2.7.6.1-2) ...
▍Установка ShellCheck в CentOS/RHEL/Fedora/Oracle Linux
Сначала нужно включить репозиторий EPEL в CentOS/RHEL:
$ sudo yum -y install epel-release
Дальше надо ввести следующую команду yum:
$ sudo yum install ShellCheck
Вот что будет выведено в ответ на эту команду:
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base: centos.excellmedia.net
* epel: mirror.nes.co.id
* extras: mirrors.vonline.vn
* updates: centos-hcm.viettelidc.com.vn
Resolving Dependencies
--> Running transaction check
---> Package ShellCheck.x86_64 0:0.3.5-1.el7 will be installed
--> Processing Dependency: ghc(ShellCheck-0.3.5-297097a7f5fa37100847be7f096be51e) for package: ShellCheck-0.3.5-1.el7.x86_64
.....
..
...
Dependencies Resolved
===============================================================================
Package Arch Version Repository Size
===============================================================================
Installing:
ShellCheck x86_64 0.3.5-1.el7 epel 495 k
Installing for dependencies:
ghc-ShellCheck x86_64 0.3.5-1.el7 epel 540 k
ghc-array x86_64 0.4.0.1-26.4.el7 epel 113 k
ghc-base x86_64 4.6.0.1-26.4.el7 epel 1.6 M
ghc-bytestring x86_64 0.10.0.2-26.4.el7 epel 182 k
ghc-containers x86_64 0.5.0.0-26.4.el7 epel 287 k
ghc-deepseq x86_64 1.3.0.1-26.4.el7 epel 45 k
ghc-directory x86_64 1.2.0.1-26.4.el7 epel 59 k
ghc-filepath x86_64 1.3.0.1-26.4.el7 epel 60 k
ghc-json x86_64 0.7-4.el7 epel 96 k
ghc-mtl x86_64 2.1.2-27.el7 epel 33 k
ghc-old-locale x86_64 1.0.0.5-26.4.el7 epel 50 k
ghc-parsec x86_64 3.1.3-31.el7 epel 105 k
ghc-pretty x86_64 1.1.1.0-26.4.el7 epel 57 k
ghc-regex-base x86_64 0.93.2-29.el7 epel 28 k
ghc-regex-compat x86_64 0.95.1-35.el7 epel 15 k
ghc-regex-posix x86_64 0.95.2-30.el7 epel 47 k
ghc-syb x86_64 0.4.0-35.el7 epel 39 k
ghc-text x86_64 0.11.3.1-2.el7 epel 379 k
ghc-time x86_64 1.4.0.1-26.4.el7 epel 187 k
ghc-transformers x86_64 0.3.0.0-34.el7 epel 100 k
ghc-unix x86_64 2.6.0.1-26.4.el7 epel 160 k
Transaction Summary
===============================================================================
Install 1 Package (+21 Dependent packages)
Total download size: 4.6 M
Installed size: 28 M
Is this ok [y/d/N]: y
Downloading packages:
(1/22): ghc-bytestring-0.10.0.2-26.4.el7.x86_64.rpm | 182 kB 00:09
(2/22): ghc-array-0.4.0.1-26.4.el7.x86_64.rpm | 113 kB 00:09
....
..
...
ghc-parsec.x86_64 0:3.1.3-31.el7
ghc-pretty.x86_64 0:1.1.1.0-26.4.el7
ghc-regex-base.x86_64 0:0.93.2-29.el7
ghc-regex-compat.x86_64 0:0.95.1-35.el7
ghc-regex-posix.x86_64 0:0.95.2-30.el7
ghc-syb.x86_64 0:0.4.0-35.el7
ghc-text.x86_64 0:0.11.3.1-2.el7
ghc-time.x86_64 0:1.4.0.1-26.4.el7
ghc-transformers.x86_64 0:0.3.0.0-34.el7
ghc-unix.x86_64 0:2.6.0.1-26.4.el7
Complete!
Если вы пользуетесь Fedora, выполните следующую команду dnf:
$ sudo dnf install ShellCheck
▍Установка ShellCheck в Arch Linux
Введите следующую команду pacman:
$ sudo pacman -S shellcheck
▍Установка ShellCheck в Gentoo Linux
Введите такую команду emerge:
$ sudo emerge --ask shellcheck
▍Установка ShellCheck в OpenSUSE Linux
Введите следующую команду zypper:
$ sudo zypper in ShellCheck
▍Установка ShellCheck в macOS Unix
Воспользуйтесь следующей командой port если вы работаете с MacPorts:
$ port install shellcheck
Если вы пользуетесь Homebrew в macOS/OS X, введите такую команду brew:
$ brew install shellcheck
Как пользоваться ShellCheck
Испытаем ShellCheck на скрипте, содержимое которого просмотрим с помощью команды cat:
$ cat -n backupme
Вот его код:
#!/bin/bash
t="/tmp/exclude.$$"
source ~/.backup.conf
>$t
for w in $WHATNOT
do
echo $w >> $t
done
rsync $OPT -avr --exclude-from=$t $WHAT $SERVER:$WHERE
rm -rf $t
Теперь проверим скрипт с помощью ShellCheck:
$ shellcheck backupme
В ответ программа выдаст следующее:
ShellCheck в действии
Утилита ShellCheck предложила внести исправления, касающиеся использования переменных, не заключённых в кавычки, а также сообщила о других проблемах. Исправим ошибки и снова просмотрим текст скрипта следующей командой:
$ cat -n backupme
Вот что, в итоге, получилось:
#!/bin/bash
t="/tmp/exclude.$$"
source ~/.backup.conf
touch $t
for w in $WHATNOT
do
echo "$w" >> $t
done
rsync "$OPT" -avr --exclude-from=$t "$WHAT" "$SERVER:$WHERE"
rm -rf "$t"
Интеграция ShellCheck в текстовый редактор
ShellCheck можно интегрировать в vim или emacs, в результате, он будет проверять тексты скриптов прямо в редакторе. Тут показано применение плагина для vim neomake, асинхронного средства для линтинга и сборки программ. Он был установлен с использованием менеджера плагинов vim-plug в ~/.vimrc
:
call plug#begin('~/.vim/plugged')
Plug 'pearofducks/ansible-vim'
" install and use neomake linting
Plug 'neomake/neomake'
call plug#end()
Для установки ansible-vim
и neomake/neomake
, введите в vim следующую команду:
:PlugInstall
Для использования плагина введите следующую команду, редактируя bash/sh-скрипт:
:Neomake
Вот как выглядят результаты работы плагина в редакторе:
Neomake выводит предупреждения и сообщения об ошибках с помощью ShellCheck
Итоги
Полагаем, ShellCheck — это замечательный инструмент, который позволяет улучшать и исправлять скрипты командной строки Linux. Он способен обнаруживать множество распространённых недоработок и ошибок в их коде. Если вы хотите узнать о SpellCheck больше — вот сайт проекта, а вот — его репозиторий на GitHub.
Уважаемые читатели! Проверяете ли вы свои скрипты чем-то вроде ShellCheck?