Очень часто системным администраторам требуется запустить какую-либо команду на удаленном компьютере, желательно не покидая рабочего места. Это может понадобиться для установки программы или утилиты, изменения каких-либо настроек, да и много для чего еще. И конечно, редко речь идет лишь об одном компьютере, чаще команду требуется выполнить на множестве рабочих станций или серверов.
Поскольку задача это популярная, способов ее решения существует множество, начиная от групповых политик (в которых можно применять для данной цели сценарии регистрации в системе или автозагрузки) и заканчивая мощными системами управления, вроде System Center Essentials или System Center Configuration Manager. Но я в этой статье хочу рассмотреть методы, которые доступны сразу из командной строки или файлов сценариев, а также не требуют предварительной установки агентов и прочей суматохи. Впрочем, какие-то предварительные требования, конечно, есть. Например, у вас должны быть административные полномочия на том компьютере, на котором предстоит выполнить команду (за исключением сценария с «проксированием», но об этом позже).
Запуск PsExec.exe
Один из проверенных помощников в решении данной задачи — утилита командной строки PsExec.exe, написанная Марком Русиновичем, которую можно загрузить с сайта Windows SysInternals. Ссылка на нее приведена в конце статьи. Она не требует установки в систему, достаточно просто скопировать ее в одну из папок, содержащихся в переменной окружения %path%, и вызвать из любой оболочки командной строки: Cmd или PowerShell.
Использовать PsExec очень просто. Например, чтобы выполнить ipconfig/flushdns на компьютере с именем main, достаточно запустить следующую команду:
psexecmain ipconfig/flushdns
Команда ipconfig будет запущена на компьютере main под вашими учетными данными (см. экран 1). После завершения работы ipconfig весь текстовый вывод будет передан на ваш компьютер, а кроме того, будет возвращен код выхода команды (error code). Если команда выполнена успешно, он будет равен 0.
Разумеется, этим возможности PsExec не исчерпываются. Вызвав утилиту без параметров, можно просмотреть другие доступные ключи. Я обращу внимание лишь на некоторые из них.
Ключ -d сообщает PsExec, что не нужно дожидаться выполнения команды, а достаточно лишь запустить ее. В этом случае мы не получим выходных данных от консольной утилиты, но зато сможем, не дожидаясь завершения предыдущей команды, запускать другие. Это очень полезно, если необходимо запустить, например, установщик программы на нескольких компьютерах.
По умолчанию PowerShell выполняет команды в скрытом режиме, то есть на системе, где выполняется команда, не будут выводиться никакие окна. Однако можно это изменить с помощью ключа -i. После него можно указать номер сессии, в которой следует выводить окна, либо не указывать, тогда интерфейс будет отображен в консольной сессии.
Таким образом, чтобы вывести окно с информацией о версии операционной системы на компьютере main, следует запустить PsExec таким образом:
psexec -imain winver.exe
Чтобы выполнить команду сразу на нескольких компьютерах, воспользуемся возможностью прочитать их имена из текстового файла списка (см. экран 2):
psexec @c:comps.txt systeminfo.exe
Наконец, одной из самых полезных функций PsExec является возможность интерактивного перенаправления ввода/вывода между компьютерами, что позволяет нам запустить, например, cmd.exe на удаленном сервере, а давать ему команды и получать результаты на локальном компьютере. Принципы работы PsExec изложены во врезке «Каким образом работает PsExec».
Windows Management Instrumentation (WMI)
Следующий способ реализации удаленного запуска — использование Windows Management Instrumentation. WMI присутствует во всех операционных системах Microsoft, начиная с Windows 2000, и даже на Windows 9 x его можно установить с помощью отдельного пакета. Интерфейс WMI включен по умолчанию и не требует дополнительной настройки. Для его использования достаточно административных прав и разрешенного на брандмауэре протокола DCOM. WMI предоставляет широкие возможности для управления системами, но нас сейчас интересует лишь одна из них.
Для запуска процессов нам потребуется метод Create класса Win32_Process. Использовать его несложно. В PowerShell, например, это делается следующим образом:
$Computer = «main»
$Command = «cmd.exe/c systeminfo.exe
>servershare\%computername%.txt»
([wmiclass]»$Computer oot
cimv2: Win32_Process»).create
($Command)
Здесь в качестве запускаемого процесса я указал cmd.exe, а уже ему в качестве аргументов передал нужную команду. Это необходимо в том случае, если вам нужно использовать переменные окружения удаленного компьютера или встроенные операторы cmd.exe, такие как «>», для перенаправления вывода в файл. Метод Create не дожидается завершения процесса и не возвращает результатов, но зато сообщает нам его идентификатор — ProcessID.
Если на вашем компьютере не установлен PowerShell, можно вызвать этот метод WMI из сценария на VBScript. Пример показан в листинге 1.
Но гораздо проще воспользоваться утилитой командной строки wmic.exe, которая предоставляет достаточно удобный интерфейс для работы с WMI и входит в состав операционных систем начиная с Windows XP. Чтобы в ней запустить, например, калькулятор на компьютере main, достаточно выполнить следующую команду:
wmic/node: main process call create calc.exe
Разумеется, возможности WMI не ограничиваются только запуском процессов. Тем, кого интересует дальнейшее изучение этой технологии, я рекомендую ознакомиться со статьями Константина Леонтьева, посвященными WMI, ссылки на которые можно найти во врезке «Дополнительная литература».
WSH Remote Scripting
Да, как ни странно, в Windows Script Host тоже предусмотрена возможность запуска сценариев на других компьютерах. Правда, эта функция не получила большой популярности, и, скорее всего, из-за того, что требует слишком много подготовительных мероприятий, а взамен предоставляет совсем мало возможностей. Но я все равно расскажу об этом методе, так как кому-то и он может пригодиться.
Итак, для запуска сценария на другом компьютере с помощью WSH понадобится сделать следующее:
-
Права администратора на удаленном компьютере. Это требуется и почти для всех остальных методов запуска, перечисленных в статье.
-
Разрешить запуск WSH Remote Scripting, создав в системном реестре строковый параметр Remote, равный «1» в разделе реестра HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows Script HostSettings.
-
Из-за ошибки, описанной в статье базы знаний Microsoft с номером 311269, на системах с Windows XP может понадобиться выполнить команду wscript -regserver
-
Если на компьютерах используется брандмауэр, то в нем необходимо разрешить обращения к DCOM. Причем сделать это надо не только на управляемом компьютере, но и на том, с которого предполагается запускать сценарий.
-
В системах Windows XP с пакетом обновлений SP2 и выше необходимо изменить параметры безопасности DCOM. Это можно сделать с помощью групповой политики. В узле Computer ConfigurationWindows SettingsSecurity SettingsLocal PoliciesSecurity Options следует установить разрешения следующим образом:
-
DCOM: Machine Access Restrictions in Security Descriptor Definition Language (SDDL) syntax;
-
выдать группам Anonymous Logon и Everyone разрешения Allow Local и Allow Remote Access;
-
DCOM: Machine Launch Restrictions in Security Descriptor Definition Language (SDDL) syntax;
-
выдать группе Administrators разрешения Allow Local Launch, Allow Remote Launch, Allow Local Activation, Allow Remote Activation;
-
группе Everyone — Allow Local Launch, Allow Local Activation.
После завершения всех этих процедур можно попробовать запустить свой сценарий на другом компьютере.
Пример сценария, который использует эту технологию, приведен в листинге 2. Во второй его строчке в качестве параметров для функции CreateScript указывается путь к файлу сценария, который будет выполнен на удаленном компьютере, и собственно имя этого компьютера.
Более подробную информацию о данной технологии можно найти в статье Advanced VBScript for Microsoft Windows Administrators — Chapter 6: Remote Scripting (см. врезку «Дополнительная литература»).
Планировщик заданий
Планировщиком заданий можно управлять из командной строки, используя две утилиты — at.exe и schtasks.exe. Обе программы позволяют указать имя удаленного компьютера для создания задания и, следовательно, позволяют решить нашу задачу. Но подробно мы рассмотрим лишь schtasks.exe, так как она предоставляет гораздо больше возможностей.
Хотя выполнение команд на других компьютерах не является основным предназначением планировщика, тем не менее он позволяет реализовать немало интересных сценариев. Например, с его помощью можно включить установку программного обеспечения в обеденный перерыв. Или если ваши пользователи обедают в разное время, запуск можно выполнять после определенного периода бездействия компьютера.
schtasks/create/s server6.td.local
/tn install/trmaindatainstall.cmd
/sc once/st 13:00/ru system
Важно понимать, от имени какой учетной записи будет выполняться задача. В данном примере я указал для параметра/ru значение system, следовательно, для выполнения установки учетной записи компьютера будет необходим доступ на чтение в сетевую папку с дистрибутивом программы.
Еще мне представляется целесообразным запланировать какое-либо действие на ежедневное выполнение и удалять задачу лишь при подтверждении успеха. То есть можно создать простой командный файл, который сначала запускает установщик программы, дожидается его завершения и проверяет, успешно ли установилась программа. Если это так, он удаляет задание из планировщика на данном компьютере. Пример такого файла приведен в листинге 3.
WinRM (WS-Management)
WinRM — это реализация открытого стандарта DMTF (Distributed Management Task Force) от Microsoft, которая позволяет управлять системами с помощью Web-служб. Углубляться в устройство технологии я не буду, лишь кратко опишу, что необходимо для ее использования.
Версия WinRM 1 и выше входит в состав операционных систем, начиная с Windows Vista и Windows Server 2008. Для Windows XP и Windows Server 2003 можно установить WinRM в виде отдельного пакета (см. врезку «Дополнительная литература»).
Для того чтобы быстро настроить компьютер для обеспечения подключений к нему, используя стандартные порты и разрешив подключения административным учетным записям, достаточно выполнить команду:
winrm quickconfig
Чтобы winrm не запрашивала подтверждение, можно добавить к вызову ключ -quiet. Получить информацию о более тонкой настройке можно из встроенной справки winrm:
winrm help config
Если на управляемом компьютере работает Web-сервер, WinRM ему не помешает, хоть и использует по умолчанию стандартные порты HTTP. Он будет перехватывать лишь подключения, предназначенные специально для него.
Разумеется, необязательно выполнять эту команду вручную на каждом компьютере, которым вы хотите управлять. Все необходимые настройки легко выполнить с помощью групповых политик. Для этого нужно:
-
Настроить службу WinRM (Windows Remote Management) на автоматический запуск.
-
Настроить элемент групповой политики Computer ConfigurationAdministrative TemplatesWindows ComponentsWindows Remote Management (WinRM)WinRM ServiceAllow automatic configuration of listeners. Здесь следует указать диапазоны IP-адресов, с которых разрешаются подключения.
-
Разумеется, еще потребуется разрешить подключения на соответствующие порты (по умолчанию 80) в брандмауэре Windows.
Независимо от того, используется порт HTTP (80) или HTTPS (443), трафик, передаваемый WinRM, шифруется (если, конечно, не отключить эту возможность). Для аутентификации по умолчанию применяется протокол Kerberos.
Но хватит о настройках, перейдем непосредственно к использованию. Хоть утилита winrm и позволяет настраивать службу WinRM, а также выполнять, например, WMI-запросы, нам интереснее другая — winrs. Буквы RS здесь означают Remote Shell. WinRS работает очень похоже на PsExec, хотя и использует технологию WinRM. Имя компьютера задается ключом -r, а после него следует команда, которую нужно выполнить. Вот несколько примеров:
winrs -r: Core ver.exe
Так как winrs уже использует cmd.exe в качестве удаленной оболочки, в командах можно легко обращаться к удаленным переменным окружения либо использовать другие встроенные команды cmd.exe:
winrs -r: Core "dir c: emp > c: emp list.txt"
Как и PsExec, утилита winrs позволяет открыть интерактивный сеанс на удаленном компьютере:
winrs -r: main cmd.exe
Эта функция аналогична сессии telnet, но winrs однозначно лучше telnet и даже PsExec с точки зрения безопасности. Независимо от того, используется ли порт HTTP (80) или HTTPS (443), трафик, передаваемый WinRM, шифруется (если, конечно, не отключить эту возможность). Для аутентификации по умолчанию применяется протокол Kerberos.
Windows PowerShell 2.0 Remoting
Хотя вторая версия Windows PowerShell в данный момент находится еще в состоянии бета-тестирования, о ее возможностях в области удаленного выполнения команд стоит рассказать уже сейчас. Поизучать его можно, либо загрузив предварительную версию (см. ссылки), либо в составе бета-версии Windows 7 или Windows Server 2008 R2.
Инфраструктура PowerShell Remoting основана на WinRM версии 2.0, поэтому наследует все преимущества этой технологии, такие как шифрование передаваемых данных и возможность работать по стандартным портам HTTP/HTTPS. Но благодаря богатым возможностям языка Windows PowerShell и его функциям для работы с объектами мы получаем еще более широкие возможности. На сегодня пакет WinRM2.0 тоже находится в состоянии бета-тестирования и доступен для загрузки только для систем Windows Vista и Windows 2008. В системы Windows 7 и Windows Server 2008 R2 он будет встроен изначально, как и PowerShell 2.0.
Прежде чем воспользоваться всеми этими преимуществами, PowerShell Remoting необходимо активизировать на управляющем и управляемых компьютерах. Сделать это просто, достаточно запустить команду Windows PowerShell, а именно Enable-PSRemoting. Причем, если добавить ключ -Force, то никаких подтверждений система запрашивать не будет. Эта команда при необходимости вызовет winrs quickconfig и создаст исключения в брандмауэре Windows, так что никаких дополнительных действий выполнять не нужно.
После этого вы сможете легко выполнять команды на других компьютерах, используя команду Invoke-Command (или ее псевдоним icm):
Invoke-Command -ComputerName
Main -ScriptBlock {netsh interface
dump > c:ipconfig.txt}
Разумеется, команду можно заранее поместить в переменную, а для параметра -ComputerName указать имена не одного, а сразу нескольких компьютеров. Приведенная ниже последовательность позволяет вывести версию файла Explorer.exe сразу с трех компьютеров.
$Command = {(get-item c:Windows
explorer.exe).VersionInfo.FileVersion}
Invoke-Command -ComputerName Main,
Server7, Replica -ScriptBlock
$Command
Как показано на экране 3, можно передавать сразу несколько команд в одном блоке, помещать их результаты выполнения на нескольких компьютерах в переменную, а затем обрабатывать на рабочей станции, используя возможности Windows PowerShell по работе с объектами.
Впрочем, возможности PowerShell Remoting этим далеко не исчерпываются. С помощью команды Enter-PSSession можно войти в интерактивную сессию Windows PowerShell на удаленном компьютере. Выйти из такого сеанса можно, воспользовавшись командой Exit-PSSession или просто exit.
Команда New-PSSession создает сессии на удаленных компьютерах, указатели на которые можно поместить в переменную, а затем, передавая ее как аргумент для Invoke-Command, выполнять команды сразу на нескольких компьютерах, в постоянном окружении. Пример показан на экране 4, где последовательность команд выполняется сразу на нескольких компьютерах из списка c:computers.txt.
Проксирование
Этот метод отличается от всех перечисленных выше и служит совсем для других задач, но не менее актуален. Когда делегирование полномочий неосуществимо или предоставляет слишком большие возможности, он позволяет разрешить обычному пользователю выполнять некую команду, требующую административных привилегий, никаким образом не выдавая дополнительных полномочий и не подвергая риску пароль администратора.
Чаще всего такие проблемы решаются с помощью утилит вроде cpau.exe (см. врезку «Дополнительная литература»), которые создают файл с зашифрованным паролем административной учетной записи, позволяющий запускать определенную программу. Проблема, однако, в том, что зашифрованный пароль перед запуском программы утилите придется расшифровать. А, соответственно, пользователь может задействовать утилиту, повторяющую алгоритм расшифровки пароля, и узнать его, чтобы затем использовать для запуска других программ или получения дополнительных привилегий. Сделать это, конечно, довольно сложно для обычных пользователей, не обладающих специальными знаниями, но тем не менее вполне возможно. Еще раз уточню: это не беда конкретной утилиты, а проблема такого подхода вообще.
Еще может показаться, что для решения задачи подойдет параметр/savecred утилиты runas. Но здесь есть даже две проблемы. Во-первых, как и в описанном выше случае, пароль сохраняется на компьютере пользователя, а следовательно, может быть расшифрован, хотя в случае с runas для этого понадобятся права локального администратора. Во-вторых, runas сохраняет учетные данные, не связывая их с конкретной командой, а следовательно, пользователь сможет запустить с повышенными правами не только ту команду, доступ к которой администратор хотел ему предоставить, но и любую другую.
Чтобы избежать подобных проблем, но тем не менее разрешить выполнение конкретной команды, можно использовать методику, которая называется «проксированием».
Работает она следующим образом. На компьютере постоянно функционирует сценарий с высокими привилегиями. Например, в нашем случае он будет запущен из-под учетной записи, обладающей правами администратора на файловом сервере. По сигналу пользователя он будет выполнять одну заранее определенную команду. В данном примере — закрывать все файлы, открытые по сети.
Для организации этой системы мы поместим на сервере, например в папке c:scripts, командные файлы Server.cmd (см. листинг 4) и Action.cmd (см. листинг 5).
Server.cmd будет ждать сигнала от пользователя (создание файла в определенном месте) и, получив его, запускать файл с командами — Action.cmd. Разумеется, к этой папке пользователи не должны иметь доступа. Автоматический запуск Server.cmd при запуске компьютера можно организовать, просто создав соответствующую задачу в планировщике:
schtasks/create/ru domainadministrator
/rp/sc onstart/tn ProxyScript
/tr c:scriptsserver.cmd
После параметра/ru указывается учетная запись, под которой будет выполняться сценарий (в нашем случае она обладает правами администратора на сервере), так как после параметра/rp пароль не указан — он будет запрошен при создании задачи. Параметр/sc позволяет указать момент запуска сценария, в нашем случае — при включении компьютера. Ну а /tn и /tr позволяют указать имя задачи и исполняемый файл.
Теперь для того чтобы пользователь мог подать сценарию сигнал, мы создадим папку c:commandShare и сделаем ее доступной по сети. Доступ на запись в эту папку должен быть только у тех пользователей, которые будут запускать команду.
После этого достаточно будет поместить пользователю на рабочий стол файл Run.cmd (см. листинг 6). При его выполнении от имени пользователя будет создаваться файл servercommand
Share rigger.txt. Сценарий Server.cmd, заметив его, запустит на выполнение со своими привилегиями файл Action.cmd, добавит запись в файл c:scriptslog.txt о текущем времени, а затем удалит trigger.txt, чтобы не выполнять команду снова до следующего сигнала пользователя.
В сценарии Server.cmd применяется утилита Sleep.exe, позволяющая сделать паузу в выполнении сценария на заданный в секундах промежуток времени. Она не входит в состав операционной системы, но ее можно взять из набора Resource Kit Tools (см. врезку «Дополнительная литература») и скопировать на любой компьютер.
Василий Гусев (xaegr@yandex.ru) — системный администратор, MVP: Admin Frameworks
Дополнительная литература
PsExec.exe — http://technet.microsoft.com/ru-ru/sysinternals/bb897553.aspx
Windows SysInternals — http://technet.microsoft.com/ru-ru/sysinternals/default.aspx
WMI — http://www.script-coding.info/WMI_Processes.html
BUG: You receive an «ActiveX component can't create object» error message when you Use Windows Script Host to execute remote script — http://support.microsoft.com/kb/311269
Advanced VBScript for Microsoft Windows
Administrators — Chapter 6: Remote
Scripting — http://www.microsoft.com/technet/scriptcenter/topics/remote/rscripting.mspx
Вы все еще не используете WMI?
Часть 1 — http://www.samag.ru/art/01.2006/01.2006_02.html
Вы все еще не используете WMI?
Часть 2 — http://www.samag.ru/art/02.2006/02.2006_02.html
Узнай секреты WMI: события и провайдеры — http://www.samag.ru/art/03.2006/03.2006_05.html
Узнай секреты WMI: события и провайдеры — http://www.samag.ru/art/05.2006/05.2006_07.html
WS-Management v1.1 для Windows XP и Windows Server 2003 http://support.microsoft.com/kb/KB936059
CPAU.exe — http://www.joeware.net/freetools/tools/cpau/index.htm
Windows PowerShell 1.0 — http://www.microsoft.com/powershell/download
Windows PowerShell 2.0 Community Technology Preview 3 — http://go.microsoft.com/fwlink/?LinkID=131969
WinRM 2.0 Community Technology Preview 3 — http://go.microsoft.com/fwlink/?LinkID=131971
Windows Server 2003 Resource Kit Tools — http://www.microsoft.com/downloads/details.aspx?familyid=9D467A69-57FF-4AE7-96EE-B18C4790CFFD
Как работатет PsExec?
Все гениальное просто. В ресурсах исполняемого файла PsExec.exe находится другой исполняемый файл – PSEXESVC, который является службой Windows. Перед выполнением команды PsExec распаковывает этот ресурс на скрытую административную общую папку удаленного компьютера, в файл:ИмяКомпьютераAdmin$system32psexesvc.exe. Если вы с помощью ключа -c указали, что необходимо скопировать исполняемые файлы на данную систему, они тоже скопируются в эту папку.
По завершении подготовительных действий PsExec устанавливает и запускает службу, используя API-функции Windows для управления службами. После того как PSEXESVC запустится, между ним и PsExec создается несколько каналов для передачи данных (вводимых команд, результатов и т. д.). Завершив работу, PsExec останавливает службу и удаляет ее с целевого компьютера.
Выполнение блока команд и обработка результатов в PowerShell 2.0