Казалось бы, можно дать клиенту урезанный шелл и контролировать исполнение «опасных» команд при помощи sudo. Однако даже если с точки зрения безопасности удается все удачно «разрулить», это не решает всех проблем. Клиента приходится учить основам работы в командной строке, отвечать на шквал вопросов и разбираться, что и почему у него не получается. Время, затрачиваемое на поддержку, увеличивается значительно.
Пытаясь найти решение я наткнулся на описание модуля Cmd для Python. Данный модуль позволяет с минимальными затратами написать подобие интерфейса командной строки c необходимым набором команд.
Начнем с небольшого скрипта-каркаса, который можно будет дополнять командами по мере необходимости. Вот он. Всего 25 строчек. Даже под спойлер прятать не надо.
#!/usr/bin/env python # -*- coding: utf-8 -*- import cmd class Cli(cmd.Cmd): def __init__(self): cmd.Cmd.__init__(self) self.prompt = "> " self.intro = "Добро пожаловать\nДля справки наберите 'help'" self.doc_header ="Доступные команды (для справки по конкретной команде наберите 'help _команда_')" def do_hello(self, args): """hello - выводит 'hello world' на экран""" print "hello world" def default(self, line): print "Несуществующая команда" if __name__ == "__main__": cli = Cli() try: cli.cmdloop() except KeyboardInterrupt: print "завершение сеанса..."
Cохраним файл как cli.py и запустим. Скрипт бодро поприветсвует нас и выдаст приглашение командной строки. Вот пример его работы:
$ ./cli.py Добро пожаловать Для справки наберите 'help' > help Доступные команды (для справки по конкретной команде наберите 'help _команда_') =========================================================================== hello help > help hello hello - выводит 'hello world' на экран > hello hello world > завершение сеанса...
Вернемся к коду. Мы унаследовали класс Cli от Сmd, переопределили несколько свойств для вывода приветствия и начальной справки на родном языке. А так же дописали два метода — default и do_hello. Метод default определяет поведение командной строки в случае, если набранная пользователем команда не существует. На методе do_hello остановимся подробней.
Метод do_hello описывает единственную команду нашего cli (ну, кроме доступной по умолчанию help) — hello. Модуль cmd следует соглашению, по которому методы вида do_command преобразуются в команды command в cli. Комментарий в тройных кавычках, идущий первой строкой в теле метода преобразуется в справку по этой команде. В аргументе args в метод передается строка пользовательских аргументов. Например, если пользователь в консоли набрал «hello everyone» переменная args будет содержать строку «everyone». В данном случае мы просто игнорируем аргументы командной строки.
По умолчанию доступно автодополнение (по табуляции) и история команд (стрелочка вверх). Так же доступна встроенная команда «help» (она же — "?"), которая при помощи обильной дозы магии преобразует комментарии в коде скрипта в справку по командам.
Имея данный скрипт-каркас, мы можем расширять функциональность нашего интерфейса командной строки, добавляя в код нужные методы вида do_cmd. Например, удалим не несущую полезной нагрузки команду hello и добавим несколько полезных команд для мониторинга системы.
#!/usr/bin/env python # -*- coding: utf-8 -*- import cmd import os class Cli(cmd.Cmd): def __init__(self): cmd.Cmd.__init__(self) self.prompt = "> " self.intro = "Добро пожаловать\nДля справки наберите 'help'" self.doc_header ="Доступные команды (для справки по конкретной команде наберите 'help _команда_')" def do_show_cpu(self, args): """show_cpu - нагрузка на процессоры""" os.system("sar 2") def do_show_mem(self, args): """show_mem - использование RAM""" os.system("free") def do_show_disk(self, args): """show_disk - свободное место на диске""" os.system("df -h") def do_show_net(self, args): """show_net - сетевые параметры""" os.system("/sbin/ifconfig") os.system("/sbin/route -n") def do_show_log(self, args): """show_log - системный журнал""" os.system("sudo tail -f /var/log/messages") def default(self, line): print "Несуществующая команда" def emptyline(self): pass if __name__ == "__main__": cli = Cli() try: cli.cmdloop() except KeyboardInterrupt: print "завершение сеанса..."
Наш новоиспеченный шелл готов. Переместим его в место, доступное для чтения всем пользователям системы. Например в /usr/local/bin/. Возможно, путь к нашему скрипту нужно будет прописать в /etc/shells.
Добавляем пользователя с нашим шеллом и пробуем:
# adduser user --shell /usr/local/bin/cli.py ... root@laptop:~# su - user Добро пожаловать Для справки наберите 'help' > ? Доступные команды (для справки по конкретной команде наберите 'help _команда_') =========================================================================== help show_cpu show_disk show_log show_mem show_net > show_cpu Linux 3.5.0-17-generic (dima-laptop) 04/03/2013 _x86_64_ (4 CPU) 02:38:03 PM CPU %user %nice %system %iowait %steal %idle 02:38:05 PM all 0.63 0.00 0.25 0.13 0.00 98.99 02:38:07 PM all 1.00 0.00 0.25 0.25 0.00 98.50 ^C> show_mem total used free shared buffers cached Mem: 3911236 2123408 1787828 0 124156 994752 -/+ buffers/cache: 1004500 2906736 Swap: 4393980 0 4393980 >
ссылка на оригинал статьи http://habrahabr.ru/post/175321/
Добавить комментарий