Системная служба заняла всю свободную оперативную память

Возникла проблема: на двух серверах Windows Server 2008R2 SP1, на которых давно не ставили обновления и которые не перезагружались больше года, кончилась свободная оперативная память на сервере. При беглом взгляде было обнаружено, что проблема вроде бы как в системных службах, в частности в службе «Установщик модулей Windows» (aka TrustedInstaller). После ее перезапуска проблема не устранилась, тут же другая системная служба заняла всю доступную оперативную память. И тут пришла идея проверить количество дескрипторов, занятых процессами..

Сразу стало понятно в чем источник проблемы. Перезапуск службы «Digi Anywhere» инициировал активную работу служб, которые заняли оперативную память и через 20-30 секунд вместо 4 ГБ занятой памяти осталось только 1 ГБ. Проблема бесследно исчезла. Так что почаще проверяйте количество дескрипторов, использующимися вашими процессами, возможно проблема в них.

Ошибка «SCP Wrong response: 1scp: ambiguous target » в Veeam BR

Привет! Столкнулся сегодня с такой ошибкой в отчете резервного копирования, который Veeam присылает на почту:
Error: SCP Wrong response: 1scp: ambiguous target
В логе с именем файла task.<имя сервера>.log, который находится в директории C:\ProgramData\Veeam\Backup\<имя задачи>\ на сервере Veeam BR я нашел следующую строчку:
Info [LinuxEpBackupManagementService] Uploading local file C:\Scripts\rhel-share_do-backup-catalog — Job ABS_FIO.sh to /var/lib/veeam/scripts/rhel-share_do-backup-catalog — Job ABS_FIO.sh on target machine.
Как видно в строчку в строке с директорией содержатся пробелы. Если посмотреть настройки этой задачи, то в настройках «Application-aware processing» можно обнаружить подключенный скрипт, который в своем имени содержит пробелы.
Чтобы ошибка пропала достаточно в имени скрипта убрать пробелы или заменить их на знак «подчеркивания». Ошибка после этого пропала.

Powershell cкрипт для массового отображения/изменения ACL на файловом сервере

Привет! Понадобилось мне недавно провести вручную операцию по удалению из ACL лишней записи. Проблема была в том, что таких папок было около 50 штук. Спасало только то, что это нужно было сделать в папке с одним и тем же именем в разных директориях с одним общим корнем. Я это сделал вручную, так как задачу надо было выполнить быстро, но решил для себя написать скрипт, чтобы можно было быстро править ACL-листы папок в Windows. Необходимо только, чтобы на сервере был Powershell и немного его знания, так как скрипт практически не оттестирован и не проверен в реальной работе на большом количестве данных.
Вот он сам, по комментариям внутри него думаю будет понятно, что надо делать.

function Print_Dir($list_catalogs)
    {
         $Table = New-Object system.Data.DataTable “$Table_Security”  <#Создание таблицы для отображения ACL#>
         $column1 = New-Object system.Data.DataColumn Директория,([string])
         $column2 = New-Object system.Data.DataColumn ACL,([string])
         $column3 = New-Object system.Data.DataColumn Владелец,([string])
         $table.columns.add($column1)
         $table.columns.add($column2)
         $table.columns.add($column3)
         foreach ($Foundfolder in $list_catalogs) 
            {
                $Access = (Get-Acl $Foundfolder.FullName).AccessToString  
                $row = $table.NewRow()
                $row.Директория = $Foundfolder.FullName
                $row.ACL = “$Access”
                $row.Владелец = $AccessACL.Owner
                $table.Rows.Add($row)
            } 
         $table | format-table -Wrap
        
    }

function Found_Folder()
    {
                $Root_Path = Read-Host 'Введите корневую директорию'   <#Директория в которой производится поиск по-умолчанию#>
                $Target_Folder = Read-Host 'Введите название папки'    <#папка для поиска по-умолчанию #>
                $FFolder = Get-ChildItem $Root_Path -Recurse -Directory -Force -ErrorAction SilentlyContinue -Filter "$Target_Folder" <#Найденные папки#>
                return $FFolder
    }

While ($KEY='1')
{
$ACL_Key = Read-Host 'Что необходимо сделать? (1 - Вывести текущие значения ACL; 2 - Добавление; 3 - Удаление; 4 - Выход из программы)'
switch ($ACL_Key)
{
    1 
        {
                $Found_Folder = Found_Folder
                Print_Dir($Found_Folder)
        }
    2
        {
                $Found_Folder = Found_Folder
                $AccessRuleAdd = New-Object System.Security.AccessControl.FileSystemAccessRule "ONIX\TestAV", "Modify","ContainerInherit,ObjectInherit", "None","Allow" <#ACL, которую требуется добавить в папки#>
                foreach ($Foundfolder in $Found_Folder)
                    {
                        $ACL = $Foundfolder.GetAccessControl("Access")  
                        $ACL.AddAccessRule($AccessRuleAdd)
                        $Foundfolder.SetAccessControl($ACL)
                    } 
                Print_Dir($Found_Folder)
        }
    3
        {
                $Found_Folder = Found_Folder
                $AccessRuleDel = New-Object System.Security.AccessControl.FileSystemAccessRule "ONIX\TestAV", "Modify","ContainerInherit,ObjectInherit", "None","Allow" <#ACL, которую требуется добавить в папки#>
                foreach ($Foundfolder in $Found_Folder)
                    {
                        $ACL = $Foundfolder.GetAccessControl("Access")  
                        $ACL.RemoveAccessRule($AccessRuleDel)
                        $Foundfolder.SetAccessControl($ACL)
                    } 
                Print_Dir($Found_Folder)
        }
    4   
        {
            exit
        }
} 
}

Автоматическое восстановление базы данных SQL из Veeam Backup

Понадобилось автоматически восстанавливать MS SQL базу данных из Veeam Backup & Replication 9.5. Задание должно было запускаться сразу после того, как заканчивалось резервное копирование и восстановление должно было происходить на другой сервер. Вот какой скрипт у меня получился:

Add-PSSnapin VeeamPSSnapIn

$source_host        = "SQL_Original"
$source_db1         = "DB1"
$source_db2         = "DB2"
$source_db3         = "DB3"
$source_db4         = "DB4"
$target_host        = "SQL_Target"
$target_cred        = Get-VBRCredentials -Name "onix\onix_backup"
$target_instance    = "test"

$target_db1    = $source_db1
$target_db2    = $source_db2
$target_db3    = $source_db3
$target_db4    = $source_db4

$(
$restorepoint = Get-VBRApplicationRestorePoint -SQL -Name $source_host| Sort-Object creationtime -Descending | Select-Object -First 1
$database1 = Get-VBRSQLDatabase -ApplicationRestorePoint $restorepoint -Name $source_db1
$database2 = Get-VBRSQLDatabase -ApplicationRestorePoint $restorepoint -Name $source_db2
$database3 = Get-VBRSQLDatabase -ApplicationRestorePoint $restorepoint -Name $source_db3
$database4 = Get-VBRSQLDatabase -ApplicationRestorePoint $restorepoint -Name $source_db4
$restore_session = Start-VBRSQLDatabaseRestore -Database $database1 -ServerName $target_host -InstanceName $target_instance -DatabaseName $target_db1 -GuestCredentials $target_cred -SqlCredentials $target_cred -Force -Wait
$restore_session = Start-VBRSQLDatabaseRestore -Database $database2 -ServerName $target_host -InstanceName $target_instance -DatabaseName $target_db2 -GuestCredentials $target_cred -SqlCredentials $target_cred -Force -Wait
$restore_session = Start-VBRSQLDatabaseRestore -Database $database3 -ServerName $target_host -InstanceName $target_instance -DatabaseName $target_db3 -GuestCredentials $target_cred -SqlCredentials $target_cred -Force -Wait
$restore_session = Start-VBRSQLDatabaseRestore -Database $database4 -ServerName $target_host -InstanceName $target_instance -DatabaseName $target_db4 -GuestCredentials $target_cred -SqlCredentials $target_cred -Force -Wait
) *>&1 >> "C:\SQLRestore_errors.log"

Все достаточно просто: берется оригинальный хост с базами данных, список баз для восстановления, хост на который надо восстановить, учетная запись от имени которой будет восстановление (должна быть сохранена в «Manage Credentials» и целевой инстанс SQL если требуется). Находится последняя точка резервного копирования базы (на точку восстановления с проигрыванием логов восстановиться можно, но не получится это сделать автоматически) и восстанавливается. Если происходят ошибки, то они выводятся в текстовый файл (в консоли Veeam ошибки работы скрипта показаны не будут).

Остается в задаче, которая бекапит SQL-сервер, настроить запуск скрипта, делаем это в «Advanced Settings». Задаем так строку C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noninteractive -file «C:\Scripts\SQLRestore.ps1»

Сброс пароля в Kaspersky Endpoint Security 10

Понадобилось вчера переустановить антивирус Касперского в доменной среде, при незнании пароля, установленного в KSC для блокирования изменения настроек. К сожалению bat -файл с раздела технической поддержки Касперского, который сбрасывает пароль, не работает на серверных операционных системах, поэтому пришлось искать другой способ. Оказывается он совсем простой, достаточно только также загрузиться в безопасный режим и в реестре найти ветку HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\KasperskyLab\protected\KES10\settings (для Win x64) или HKEY_LOCAL_MACHINE\SOFTWARE\KasperskyLab\protected\KES10\settings (для Win x32) и изменить ключ на следующее значение:

"EnablePswrdProtect"=dword:00000000

После этого перезагружаемся опять в безопасный режим и можно смело удалять антивирус, пароль уже не потребуется. Для удаления я воспользовался утилитой kavremvr.exe. от того же Касперского. Делал я по той причине, что Касперский никак не хотел ставиться после обновления системы на новую версию, ошибка в логах была «Failed to extract stream: mklifx64nt602.cab Error 0x80070006»

Перенос WordPress на Debian с NGINX.

Привет! На днях решил заняться этим блогом. Решил немного попрактиковаться с web-сервером на linux-машине. Был выбран Debian 9 и nginx. Пришлось немного повозиться, наступить на различные грабли, но самое главное я добился своей цели. Не буду здесь писать инструкции как я это осуществил, так как в интернете полно материалов на данную тему. Могу лишь только сказать, что для начинающего администратора это может оказаться сложным. Если у кого-то будут вопросы по мигрированию или созданию новых блогов на данной платформе, то прошу вас, обращайтесь ко мне через комментарии к этой заметке или через обратную форму на главной странице.

P.S. Среднее время загрузки главной страницы сайта у меня теперь составляет менее 500 мс, хотя ранее на Windows с IIS web-сервером эта цифра составляла 3-4 секунды.

Ошибка «We couldn’t create a new partition or locate an existing one» при установке Windows Server 2012R2 на ProLiant BL460c G7

Привет! Первый раз столкнулся с проблемой установки серверной системы Microsoft на сервер HP. Вот возможные варианты решения данной проблемы:

  1. внедрить драйвера дискового контроллера в образ Windows
  2. драйвера дискового контроллера подсунуть на флешке, подключив ее  перед запуском установки системы
  3. самый оптимальный для ленивых админов:
    • нажать Shift+F10 в момент, когда появилось сообщение об ошибке.
    • В cmd набрать команды:
      diskpart
      list disk
      select disk 0 (номер диска куда устанавливается система)
      clean
      create partition primary
      format fs=ntfs quick
      assign
      active
      list volume (смотрим какая буква назначилась разделу и какая буква принадлежит iso с дистрибутивом)
      exit
      cd D: (переходим в каталог, где лежит дистрибутив системы)
      xcopy d: c:/e/h/k (копируем дистрибутив на раздел куда будем устанавливать систему)
  • после завершения копирования отключаем ISO-образ от сервера и перезагружаемся
  • запустится инсталлятор системы непосредственно с дисковой подсистемы сервера. В процессе установки указываем тот же раздел, в который копировали установщик
  • После завершения установки и входа в систему надо очистить корень системного диска С: от файлов и папок установщика.
  • правим загрузчик системы., иначе по-умолчанию в его настройках будет 2 записи, одна из которых будет ссылаться на установочные файлы. Для этого в загруженной системе открываем cmd и пишем:
    bcdedit 
    Находим запись об установщике Windows Setup и копируем его идентификатор
    bcdedit /delete <ID> 
    Удаляем запись с нужным идентификатором
    После этого установленная система не будет отличаться от той, что была бы установлена по 1 или 2 способу.

Перенос физического сервера FreeBSD в виртуальную машину

В моем случае сервер FreeBSD 9.1, виртуальная машина будет находится на хосте ESXi 6.5, впрочем это совсем не важно. Выполняем следующие шаги:

1) Подготавливаем новый сервер (виртуальную машину).
2) Запускаем установщик сервера (достаточен bootonly ISO-образ FreeBSD).
3) Установщик спрашивает в начале что будем делать: устанавливать, запустить Shell или запустить Live CD. Выбираем «запуск Shell»
4) Настраиваем сеть: ifconfig em0 10.9.96.5/24
Добавляем маршрут по-умолчанию: route add default 10.9.96.1
Проверяем, что сервер, который требуется перенести может пинговать наш новый сервер.
5) Запускаем SSH. Для этого нужны следующие шаги:
mkdir /tmp/etc
mount_unionfs /tmp/etc /etc

Правим файл настроек SSH для возможности подключения root к серверу:
ee /etc/ssh/sshd_config
Правим строку. Должно быть:
PermitRootLogin yes
SSH-готов для запуска:
/etc/rc.d/sshd onestart
6) Меняем пароль у root-пользователя во времено загруженной системы: passwd
7) Командой sysctl kern.disks проверяем наличие дисков в системе. Находим тот, который будет выделен под систему.
Командой gpart show <имя диска> смотрим, что на этом диске есть. Если разделов нет или они отличаются от разделов на исходном сервере, то командой gpart destroy -F <имя диска> уничтожаем всё на диске.
8) Командой geom disk list на целевом сервере проверяем размер сектора диска. Если установка производится на современные жесткие диски, у которых размер сектора = 4 кб, то при создании разделов необходимо использовать выравнивание.
9) Командами gpart create -s <BSD|GPT|MBR> <имя диска> создадим одну из схем (геометрию) на диске.
10) Командой gpart add -t <freebsd-ufs|freebsd-boot|freebsd-swap> <имя диска> создаем раздел на диске (если нужно выравнивание, то используем дополнительные ключи)
11) Форматируем корневой раздел командой newfs -U <имя раздела>. Ключ -U включает Soft Updates
12) Делаем диск загрузочным: для этого выполняем команду gpart bootcode -b /boot/boot <имя диска> (для схемы BSD). Для других схем команды будут: gpart bootcode -b /boot/mbr <имя диска> и
gpart bootcode -b /boot/pmbr <имя диска>
gpart bootcode -p /boot/gptboot -i 1 <имя диска>

13) Монтируем раздел mount <имя раздела> /mnt
14) На исходной машине выполняем команду: dump -0Lf - / | ssh root@10.9.96.5 "cd /mnt ;restore -rf -". Если сервер пишет «Cannot create snapshot. Snapshots are not yet supported when running with journaled soft updates.», то тогда нужно загрузиться в Single Mode и выполнить команды:
tunefs -J disable /dev/ada0
tunefs -n disable /dev/ada0
tunefs -j disable /dev/ada0

После этого перезагружаемся и снова выполняем команду dump. Дожидаемся надписи «DUMP IS DONE»
Если сервер нет возможности перезагрузить в безопасный режим, то тогда из команды dump убираем ключ -L. Чтобы данные были как можно более консистенты на новом сервере, на исходном сервере перед дампом выключаем все сервисы. В моем случае это:
service apache22 stop; service nginx stop; service sendmail stop; service mysql-server stop
15) Перезагружаем конечный сервер. Если он не может подмонтировать корневую файловую систему, но еще раз загружаемся с ISO-образа, монтируем том, куда мы скопировали сервер и в нем открываем файл ee /etc/fstab. Там меняем название раздела для корневой системы на правильное.

Удаление ярлыка с рабочего стола через GPO средствами Powershell

Привет! Возникла задача удалить ярлык программы с рабочего стола всех пользователей домена. Проблема была в том, что ярлык этот изначально не создавался групповыми политиками, соответственно и удалить его нельзя было отключив соответствующую политику. В таком случае нужно писать скрипт.

Перед тем, как настраивать GPO для запуска powershell-скрипта на компьютерах необходимо средствами групповых политик разрешить запуск PS-скриптов. По-умолчанию, на компьютере запрещен их запуск. Поэтому заходим в дефолтную GPO для домена в User Configuration — Policies — Administrative Templates — Windows Components — Windows PowerShell. Находим там политику «Turn on Script Execution«, включаем её и переводим в режим работы «Allow local scripts and remote signed scripts«.

Теперь можно настраивать политику, которая будет запускать PS-скрипт при входе пользователя в систему. Для этого заходим в созданную для этого политику в раздел User Configuration — Policies  — Windows Settings — Scripts — Logon. Выбираем вкладку «PowerShell Scripts» и нажимаем кнопку «Add». Далее нажимаем кнопку «Browse» и в открывшееся окно проводника копируем файл с powershell-скриптом. После этого выбираем этот файл и нажимаем «Open» в этом же окне и «OK» в предыдущем. Таким образом политика настроена.

А вот текст самого скрипта. Сохраняем его под расширением PS1 у себя на компе.

$DeleteItem = "Кодекс-клиент.lnk"
$Date = Get-Date
$ComputerName = $Env:Computername
$UserName = $Env:UserName
$DesktopPath = [Environment]::GetFolderPath("Desktop")
$ShortcutFiles = Get-ChildItem -Path $DesktopPath -Recurse -Include *.lnk
Write-Host "Всего найдено ярлыков:" $ShortcutFiles.Count -ForegroundColor Green
$Changed = 0
ForEach ($Shortcut in $ShortcutFiles) {
IF ($Shortcut -match $DeleteItem ) {
Remove-Item $Shortcut
$Changed ++
}
}
Write-Host "Удалено ярлыков:" $Changed -ForegroundColor Green
echo $Date $UserName "Всего найдено ярлыков:" $ShortcutFiles.Count "Удалено ярлыков:" $Changed >> \\DC-01\C$\Logs_remove_shortcut\$ComputerName.log

В последней строке скрипта я сохраняю логи исполнения данного скрипта на компьютерах пользователя. У меня они сохраняются в скрытую папку на контроллере домена, у вас она будет другой, поэтому поменяйте путь до вашей папки.

Этот же скрипт может быть взят за основу для удаления любого файла из любой директории.