Справочник командной строки
Каждая команда, каждый параметр и каждый код завершения bws, версия 0.5.0. Авторитетна bws --help, и она длиннее - эта страница показывает ту же поверхность, разложенную так, чтобы её было удобно читать.
Команды
Одиннадцать команд. snapshot - существительное и принимает после себя слово. tool тоже существительное, и само по себе оно перечисляет инструменты.
bws list [--query TEXT] [--signatures] [--memory] [--required-by] [--follow-network] [--json] [--timing]
bws show NAME [--full] [--follow-network] [--json] [--timing]
bws stop|start|restart NAME [--dry-run] [--dependents] [--timeout SECONDS] [--json] [--timing]
bws kill NAME [--force] [--restart] [--dry-run] [--dependents] [--timeout SECONDS] [--json] [--timing]
bws start-type NAME automatic|delayed|manual|disabled [--stop] [--dry-run] [--json] [--timing]
bws snapshot create [FILE] [--note TEXT] [--follow-network] [--force] [--json] [--timing]
bws snapshot diff EARLIER LATER [--exit-code] [--json] [--timing]
bws snapshot diff EARLIER --live [--exit-code] [--json] [--timing]
bws history [NAME] [--json] [--timing]
bws tool
bws tool fix
bws tool fix NAME [--dry-run] [--timeout SECONDS] [--json] [--timing]
bws license [--components]
bws --help
bws --version
Для неверно набранной команды предлагается та, которую вы, вероятно, имели в виду, и выполнение завершается кодом 2, а не делает что-то близкое к тому, что вы просили.
$ bws lst
There is no command lst. Did you mean list?
Что делает каждая команда
list и show
list - это вся машина, суженная параметром --query. show - одна запись со всем, что о ней известно: подпись, привилегии, дескриптор безопасности и память, всё это читается каждый раз, потому что для одной записи это стоит около шестидесяти миллисекунд, а для всей машины - секунду. Поля, которые действительно пусты, опускаются, пока вы не передадите --full. Поле, которое никто не смог прочитать, печатается в любом случае, потому что его пропуск выглядел бы как ответ.
stop, start и restart
Каждая строит план и выполняет его. --dry-run печатает план и ничего не меняет, --dependents включает в него службы, которые сломались бы, как отдельные шаги, а --timeout говорит, сколько один шаг может идти без прогресса. Драйверы отклоняются, а не пробуются, потому что остановка драйвера ядра часто необратима без перезагрузки.
kill - для службы, которая не останавливается
Он просит службу остановиться и завершает стоящий за ней процесс, только если это не сработало, поэтому запись, которая останавливается сама, никогда не завершается принудительно. Завершение процесса уносит с собой каждую другую службу, живущую в этом процессе, остановились они до этого или нет, а предпросмотр называет их и называет процесс по номеру. --force пропускает вежливый шаг, и предпросмотр тогда показывает один шаг вместо двух. --restart потом возвращает всё обратно.
Windows пишет эту идею иначе. --force у Stop-Service означает «даже если что-то от неё зависит», а это здесь делает --dependents. Поэтому это отдельная команда, а не параметр у stop.
start-type - настройка, а не действие
Он говорит, что диспетчер сделает с записью при следующей загрузке, и без --stop ничего не двигает: работающая запись продолжает работать, остановленная остаётся остановленной, и план говорит об этом. disabled - то, на чём стоит задержаться, потому что оно вообще не даёт диспетчеру запускать запись, в том числе по требованию для чего-то другого, что в ней нуждается. delayed - это автоматический запуск чуть позже остальных автоматических записей, слово, о котором спрашивает start:delayed в запросе, - и Windows отказывает в нём для записи из группы порядка загрузки, о чём план сообщает до того, как что-либо произойдёт. Каждый из четырёх записывает, запускается ли запись с задержкой, как это делает sc.exe. --stop, только вместе с disabled, останавливает запись в том же плане после записи настройки.
snapshot create и snapshot diff
create всегда читает подписи и хеши, потому что снимок хранится и сравнивается позже, а снимок без них при сравнении со снимком с ними выглядел бы так, будто машина изменилась. diff говорит, что изменилось при переходе от первого файла ко второму или от файла к этой машине с --live. Страница о снимках содержит формат и обоснование.
history - кто изменил, по журналу System
Изменения типа запуска и установки из журнала System, новые первыми, с учётной записью, которую записала Windows. Первая строка говорит, насколько далеко назад уходит журнал и не очищался ли он, потому что история длится не дольше журнала. С именем это изменения типа запуска этой службы: установки перечисляются только без имени, потому что Windows записывает установку под отображаемым именем и никогда под именем службы. Учётная запись называется там, где эта машина может назвать её сама, а иначе показывается как SID, а типы запуска приходят теми словами, которыми их записала Windows.
tool - готовые ответы на частые проблемы
Те же инструменты, что окно показывает на вкладке Tools. bws tool перечисляет их, а bws tool fix перечисляет быстрые исправления: printer, sound, indexing и search, каждое - перезапуск одной службы Windows вместе с тем, что от неё зависит, выбранный потому, что его предлагают собственные страницы Microsoft по устранению неполадок. bws tool fix printer - это в точности bws restart Spooler --dependents: тот же план, тот же вывод и те же коды завершения, - и, как каждая команда здесь, что-то меняющая, она не спрашивает заранее, поэтому --dry-run - способ посмотреть, прежде чем она выполнится.
license - что внутри скачанного файла
Она вообще ничего не читает - ни диспетчера служб, ни диска, ни сети - и отвечает из реестра, скомпилированного в исполняемый файл. --components превращает уведомление в каждый компонент с его версией, лицензией и происхождением. Тот же набор, что несёт опубликованная рядом с загрузкой ведомость материалов, потому что обе строятся из одного реестра, и поэтому её стоит иметь: программа - один автономный файл, рядом с ним нет ничего, что мог бы прочитать сканер.
Примеры
Планы ниже проверены с --dry-run на программе, которую описывает эта страница. Команда, которая что-то меняет, не спрашивает заранее, поэтому --dry-run - способ посмотреть, прежде чем она выполнится. Spooler обозначает любую службу - подставьте вместо него имя своей.
Найти и прочитать
bws list каждая служба и драйвер на этой машине
bws list --query "start:auto !status:running" что должно работать и не работает
bws list --query "status:running" --memory что использует процесс каждой работающей записи
bws show Spooler всё, что известно об одной записи
bws show Spooler --full и поля, которые действительно пусты
Сначала посмотреть, потом менять
bws restart Spooler --dry-run план и ничего больше
bws restart Spooler --dependents перезапустить её вместе с тем, что от неё зависит
bws stop Spooler --dependents --timeout 120 разрешить две минуты на шаг без прогресса
bws start-type WSearch delayed --dry-run запускать чуть позже остальных автоматических записей
bws start-type Spooler disabled --stop отключить и остановить в одном плане
Служба, которая не останавливается
bws kill Spooler --dry-run процесс и каждая служба, которая в нём живёт
bws kill Spooler --restart завершить процесс, только если остановка не удалась, потом вернуть всё
bws kill Spooler --force --dry-run один шаг вместо двух: процесс завершён сразу
Снимки и дрейф
bws snapshot create before.json --note "before the patch" заморозить машину с примечанием, хранящимся внутри
bws snapshot diff before.json after.json два файла - два дня или две машины
bws snapshot diff before.json --live файл против этой машины в её текущем виде
bws snapshot diff before.json --live --exit-code то же, завершается кодом 5, если конфигурация ушла в дрейф
Кто изменил
bws history каждое изменение типа запуска и каждая установка, которые хранит журнал System
bws history Spooler изменения типа запуска одной службы
bws history --json то же в виде документа, с журналом и изменениями
Быстрые исправления
bws tool какие есть инструменты
bws tool fix быстрые исправления и служба за каждым из них
bws tool fix sound --dry-run план перезапуска двух звуковых служб
bws tool fix printer перезапустить Print Spooler вместе с тем, что от него зависит
Что внутри файла
bws license --components каждый компонент, его версия, лицензия и происхождение
bws --version версия этого исполняемого файла
В скрипте PowerShell
# записи, которые должны работать и не работают, как объекты
bws list --query "start:auto !status:running" --json | ConvertFrom-Json | Select-Object serviceName, displayName, status
# неподписанные файлы - в таблицу
bws list --query "signed:no" --json | ConvertFrom-Json | Select-Object serviceName, binaryPath | Export-Csv unsigned.csv -NoTypeInformation
# что нужно одной службе
(bws show Spooler --json | ConvertFrom-Json).dependsOn
# ночная проверка, ветвящаяся по коду завершения
bws snapshot diff C:\baselines\web01.json --live --exit-code > $null
switch ($LASTEXITCODE) {
0 { 'no configuration drift' }
5 { 'the configuration drifted' }
default { "no clean answer, exit code $LASTEXITCODE" }
}
В cmd и пакетном файле
rem вторая команда, только если первая завершилась не чисто
bws restart Spooler || echo the restart did not end cleanly
rem в пакетном файле с включённым отложенным расширением для ! нужна каретка
bws list --query "start:auto ^!status:running"
Параметры
18 штук. Третий столбец - команды, к которым относится каждый: параметр, переданный команде, которой он ни к чему, - это ошибка с этим списком внутри, а не молча игнорируемый флаг.
| Параметр | Что делает | Где работает |
|---|---|---|
--query | Сужает список с помощью языка запросов. | list |
--signatures | Читает, кто подписал каждый исполняемый файл и доверяет ли ему Windows. На всей машине занимает несколько секунд, поэтому выключено, пока не попросят, - а запрос о подписях включает это само. | list |
--memory | Читает, что использует процесс каждой работающей записи. По умолчанию выключено, потому что это измерение, а не настройка: секунду спустя оно уже другое. | list |
--required-by | Читает, какие записи сломаются, если остановить одну, спрашивая напрямую у Windows, а не выводя из того, что все объявляют. Один вызов на запись, поэтому выключено, пока не попросят. show и snapshot create читают это каждый раз. | list |
--follow-network | Позволяет инструменту вообще выходить за пределы этой машины: путь запуска, лежащий на чужом общем ресурсе, и сертификат, которого на этой машине ещё нет. По умолчанию выключено ради безопасности: один недоступный общий ресурс стоит двадцати одной секунды и аутентифицируется как тот, кто запустил, а получение сертификата - это соединение с третьей стороной посреди обычного списка. Без этого параметра подпись проверяется по тому, что есть здесь, а результат, который мог быть вызван тем, что не смотрели, сообщается как непрочитанный, а не как вердикт. | list, show, snapshot create |
--force | У kill завершает процесс сразу, не прося вежливо: предпросмотр тогда показывает один шаг вместо двух. У snapshot create заменяет уже существующий снимок: файл, не являющийся снимком, не заменяется никогда. | snapshot create, kill |
--restart | У kill возвращает запись, когда процесса уже нет, вместе со всем, что делило его. | kill |
--stop | У start-type и только вместе с disabled останавливает запись в том же плане после записи настройки. Тип запуска меняет следующую загрузку и ничего сейчас, поэтому без него работающая запись, переведённая в disabled, продолжает работать. | start-type |
--full | У show печатает и поля, которые действительно пусты. Поле, которое никто не смог прочитать, печатается в любом случае. | show |
--json | Тот же документ, машиночитаемый, в стандартном выводе. | list, show, stop, start, restart, start-type, snapshot create, snapshot diff, kill, history, tool fix NAME |
--note | Для чего был сделан снимок, хранится внутри файла. | snapshot create |
--exit-code | Завершается кодом 5, когда конфигурация отличается: запись добавлена или удалена, или одна настроена иначе. Одно состояние выполнения не считается. По умолчанию выключено, чтобы скрипт, которому нужны лишь напечатанные различия, не спотыкался о то, что он их нашёл. | snapshot diff |
--live | Сравнивает файл с этой машиной в её текущем виде, а не со вторым файлом. | snapshot diff |
--timing | Сколько занимала каждая часть чтения, в стандартном потоке ошибок. | list, show, stop, start, restart, start-type, snapshot create, snapshot diff, kill, history, tool fix NAME |
--dry-run | Печатает план и ничего не меняет. Это тот же план, который выполняет настоящий запуск: второго пути в коде для настоящего выполнения нет. | stop, start, restart, start-type, kill, tool fix NAME |
--dependents | Включает в план службы, которые сломались бы, как отдельные шаги. | stop, restart, kill |
--timeout | Сколько один шаг может идти без прогресса, прежде чем от него откажутся, отсчёт начинается заново каждый раз, когда служба сообщает о прогрессе. Шестьдесят секунд, если не скажете иначе. За службой, которая продолжает сообщать о прогрессе, наблюдают столько, сколько нужно. Истечение времени - это конец наблюдения, а не отказ, и отчёт говорит, где запись была оставлена. | stop, start, restart, kill, tool fix NAME |
--components | У license превращает уведомление в каждый компонент внутри этого исполняемого файла с его версией, лицензией и происхождением. Тот же набор, что несёт опубликованная рядом с загрузкой ведомость материалов, потому что обе строятся из одного реестра. | license |
Коды завершения
6 исходов, и каждый - это отдельное действие для скрипта. Данные идут в стандартный вывод, а всё остальное в стандартный поток ошибок, поэтому bws list --json | jq работает, а предупреждение никогда не попадёт в ваш JSON.
Каждый документ JSON - простой ASCII: буква вне него записывается как шестисимвольная escape-последовательность, которую любой читатель JSON превращает обратно в букву, поэтому bws list --json > file.json - корректный UTF-8, а | ConvertFrom-Json читает его верно при любой кодовой странице консоли. В тексте, который читает человек, символ, который сдвинул бы терминал вместо того, чтобы напечататься, - табуляция, перевод строки, escape-последовательность, переопределение направления - показывается как его кодовая точка, <U+001B>.
-- завершает параметры, поэтому службу, имя которой начинается с дефиса, всё же можно назвать: bws show -- -odd. Командные строки, которые вам выдаёт инструмент, написаны для PowerShell: имя с пробелом берётся в двойные кавычки, которые cmd читает так же, а имя, которое PowerShell раскрыл бы внутри них, например MSSQL$SQLEXPRESS, берётся в одинарные.
| Код | Значение |
|---|---|
0 | Готово, и всё дошло, куда шло. |
1 | Инструмент дал сбой: он не смог сделать то, о чём его просили, по причине, которая относится к самому инструменту, а не к плану. |
2 | Командная строка была неверной. При опечатке в команде предлагается та, которую вы, вероятно, имели в виду. |
3 | План был хорош, он выполнился, и что-то в нём не дошло, куда шло: диспетчер отказал или у сеанса не было прав на это. |
4 | Кто-то остановил выполнение вручную. Не ноль, даже если каждый шаг всё же дошёл, чтобы обёртка не считала прерванное выполнение чистым. |
5 | Сравнение выполнилось и обнаружило, что конфигурация ушла в дрейф: запись добавлена или удалена, или одна настроена иначе. Одно состояние выполнения дрейфом не является. Только с --exit-code, потому что дрейф - это то, что этот инструмент создан находить, а его нахождение не является отказом. |
У Ctrl+C три уровня, и каждый говорит, чего стоит следующий. Первый перестаёт двигаться вперёд и всё же возвращает взятое, второй оставляет всё как есть и всё же печатает отчёт, третий завершает процесс. Выполнение, остановленное вручную, завершается кодом 4, даже если каждый шаг всё же дошёл.
Закрытие окна консоли считается первым Ctrl+C. После этого Windows даёт программе пять секунд, и за них она перестаёт двигаться вперёд и возвращает то, что обрушила. Выход из системы и выключение завершают её без какого-либо предупреждения, на которое она могла бы отреагировать, и оборвавшийся удалённый сеанс - возможно, тоже.
В запланированной задаче
Форма, для которой этот инструмент построен: заморозьте машину, когда известно, что она в порядке, а потом каждую ночь спрашивайте, так ли это ещё.
# день, когда машина вводится в эксплуатацию
bws snapshot create C:\baselines\web01.json --note "after the build"
# каждую ночь, из запланированной задачи
bws snapshot diff C:\baselines\web01.json --live --exit-code --json > C:\logs\drift.json
# 0 - дрейфа конфигурации нет
# 5 - конфигурация ушла в дрейф, и drift.json говорит в чём
# 3 - выполнилось и не смогло прочитать всё, поэтому ответ частичный
Окно - вторая половина того же движка: BetterWindowsServices-win-x64.zip содержит его, а страница загрузки говорит, что такое каждый архив.
Аргумент окна
BetterWindowsServices.exe принимает один аргумент, предназначенный для человека: --catalogue открывает лист разработчика, показывающий каждый компонент окна в каждом состоянии, и ничего не читает с вашей машины. Второй, --carry, - способ, которым окно передаёт то, что показывало, своей копии, которую перезапускает от имени администратора. Его никто не набирает, и всё в нём, чего это окно не могло бы записать, отклоняется.