Интерфейс с удаленными компьютерами с использованием Python - PullRequest
5 голосов
/ 20 августа 2009

Я только что стал системным администратором кластера моей исследовательской группы и в этом отношении я новичок. Я пытаюсь создать несколько инструментов для мониторинга сети, и мне нужна помощь, чтобы начать реализовывать их с помощью Python (мой родной язык).

Например, я хотел бы посмотреть, кто вошел на удаленные машины. Вручную, я бы ssh и who, но как мне получить эту информацию в сценарий для манипуляции? Что-то вроде

import remote_info as ri
ri.open("foo05.bar.edu")
ri.who()

Out[1]: 
hutchinson tty7         2009-08-19 13:32 (:0)
hutchinson pts/1        2009-08-19 13:33 (:0.0)

Аналогично для таких вещей, как cat /proc/cpuinfo, чтобы получить информацию о процессоре узла. Отправной точкой было бы действительно здорово. Спасибо.

Ответы [ 6 ]

2 голосов
/ 20 августа 2009

Я использовал Pexpect , который позволяет вам подключаться к машинам, отправлять команды, читать выходные данные и успешно реагировать на них. Я даже начал проект с открытым исходным кодом, Proxpect - который не обновлялся годами, но я отвлекся ...

2 голосов
/ 20 августа 2009

Вот простое, дешевое решение для начала

from subprocess import *
p = Popen('ssh servername who', shell=True, stdout=PIPE)
p.wait()
print p.stdout.readlines()

возвращает (например)

['usr      pts/0        2009-08-19 16:03 (kakapo)\n',
 'usr      pts/1        2009-08-17 15:51 (kakapo)\n',
 'usr      pts/5        2009-08-17 17:00 (kakapo)\n']

и для cpuinfo:

p = Popen('ssh servername cat /proc/cpuinfo', shell=True, stdout=PIPE)
1 голос
/ 20 августа 2009

Если вам нужно перерасти в простое «ssh remote-host.example.org who», то есть замечательная библиотека python, которая называется RPyC . Он имеет так называемый «классический» режим, который позволяет почти прозрачно выполнять код Python по сети с несколькими строками кода. Очень полезный инструмент для доверенных сред.

Вот пример из Википедии:

import rpyc
# assuming a classic server is running on 'hostname'
conn = rpyc.classic.connect("hostname")

# runs os.listdir() and os.stat() remotely, printing results locally
def remote_ls(path):
    ros = conn.modules.os
    for filename in ros.listdir(path):
        stats = ros.stat(ros.path.join(path, filename))
        print "%d\t%d\t%s" % (stats.st_size, stats.st_uid, filename)

remote_ls("/usr/bin")

Если вам интересно, в их вики есть хороший учебник .

Но, конечно, если вы прекрасно справляетесь с ssh-вызовами, использующими Popen или просто не хотите запускать отдельный демон "RPyC", то это определенно излишество.

1 голос
/ 20 августа 2009

Модуль pexpect может помочь вам взаимодействовать с ssh. Более или менее, вот как будет выглядеть ваш пример.

child = pexpect.spawn('ssh servername')
child.expect('Password:')
child.sendline('ABCDEF')
(output,status) = child.sendline('who')
0 голосов
/ 20 августа 2009

Fabric - это простой способ автоматизации некоторых простых задач, таких как эта, версия, которую я сейчас использую, позволяет вам обернуть команды следующим образом:

run('whoami', fail='ignore')

Вы можете указать параметры конфигурации (config.fab_user, config.fab_password) для каждой машины, которая вам нужна (если вы хотите автоматизировать обработку пароля для имени пользователя).

Подробнее о ткани здесь:

http://www.nongnu.org/fab/

Есть новая версия, которая является более Pythonic - я не уверен, будет ли это лучше для вас в его случае ... работает хорошо для меня в настоящее время ...

0 голосов
/ 20 августа 2009

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

Кроме того, имейте в виду, что вы должны запустить ssh-agent, чтобы это "имело смысл". Но в целом, это работает очень хорошо. Запуск deploy-control httpd configtest проверит конфигурацию apache на всех удаленных серверах.

#!/usr/local/bin/python

import subprocess
import sys

# The user@host: for the SourceURLs (NO TRAILING SLASH)
RemoteUsers = [
        "deploy@host1.example.com",
        "deploy@host2.appcove.net",
        ]

###################################################################################################
# Global Variables
Arg                             = None


# Implicitly verified below in if/else
Command = tuple(sys.argv[1:])

ResultList = []
###################################################################################################
for UH in RemoteUsers:
        print "-"*80
        print "Running %s command on: %s" % (Command, UH)

        #----------------------------------------------------------------------------------------------
        if Command == ('httpd', 'configtest'):
                CommandResult = subprocess.call(('ssh', UH, 'sudo /sbin/service httpd configtest'))

        #----------------------------------------------------------------------------------------------
        elif Command == ('httpd', 'graceful'):
                CommandResult = subprocess.call(('ssh', UH, 'sudo /sbin/service httpd graceful'))

        #----------------------------------------------------------------------------------------------
        elif Command == ('httpd', 'status'):
                CommandResult = subprocess.call(('ssh', UH, 'sudo /sbin/service httpd status'))

        #----------------------------------------------------------------------------------------------
        elif Command == ('disk', 'usage'):
                CommandResult = subprocess.call(('ssh', UH, 'df -h'))

        #----------------------------------------------------------------------------------------------
        elif Command == ('uptime',):
                CommandResult = subprocess.call(('ssh', UH, 'uptime'))

        #----------------------------------------------------------------------------------------------
        else:
                print
                print "#"*80
                print
                print "Error: invalid command"
                print
                HelpAndExit()

        #----------------------------------------------------------------------------------------------
        ResultList.append(CommandResult)
        print


###################################################################################################
if any(ResultList):
        print "#"*80
        print "#"*80
        print "#"*80
        print
        print "ERRORS FOUND.  SEE ABOVE"
        print
        sys.exit(0)

else:
        print "-"*80
        print
        print "Looks OK!"
        print
        sys.exit(1)
...