- PVSM.RU - https://www.pvsm.ru -

CLI на питоне. Пускаем пользователя на сервер

CLI на питоне. Пускаем пользователя на серверЯ системный администратор по роду деятельности. Поддерживаю удаленно сервера разных клиентов. Нередко приходится слышать от клиента просьбу дать шелл-доступ на сервер. С одной стороны просьба вполне обоснованная: сервер не мой, да и доступ клиенту нужен, чтоб меня же не дергать по пустякам (скажем, посмотреть, не закончилось ли место на диске или все ли процессы запущены). С другой стороны клиент зачастую практически не имеет опыта работы в unix, и нет никакой гарантии, что я смогу все исправить после того, как клиент по незнанию сотрет что-нибудь с диска или заблочит мне доступ, удалив правила фаервола. Зачастую клиенты и сами это понимают, но настаивают на предоставлении им доступа, не видя другого выхода.

Казалось бы, можно дать клиенту урезанный шелл и контролировать исполнение «опасных» команд при помощи sudo. Однако даже если с точки зрения безопасности удается все удачно «разрулить», это не решает всех проблем. Клиента приходится учить основам работы в командной строке, отвечать на шквал вопросов и разбираться, что и почему у него не получается. Время, затрачиваемое на поддержку, увеличивается значительно.

Пытаясь найти решение я наткнулся на описание модуля Cmd [1] для 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
> 

Автор: facha

Источник [2]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/python/31125

Ссылки в тексте:

[1] Cmd: http://docs.python.org/2/library/cmd.html

[2] Источник: http://habrahabr.ru/post/175321/