python

Управление Windows компьютерами из консоли Linux

  • четверг, 4 июня 2015 г. в 02:10:42
http://habrahabr.ru/post/259469/

Здесь рассматривалась задача управления компьютером на Windows из Linux. Решалась с помощью winexe.

Подобная задача удаленной установки софта, проверки состояния, дистанционного выключения/перезагрузки большой группы Windows компьютеров (учебные классы) ниже решается с помощью freeSSHd — ssh-сервера для Windows.

На сайте лежит только последняя версия freeSSHd — 1.3.1. У меня она работает неустойчиво (иногда падает сервис). Предыдущая версия — 1.2.4 — работает прекрасно от XP до Win8.1, хотя и есть небольшой эксплоит — но вроде ничего кроме, как завалить сервис FreeSSHDService не получается, поэтому можно закрыть на это глаза. На всякий случай положил эту версию здесь (размер — 782456)

Запускаем установщик, в процессе меняем путь установки («C:\Program Files (x86)\FreeSSHD») на C:\bin\FreeSSHD — так проще его найти на системах с разной архитектурой и конфиг будет везде одинаковый. (C:\bin надо предварительно создать.)

Дальше все по умолчанию — в конце запускается сервис FreeSSHDService. Его можно настроить, щелкнув значок в трее, но проще скопировать готовые настройки в файл настроек C:\bin\FreeSSHD\FreeSSHDService.ini и рестартануть сервис.
Пример FreeSSHDService.ini:
[Telnet server]
TelnetListenAddress=0.0.0.0
TelnetListenPort=23
TelnetMaxConnections=0
TelnetTimeout=0
TelnetBanner=
TelnetCMD=C:\Windows\system32\cmd.exe
TelnetRun=0
TelnetNewConsole=1
[SSH server]
SSHListenAddress=0.0.0.0
SSHListenPort=22
SSHMaxConnections=0
SSHTimeout=0
SSHBanner=
SSHCMD=C:\Windows\system32\cmd.exe
SSHRun=1
SSHNewConsole=1
SSHCiphers=0
SSHMACs=65535
SSHPasswordAuth=0
SSHPublickeyAuth=0
SSHPublickeyPath=C:\bin\freeSSHd\
RSAKeyPath=C:\bin\freeSSHd\RSAKey.cfg
DSAKeyPath=C:\bin\freeSSHd\DSAKey.cfg
[SSH tunneling]
SSHLocalTunnel=0
SSHLocalTunnelOnly=0
SSHRemoteTunnel=0
SSHRemoteTunnelOnly=0
[SFTP]
SFTPHomePath=$HOME\
[Access filtering]
HostRestrictions=
HostRestrictionsAllow=0
[Logging]
LogEvents=0
LogFilePath=C:\bin\freeSSHd\freesshd.log
LogResolveIP=0
[Automatic updates]
UpdateCheckOnStartup=0
UpdateDontPrompt=0
UpdateShowMessages=1
UpdateLastMessageID=0
[Users]
UserCount=1
[User0]
Name=admin
Auth=2
Password=000000000000000000000000000000000000000000
Domain=
Shell=1
SFTP=1
Tunnel=1

Теперь надо дооформить объявленного юзера admin — создать файл C:\bin\FreeSSHD\admin и записать туда публичный ключ.

Либо используем уже имеющийся id_dsa.pub, либо в консоли Linux набираем
/# ssh-keygen -t dsa

и получаем пару ключей — id_dsa и id_dsa.pub
На Windows копируем id_dsa.pub в каталог C:\bin\FreeSSHD и переименовываем в C:\bin\FreeSSHD\admin

Рестартуем сервис FreeSSHDService:
net stop FreeSSHDService & net start FreeSSHDService


На Linux проверяем подключение (листинг корня C:\):
/# ssh -2q -i <my_key_files_path>/id_dsa -ladmin -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null <Win_Host_IP> "cmd /c dir c:\\"

Если хост отверг подключение (на win7-win8 вероятно), настраиваем Брандмауэр в «Центре управления сетями ...»:
Брандмауэр Windows -> устранение неполадок в сети -> входящие подключения -> что-то другое -> обзор -> C:\bin\FreeSSHD\FreeSSHDService.exe

Если все получилось, копируем каталог C:\bin\FreeSSHD\ на все прочие компы — тогда во время установки FreeSSHD задаст гораздо меньше вопросов и запустится уже настроенный. Можно, конечно, это все и настройку Брандмауэра реализовать через Group Policy, но я этим не заморачивался — все компы клонировались из одного удачного образа.

Теперь на любом компе можно выполнить любую (почти) команду.
Например, перезагрузка:
/# ssh -2q -i <my_key_files_path>/id_dsa -ladmin -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null <Win_Host_IP> "cmd /c shutdown /r /t 1"


Установка 1с (тихая):
/# ssh -2q -i <my_key_files_path>/id_dsa -ladmin -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null \
 <Win_Host_IP> "cmd /c  start \\\\<Server_IP>\\buh\\1Ccurrent\\setup /s"

Поскольку доступ консольный, то при попытке запуска программы с GUI надо использовать запуск из нового окна — «start ». Хотя тихая установка 1C и не требует GUI.

Когда компьютеров много, запуск команд по очереди неэффективен, надо форкать сессии.
Демо-програмка на Python, которая опрашивает компы в диапазоне 192.168.0.210-192.168.0.220 и записывает их имена в лог /tmp/rexec.log. Не ответившие помечаются как NA, а зависшие сессии — ?T:
#!/usr/bin/python
# -*- coding: utf-8 -*-

log = '/tmp/rexec.log'
host_range = range(210,220)
ip_first_3 = '192.168.0'
my_key = '/root/.ssh/id_dsa'

my_cmd = 'hostname' #имена компов
#my_cmd = 'shutdown /s /t 10' #выключить 
#my_cmd = r'\\\\srv1\\shar1\\mycmd.bat' # выполнить командный файл с сетевого ресурса

import os,sys,time,subprocess
from datetime import datetime

try:
    cmd = '/usr/bin/ssh -2q -oBatchMode=yes -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -i%s -ladmin %s.%%d "cmd /c %s " ' % (my_key,ip_first_3,my_cmd)
    procs,out,err = [],[],[]
    for x in host_range:
        xcmd = cmd % x
        procs.append([x,subprocess.Popen(xcmd,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,shell=True,bufsize=4096,executable='/bin/bash')])
    for i in range(0,20): #20 циклов по 1 сек
        stop = True
        for proc in procs:
#            print i, proc[0]
            if proc[0] == 0: continue
            try: 
                res = proc[1].poll()
                if res == None: 
                    stop = False
                    continue
                if res == 0: out.append("%d:%s" % (proc[0],proc[1].stdout.read().splitlines()[0])) #берем только 1 строку вывода !
                else: err.append("%d:NA" % proc[0])
            except: err.append("%d:EX" % proc[0])
            proc[0]=0
        if stop: break
        time.sleep(1)
    if not stop: #убиваем оставшиеся сессии    
        for proc in procs:
            if proc[0] != 0:
                proc[1].terminate()
                err.append("%d:?T" % proc[0])
    s = "%s|%s" % ('; '.join(out),'; '.join(err))
except:
    s = "!!! Error"
print s
with open(log, "ab") as fp:
    fp.write("--- %s cmd=%s\n" % (datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S"),my_cmd))
    fp.write(" Result: %s\n" % s)

(Исходная программа была CGI-скриптом, отсюда такой минимализм вывода)

Сложные и длинные команды лучше оформлять в виде пакетного файла и размещать в доступном сетевом пути. На Samba ресурсе надо дать файлу права на выполнение и оформить концы строк в стиле Windows.