rc — простой и чистый shell из Plan 9

Содержание
- Что такое Plan 9?
- Установка оболочки rc
- Использование и написание простых скриптов rc
- Базовые операторы: переменные, файлы, пайпы
- Управление потоком: условия, циклы, функции
- Советы, сравнения и когда не использовать rc
- Частые вопросы
Что такое Plan 9?
Plan 9 — это экспериментальная операционная система, разработанная в Bell Labs как преемник идей UNIX с целью упростить модель операционной системы и сделать её более однородной. Разработка началась в 1980-х годах; после официального завершения активной разработки многие компоненты поддерживаются сообществом. Plan 9 сохранил знакомый набор утилит (cp, mv, rm), но переосмыслил некоторые концепции — например, работу с пространством имён, сетевыми ресурсами и единообразным доступом к ресурсам через файловую модель.

Ключевые идеи Plan 9, полезные для понимания rc как оболочки:
- Простая и единообразная файловая модель: почти всё представлено как файлы и каталоги.
- Стремление к ясности интерфейсов и минимальной грамматике.
- Инструменты разработаны так, чтобы их можно было комбинировать и скриптовать простыми, предсказуемыми способами.
Одна из неклассических составляющих экосистемы — текстовый редактор sam и графический интерфейс acme; многие из утилит доступны в Linux через проект plan9port, который собирает и адаптирует софт Plan 9 для POSIX-сред.

Особое внимание в Plan 9 уделяется оболочке rc: она короче и проще по синтаксису, чем традиционные POSIX-оболочки, и её цели — предсказуемость и обучаемость.

Установка оболочки rc
Установка rc в Linux обычно выполняется через подключение репозитория plan9port и запуск входящего в него установщика. Ниже — развернутая и адаптированная инструкция.
Важное примечание: команды и пути в примерах предполагают стандартную файловую структуру и относительные права доступа. Меняйте /home/$USER на соответствующую домашнюю директорию в вашей системе.
- Склонируйте репозиторий plan9port на локальную машину:
git clone https://github.com/9fans/plan9port.git /home/$USER/plan9port
cd /home/$USER/plan9port- Запустите скрипт установки, который соберёт билдера Plan 9 и далее остальные утилиты:
./INSTALLПроцесс может занять несколько минут в зависимости от мощности машины и наличия зависимостей. На системах с ограниченными ресурсами компиляция может потребовать дополнительного времени.

- После сборки быстрый запуск утилит возможен из директории bin внутри репозитория:
./bin/acmeЭто запустит графический редактор acme (если ваша система поддерживает запуск графики из собранных утилит).

- Чтобы использовать утилиты plan9port из любой директории, добавьте каталог bin в переменную окружения PATH. В Bash-подобных оболочках это делается, например, так:
# Откройте файл профиля (пример для bash)
nano /home/$USER/.bash_profile
# Добавьте в конец файла одну из строк (в зависимости от оболочки):
export PATH="$PATH:/home/$USER/plan9port/bin"
# или для zsh
export PATH="$PATH:/home/$USER/plan9port/bin"После сохранения выйдите из сессии или выполните source /home/$USER/.bash_profile, чтобы обновить PATH в текущей сессии.

Совет: если вы используете system-wide установку или пакетный менеджер (редко встречается для plan9port), проверьте инструкции поставщика пакета. Для локального использования plan9port достаточно добавить bin напрямую в PATH.
Использование и написание простых скриптов rc
Чтобы запустить rc из план9портовского набора утилит, выполните:
9 rcКоманда переключит приглашение оболочки на символ %, что указывает на работу в среде rc. Внутри оболочки доступны и привычные POSIX-утилиты (если они установлены в PATH).
% ls
Ниже раскрыты основные элементы языка rc, которые чаще всего используются при написании скриптов.
Базовые операторы: переменные, файлы, пайпы
rc проектировался для простоты: синтаксис переменных и операций выглядит компактно и последовательно. Основные концепции:
- Переменные в rc — это просто имена, которым присвоены строки или списки; они не имеют строгих типов.
- Операции ввода-вывода используют перенаправления и пайпы, похожие на POSIX, но с некоторыми отличиями в выражениях.
Переменные и операции с файлами
Создание и запись значений в переменные простое:
test=helloВывод содержимого переменной в файл (append):
echo $test >> world.txtЧтение из файла как ввод в программу:
cat < world.txtОбратите внимание на пробелы вокруг операторов и на префикс $ при подстановке переменной.

Важно: в rc меньше специальных правил экранирования по сравнению с bash — строки объявляются одинарными кавычками, и многие управляющие символы внутри них не интерпретируются.
UNIX-пайпы и ветвящиеся пайпы
rc поддерживает традиционные пайпы вида cmd1 | cmd2, но также допускает нетривиальные формы, когда несколько источников направляются в один приёмник. Пример из rc:
cat world.txt | lessБолее необычный пример — объединение нескольких потоков как ввода в одну команду с использованием синтаксиса перенаправлений:
cmp <{echo hello} <{echo helloo}В этом примере обе команды echo создают отдельные подстановки ввода, которые сравниваются cmp. Такой стиль позволяет строить нелинейные конвейеры данных.

Цепочки команд и проверка кодов возврата
В rc можно выполнять несколько команд подряд, разделяя их точкой с запятой:
echo hello-world >> hello.txt; less hello.txtДля условного выполнения используются операторы && и ||, аналогично POSIX-подходу:
cmd1 && cmd2— выполнить cmd2, если cmd1 завершилась успешно.cmd1 || cmd2— выполнить cmd2, если cmd1 завершилась с ошибкой.
Пример:
mkdir ./hello && touch ./hello/world
Строки и списки
Основная философия rc — упрощение работы со строками и списками. В отличие от bash, rc использует одинарные кавычки для литералов, что уменьшает путаницу с экранированием.
Пример различия:
# rc
hello='[world]'
# bash
hello='\[world\]'Списки в rc — это просто группы слов в круглых скобках:
shop=(eggs milk cheese rice beef)Чтобы вывести элементы списка по индексам (rc использует 1‑начальную нотацию в подстановках), можно применить форму:
echo $shop(123)Это выведет первые три элемента списка (1,2,3).

Управление потоком: условия, циклы, функции
rc — полноценный язык для скриптов, который поддерживает условные выражения, циклы и пользовательские функции. Благодаря лаконичному синтаксису многие конструкции записываются компактно и читаются легче, чем их эквиваленты в более громоздких shell-языках.

Условные операторы
Базовая форма однострочного условного оператора:
if( условие ) действиеГде “условие” — это список команд; любая команда, завершившаяся успешно (код 0), трактуется как “истина”. Например:
if( test -r hello.world ) echo 'there is a hello world!'Здесь test -r проверяет, доступен ли файл на чтение, и если да — выполняется echo.

Циклы for
Общий синтаксис однострочного цикла:
for( i in step ) действиеГде step — это либо список элементов, либо результат выполнения программы. Внутри цикла i получает очередное значение.
Пример перебора файлов в каталоге:
for( f in ./hello/* ) if( test -r $f ) echo $f
Функции
Объявление функции в rc простое и компактное:
fn имя {
набор_команд
}Пример функции, которая проходит по файлам и сообщает об их наличии:
fn hello {
for(i in ./hello/*) if(test -r $i) echo 'There is a file here!'
}Важно: в rc можно писать определения компактно в одну строку или расширенно — выбор зависит от читабельности.

Продвинутые приёмы и обработка ошибок
rc поддерживает гибкие механизм перенаправления файловых дескрипторов. Для разделения диагностического вывода (stderr) и основного (stdout) используется конструкция вида:
./script.rc >[2=1] ./error.logЭто перенаправляет дескриптор 2 (stderr) в файл ./error.log через копирование в дескриптор 1. Такой способ удобен при диагностике и логировании.
Также помните о следующих практиках:
- Всегда используйте явные проверки существования файла в скриптах, если действия зависят от наличия ресурсов.
- Для критичных операций делайте резервное копирование или используйте временные файлы перед перезаписью.
- При переносе скриптов на POSIX-системы учитывайте различия в экранировании и наборе внутренних команд (rc не реализует все bash-расширения).
Сравнение: rc и традиционные оболочки (bash/sh)
Ниже — краткая сравнивающая таблица по ключевым аспектам:
| Аспект | rc | bash / sh |
|---|---|---|
| Простота грамматики | Очень лаконична и последовательна | Много исторических исключений и вариантов кавычек |
| Работа со списками | Встроенные списки в скобках | Массивы в bash, но синтаксис сложнее |
| Совместимость с POSIX | Ограниченная (не POSIX shell) | Полная для POSIX-совместных систем |
| Учебная ценность | Высока — для понимания базовых идей shell | Высока — если нужно знать практическую совместимость |
| Нестандартные возможности | Ветки пайпов, простая модель перенаправлений | Множество расширений и утилитного кода |
Принципиальное правило: выбирайте rc для обучения, экспериментов и там, где важна лаконичность; выбирайте bash/sh для сценариев, которые должны работать на широком наборе серверов и дистрибутивов без дополнительных зависимостей.
Когда rc не подходит
- Если ваш скрипт должен исполняться в окружениях, где plan9port недоступен или запрещён. Для максимальной переносимости используйте POSIX-совместимые sh-скрипты.
- Для сложных скриптов со множеством системных проверок лучше использовать bash или язык общего назначения (Python), где есть богатая стандартная библиотека.
- Если ваша команда уже автоматизирует инфраструктуру с помощью стандартных инструментов CI/CD, добавление нестандартной оболочки усложнит сопровождение.
Практический чеклист: быстрая проверка перед публикацией rc-скрипта
- [ ] Скрипт запускается в план9port-окружении (проверьте
9 rc). - Явно проверены входные файлы и права доступа.
- Ошибки логируются через перенаправление stderr при необходимости.
- Нет хардкодированных путей без переменных окружения.
- В документации указано требование plan9port или инструкция по установке.
Шпаргалка (cheat sheet) — часто используемые шаблоны
# Запуск rc из plan9port
9 rc
# Переменная и вывод
name='Ivan'
echo $name >> out.txt
# Список
shop=(eggs milk cheese)
echo $shop(12) # вывести первые два элемента
# Цикл
for(i in $shop) echo $i
# Условие
if(test -r file.txt) echo 'file exists'
# Функция
fn greet { echo 'Hello' $1 }
# Перенаправление ошибок
./script >[2=1] error.logПринятие решений: когда переходить на rc
Mermaid-диаграмма ниже помогает быстро решить, стоит ли пробовать rc в проекте:
flowchart TD
A[Нужна ли переносимость между серверами?] -->|Да| B[Использовать POSIX / bash]
A -->|Нет| C[Нужно ли простое и понятное синтаксис?]
C -->|Да| D[Попробовать rc]
C -->|Нет| E[Использовать Python или другой язык]
D --> F{Требуется интеграция с существующими инструментами}
F -->|Да| B
F -->|Нет| G[Оставить rc как локальный инструмент]Ролевые чеклисты
Для разработчика:
- Проверьте окружение plan9port.
- Напишите тесты для критичных ветвей скрипта.
- Добавьте краткую документацию для коллег.
Для системного администратора:
- Решите, допустима ли зависимость от plan9port в окружении.
- Организуйте снапшот или резервную копию перед развёртыванием.
- Подготовьте fallback-скрипт на POSIX, если требуется.
Частые вопросы
Как узнать количество элементов в списке в rc?
Чтобы получить количество элементов списка, перед именем списка ставят двойную кавычку ". Пример:
echo $"shopЭто выведет число элементов, хранящихся в переменной shop.
Можно ли создать бесконечный цикл в rc?
Да. Для бесконечного цикла в rc можно опустить условие в поле шага, но скобки обязательны. Пример бесконечного вывода:
for(i) echo helloЭтот цикл будет печатать “hello” бесконечно, пока его не прервёт пользователь (Ctrl+C) или внешний сигнал.
Как передавать и логировать ошибки, как >2 в bash?
В rc для управления файловыми дескрипторами используется расширенный синтаксис. Чтобы сохранить ошибки в файл, можно применить:
./script.rc >[2=1] ./error.logЭто направит stderr в файл error.log через копирование дескриптора 2 в дескриптор 1.
Советы по миграции и совместимости
- Если требуется совместимость с POSIX, оберните критичные участки в POSIX-совместимые скрипты или предоставьте оболочку-адаптер.
- Для команд, которые используются в скриптах, документируйте поведение и ожидаемые коды возврата.
- Тщательно тестируйте редиректы и пайпы — поведение может отличаться от bash в пограничных случаях.
Резюме
rc — лаконичная и понятная оболочка, полезная для обучения и локальных автоматизаций. Она доступна в Linux через plan9port и предлагает упрощённую модель работы со строками, списками и потоками ввода-вывода. Для продакшн-скриптов с требованиями переносимости лучше выбирать POSIX-совместимый shell, но для быстрых экспериментов и простых задач rc часто выигрывает за счёт читаемости и прямолинейности.
Важно: перед развёртыванием в командную инфраструктуру оцените совместимость и поддерживаемость plan9port в вашей среде.
Image credits: Unsplash. Все скриншоты: Ramces Red.