Справочник

Справочник командной строки

Каждая команда, каждый параметр и каждый код завершения 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, - способ, которым окно передаёт то, что показывало, своей копии, которую перезапускает от имени администратора. Его никто не набирает, и всё в нём, чего это окно не могло бы записать, отклоняется.