LVM: изменение размера, снапшоты, миграция

LVM — старая и добрая технология, представляющая дополнительный слой абстракции между физическими дисками или разделами на них, и томами, отформатированными в вашу любимую файловую систему. Так как статей на тему настройки LVM в инете валом, я ограничусь парой интересных фич, ради которых, собственно, LVM и стоит затевать.

Перво-наперво

У нас должно быть свободное место в Volume Group.  Нет смысла без особой необходимости забивать все свободное место логическими томами, когда их свободное место будет использовано не до конца. Если у нас один хард на 500 гиг, мы делаем группу на весь этот объем, а дальше, например, делаем один том в 1G под swap, другой — в 9G под /, и, например, третий — на 50G под /home. У нас остается  440G свободного места, которое мы в любой момент можем докинуть в любой раздел, а также использовать под снапшоты. Соу…

 

Как добавить места на Logical Volume

Увеличение можно проделывать на смонтированной файловой системе.

Допустим, у нас есть LVM-том с линуксовым корнем /dev/mypc/root, содержащий на себе линуксовый корень. Докинуть 100 мегабайт можно командой:

 
 
  1. lvextend -L +100m /dev/mypc/root
  2. resize2fs /dev/mypc/root

 

Первая команда увеличит том, вторая — распространит на него файловую систему.

 

 

 

Как сделать и откатить снапшот

Допустим, у нас все еще есть LVM-том /dev/mypc/root, содержащий на себе линуксовый корень. Если нам нужно, например, накатить новые дрова для видюхи и мы боимся все сломать, делаем снапшот:

 
 
  1. lvcreate -L2G -s -n rootsnapshot /dev/mypc/root

 

Эта команда сделает снапшот /dev/mypc/rootsnapshot, который будет содержать состояние на момент создания снапшота. При этом есть ограничение в 2 гига на изменения в нашем корне, если превысим — снапшот перестанет быть валидным и его можно будет только удалить:

 
 
  1. lvremove /dev/mypc/rootsnapshot

 

Так как хотелось бы снапшот уметь откатить в случае если у нас все поломается, то вариант с переполнением зарезервированного места — не вариант для нас.

 

Автоматическое увеличение размера снапшота LVM

Тут все просто, но не так просто, как часто пишут в интернетах. Нужно:

  1. Изменить файлик /etc/lvm/lvm.conf:
    snapshot_autoextend_threshold = 80
    snapshot_autoextend_percent = 20
    monitoring = 1

    Эти опции включают мониторинг, а так же увеличивают размер снапшота на 20% (от текущего размера) каждый раз, когда он оказывается занят изменениями на 80%.

  2. Установить dmeventd, который может не стоять, но который нужен чтобы все работало!

Теперь, когда наш снапшот умеет расти в размере и ему почти ничего не страшно, можно поиздеваться над корнем и откатить все изменения командой:

 
 
  1. lvconvert --merge  /dev/mypc/rootsnapshot

 

Вообще эта команда должна производиться при отмонтированном разделе, но так как в нашем случае это корень, то отмонтировать его не получится, и lvconvert скажет, что сделает все в лучшем виде при следующей активации тома — то есть при перезагрузке.

 

Как смигрировать на другой физический диск

Очень вкусная возможность лайв-миграции позволяет перетащить свои разделы с одного диска на второй, не отрываясь от работы.

Допустим у нас есть диск /dev/sda. На его разделе /dev/sda1 у нас покоится Volume Group «mypc» с нашими логическими томами:

  1. root — с корнем линукса (/),
  2. home — с домашними  каталогами (/home),
  3. swap — с разделом подкачки.

И нам нужно все это добро перенести на новый хард — /dev/sdb, который гол как сокол и ничего ж там нет.

Готовим новый диск

 
 
  1. # Создаем раздел на новом диске:
  2. parted -a opt /dev/sdb mkpart primary 0% 100%
  3. # Создаем физический том LVM:
  4. pvcreate /dev/sdb1
  5. # Расширяем Volume Group на новый физический том:
  6. vgextend mypc /dev/sdb1

 

Сдвигаем наши три логических тома со старого физического тома на новый:

 
 
  1. pvmove -n /dev/mypc/root /dev/sda1 /dev/sdb1
  2. pvmove -n /dev/mypc/home /dev/sda1 /dev/sdb1
  3. pvmove -n /dev/mypc/swap /dev/sda1 /dev/sdb1

 

Избавляемся от старого харда

 
 
  1. # Удаляем физический том LVM из группы "mypc":
  2. vgreduce mypc /dev/sda1
  3. # Удаляем физический том LVM:
  4. pvremove /dev/sda1

 

Устанавливаем загрузчик на новый диск и обновляем его конфиг:

 
 
  1. grub-install /dev/sdb
  2. update-grub

 

После перезагрузки останется вытащить старый диск и при необходимости выставить в биосе загрузку с нового.

Мой первый большой и серьезный кусок кода

Сегодня у меня появился небольшой повод для гордости. Я, конечно, не программист, но админ-  периодически небольшие скрипты писать приходится. Но сегодня я дописал (до юзабельного состояния, не идеального, не суперкрасивого, но юзабельного) свой первый большой скрипт-гуй для бэкапа LVM-разделов и, собственно, восстановления из бэкапа. Процентов на 70 это была тренировка питона, ибо написано все на нем, и процентов на 30 — решение своей хотелки управления бэкапами более-менее наглядно и без переписывания неинтерактивных скриптов по каждому чиху.

Итак, что и как оно выглядит (май ингриш из вери перфект, так что возможны смешные косяки).
Скрипт запускается под обычным юзером и в этом случае умеет вызывать судо:

Стартовый экран выглядит вот так:

При первом запуске он запоминает текущую директорию, в которой был запущен, и делает ее рабочей при последующих запусках. Если потом его запустить в другой дире (как на текущем скрине) — будет предлагать сохранить ее как рабочую.
Тут же, не отходя от кассы можно набить список исключений.

Допустим мы хотим забэкапиться, выбираем бэкап!

Скрипт сам находит все смонтированные LVM-разделы и позволяет пометить те, которые хочется забэкапить. В результате бэкапа образуются файлы — первый всегда полный бэкап, последующие автоматом инкрементируются.

Если инкрементов накопилось дофига и больше, и какие-то промежуточные хочется убить — это можно сделать опцией мерджинга. Выделенный файл бэкапа поглотит тот, что перед ним (таким образом можно слить два файла разных разделов — я пока не понял это скорее баг или фича ))).

Ну и наконец — восстановление.
Выбираем файл, который хотим восстановить:

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

В общем вышла такая себе управлялка бэкапами, для наглядного процесса копирования и восстановления.

Код на гитхабе: https://github.com/qiwichupa/lvmdarbackuper/blob/master/lvmdarbackuper.py

Папка windows\temp забивается файлами cab_xxxx

Данная проблема вызвана сбоем службы автоматического обновления Windows, в частности при работе с серверами обновлений WSUS.

Пошаговое решение проблемы выглядит так:

  1. Остановка службы обновлений (wuauserv)
  2. Остановка службы trustedinstaller
  3. Удаление содержимого папки c:\windows\temp
  4. Удаление cab-файлов из папки c:\windows\logs\CBS
  5. Удаление папки  C:\windows\softwaredistribution
  6. Запуск сервиса trustedinstaller
  7. Запуск службы обновления

Для удаленного автоматического решения проблемы можно воспользоваться скриптом:

fix_winupdate_tmp_cab.ps1
 
  1. $Machine = read-host "Type in the Computer Name"
  2. $windowsUpdateService = 'wuauserv'
  3. $trustedInstallerService = 'trustedinstaller'
  4. function Set-ServiceState
  5. {
  6.     [CmdletBinding()]
  7.     param(
  8.         [string]$ComputerName,
  9.         [string]$ServiceName
  10.     )
  11.     Write-Verbose "Evaluating $ServiceName on $ComputerName."
  12.     [string]$WaitForIt = ""
  13.     [string]$Verb = ""
  14.     [string]$Result = "FAILED"
  15.     $svc = Get-Service -computername $ComputerName -name $ServiceName
  16.     Switch ($svc.status) {
  17.         'Stopped' {
  18.             Write-Verbose "[$ServiceName] is currently Stopped. Starting."
  19.             $Verb = "start"
  20.             $WaitForIt = 'Running'
  21.             $svc.Start()
  22.         }
  23.         'Running' {
  24.             Write-Verbose "[$ServiceName] is Running. Stopping."
  25.             $Verb = "stop"
  26.             $WaitForIt = 'Stopped'
  27.             $svc.Stop()
  28.         }
  29.         default {
  30.             Write-Verbose "$ServiceName is $($svc.status). Taking no action."
  31.         }
  32.     }
  33.     if ($WaitForIt -ne "") {
  34.         Try { # For some reason, we cannot use -ErrorAction after the next statement:
  35.             $svc.WaitForStatus($WaitForIt,'00:02:00')
  36.         } Catch {
  37.             Write-Warning "After waiting for 2 minutes, $ServiceName failed to $Verb."
  38.         }
  39.         $svc = (get-service -computername $ComputerName -name $ServiceName)
  40.         if ($svc.status -eq $WaitForIt) {
  41.             $Result = 'SUCCESS'
  42.         }
  43.         Write-Verbose "$Result - $ServiceName on $ComputerName is $($svc.status)"
  44.         Write-Verbose ("{0} - {1} on {2} is {4}" -f $Result, $ServiceName, $ComputerName, $svc.status)
  45.     }
  46. }
  47. # stop update service
  48. Write-Host "stop update service"
  49. Set-ServiceState -ComputerName $Machine -ServiceName $windowsUpdateService -Verbose
  50. #removes temp files and renames software distribution folder
  51. Write-Host "removes temp files and renames software distribution folder"
  52. Remove-Item \\$Machine\c$\windows\temp\* -recurse
  53. Rename-Item \\$Machine\c$\windows\SoftwareDistribution SoftwareDistribution.old
  54. #restarts update service
  55. Write-Host "restarts update service"
  56. Set-ServiceState -ComputerName $Machine -ServiceName $windowsUpdateService
  57. #removes software distribution.old
  58. Write-Host "removes software distribution.old"
  59. Remove-Item \\$Machine\c$\windows\SoftwareDistribution.old -recurse
  60. #stops trustedinstaller service
  61. Write-Host "stops trustedinstaller service"
  62. Set-ServiceState -ComputerName $Machine -ServiceName $trustedInstallerService
  63. #removes cab files from trustedinstaller
  64. Write-Host "removes cab files from trustedinstaller"
  65. remove-item \\$Machine\c$\windows\Logs\CBS\* -recurse
  66. #restarts trustedinstaller service
  67. Write-Host "restarts trustedinstaller service"
  68. Set-ServiceState -ComputerName $Machine -ServiceName $trustedInstallerService
  69. #rebuilds cab files from WSUS
  70. Write-Host "rebuilds cab files from WSUS"
  71. invoke-command -ComputerName $Machine -ScriptBlock { & cmd.exe "c:\windows\system32\wuauclt.exe /detectnow" }

Источник: https://community.spiceworks.com/topic/495234-windows-temp-file-is-full-of-cab_xxxx-files-on-windows-server-2008-r2

В chrome под linux не работает встроенный чат twitch

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

Или показывая чат, иногда с его содержимым, но с «колесиком» загрузки поверх и без возможности что-либо писать:Такая проблема проявлялась только в хроме (вернее в хромиуме, но не суть) и только на одном из двух аналогичных в плане софта компов. Также проблема возникала только если чат был встроен по ссылке вида «http://www.twitch.tv/channelname/chat» и не проявлялась при встраивании по ссылке вида «https://www.twitch.tv/embed/channelname/chat».

Так как на втором компе с той же версией линукса (Linux Mint 17.3) и Chromium ( 64.0.3282.140) проблемы не наблюдалось, я заглянул в консоль (CTRL   Shift I) и сравнил ошибки. И действительно, на «нерабочем» компе наблюдалась ошибка «Uncaught RangeError: Unsupported time zone specified undefined» Оказалось, что на этом компе у меня выставлена таймзона «-3», соответствующая Москве, а не зона с названием «Москва». Не знаю какого рожна хром решил к этому придраться, но выставление зоны на «именную» решило данную дикую проблему.

Напомню, что в этих наших debian-like дистрах зона меняется командой:

 
 
  1. dpkg-reconfigure tzdata

 

Второй вариант где может не работать

Идем в настройки хрома:
«Настройки контента» -> «Файлы Cookie», убеждаемся что снят флаг «Блокировать сторонние файлы cookie»

Как давно выключена эта виртуалка?

Набросал небольшой скриптец для VMware ESXi, чтобы проверять как давно менялось состояние виртуальных машин. При запуске он заполняет кастомное поле «Power» состоянием и датой, когда это состояние было обнаружено. Кинув в шедулер можно с некоторой точностью понимать, что вот эту виртуалку выключили только вчера, а вот та — выключена уже пару лет (конечно после того как этот скрипт пару лет проверял ее состояние =). Скрипт использует VMware PowerCLI

check-vm-powerstate.ps1
 
  1. Add-PSSnapin VMware.VimAutomation.Core
  2. Connect-VIServer -Server localhost
  3. Get-VM  | ForEach-Object {
  4.                         $vm = $_
  5.                         $date = (Get-Date -UFormat "%Y-%m-%d  %R").ToString()
  6.                         $AnnotationStatus =  (Get-Annotation $_ | Where-Object { $_.Name -eq "Power"}).Value
  7.                        
  8.                         if ( ($_.PowerState -eq 'PoweredOn') -and ($AnnotationStatus -like 'Down*') ) {
  9.                             $vm | Set-Annotation -CustomAttribute "Power" -Value "Up since $date"
  10.                         }
  11.                         if ( ($_.PowerState -eq 'PoweredOn') -and ($AnnotationStatus -eq '') ) {
  12.                             $vm | Set-Annotation -CustomAttribute "Power" -Value "Up since  < $date"
  13.                         }
  14.                         if ( ($_.PowerState -eq 'PoweredOff') -and ($AnnotationStatus -like 'Up*') ) {
  15.                             $vm | Set-Annotation -CustomAttribute "Power" -Value "Down since $date"
  16.                         }
  17.                         if ( ($_.PowerState -eq 'PoweredOff') -and ($AnnotationStatus -eq '') ) {
  18.                             $vm | Set-Annotation -CustomAttribute "Power" -Value "Down since < $date"
  19.                         }
  20.                     }

Поправить пакет *.deb на скорую руку

Столкнулся с банальной задачей — после быстрого формирования пакета (агента системы мониторинга) при помощи checkinstall, захотелось дополнить его правильным конфигом и стартовыми скриптами. На скорую руку это делается примерно так:

  1. Распаковываем пакет:
    dpkg-deb -R zabbix-agent.deb extracted/
  2. Внутри каталога extracted/DEBIAN создаем исполняемый файл postinst с требуемым скриптом:
     
     
    1. #!/bin/bash
    2. #
    3. #тело скрипта
    4. #
    5. exit 0
  3. Докладываем в extracted/ все необходимые файлы, размещая по нужным путям. Не забываем о правах доступа при создании каталогов, если софт будет работать не от рута.
  4. Собираем пакет обратно:
    dpkg-deb -b extracted
    mv extracted.deb  zabbix-agent-new.deb

Источники гуглинга:
https://askubuntu.com/questions/825321/
https://askubuntu.com/questions/62534/

Конвертация powershell в cmd (на самом деле нет)

Встала задача — запустить скрипт powershell из обычного *.cmd. Задача традиционно возникает вследствие отсутствия ассоциаций для файлов *.ps1, и не менее традиционно решается путем создания двух файлов — скрипта на повершелле, который делает то что нужно, и обычной цмдэшки, которая его стартует. Это жесть как неудобно. Однако нагуглилось еще одно решение — повершелльный скрипт можно закодировать в одну строку и подсунуть интерпретатору, что избавляет от необходимости создавать дополнительный файл. В результате со своей несложной по сути задачей я справился, и решил привести пример скрипта, который берет тело скрипта нужной нам функциональности и генерит cmd-файл готовый к запуску.

Внутри переменной $script — тело нужного скрипта,
переменная $out задает вид генерируемого cmd-файла,
в последней строке указываем путь и имя cmd-файла (да я ленивый быдлокодер, не вынес в переменную ))

powershell to cmd generator.ps1
 
  1. $script = {
  2. import-module activedirectory
  3. $domain = Get-ADDomain
  4. Write-Host "Последнее появление компьютера в домене"
  5. Write-Host "======================================="
  6. Write-Host "Поиск в домене: $($domain.Name).$($domain.ParentDomain)"
  7. while($true)
  8.       {
  9.       $CompName = Read-Host -Prompt \'Введите короткое имя компьютера\'
  10.       $CompName = $CompName -replace \'(^\s |\s $)\',\'\' -replace \'\s \',\' \'
  11.       Get-ADComputer -Identity $CompName -Properties * | ft Name,LastLogonDate
  12.       }
  13. }
  14. $command = $script.ToString()
  15. $bytes = [System.Text.Encoding]::Unicode.GetBytes( $command )
  16. $encodedCommand = [Convert]::ToBase64String( $bytes )
  17. $out ="@echo off
  18. powershell.exe -EncodedCommand $encodedCommand"
  19. $out | Out-File -Encoding ASCII -filepath c:\111.cmd

На выходе получаем:

111.cmd
 
  1. @echo off
  2. powershell.exe -EncodedCommand DQAKAA0ACgBpAG0AcABvAHIAdAAtAG0AbwBkAHUAbABlACAAYQBjAHQAaQB2AGUAZABpAHIAZQBjAHQAbwByAHkADQAKACQAZABvAG0AYQBpAG4AIAA9ACAARwBlAHQALQBBAEQARABvAG0AYQBpAG4ADQAKAFcAcgBpAHQAZQAtAEgAbwBzAHQAIAAiAB8EPgRBBDsENQQ0BD0ENQQ1BCAAPwQ BE8EMgQ7BDUEPQQ4BDUEIAA6BD4EPAQ/BEwETgRCBDUEQAQwBCAAMgQgADQEPgQ8BDUEPQQ1BCIADQAKAFcAcgBpAHQAZQAtAEgAbwBzAHQAIAAiAD0APQA9AD0APQA9AD0APQA9AD0APQA9AD0APQA9AD0APQA9AD0APQA9AD0APQA9AD0APQA9AD0APQA9AD0APQA9AD0APQA9AD0APQA9ACIADQAKAFcAcgBpAHQAZQAtAEgAbwBzAHQAIAAiAB8EPgQ4BEEEOgQgADIEIAA0BD4EPAQ1BD0ENQQ6ACAAJAAoACQAZABvAG0AYQBpAG4ALgBOAGEAbQBlACkALgAkACgAJABkAG8AbQBhAGkAbgAuAFAAYQByAGUAbgB0AEQAbwBtAGEAaQBuACkAIgANAAoADQAKAA0ACgB3AGgAaQBsAGUAKAAkAHQAcgB1AGUAKQANAAoACQB7AA0ACgAJACQAQwBvAG0AcABOAGEAbQBlACAAPQAgAFIAZQBhAGQALQBIAG8AcwB0ACAALQBQAHIAbwBtAHAAdAAgACcAEgQyBDUENAQ4BEIENQQgADoEPgRABD4EQgQ6BD4ENQQgADgEPARPBCAAOgQ BDwEPwRMBE4EQgQ1BEAEMAQnAA0ACgAJACQAQwBvAG0AcABOAGEAbQBlACAAPQAgACQAQwBvAG0AcABOAGEAbQBlACAALQByAGUAcABsAGEAYwBlACAAJwAoAF4AXABzACsAfABcAHMAKwAkACkAJwAsACcAJwAgAC0AcgBlAHAAbABhAGMAZQAgACcAXABzACsAJwAsACcAIAAnAA0ACgAJAEcAZQB0AC0AQQBEAEMAbwBtAHAAdQB0AGUAcgAgAC0ASQBkAGUAbgB0AGkAdAB5ACAAJABDAG8AbQBwAE4AYQBtAGUAIAAtAFAAcgBvAHAAZQByAHQAaQBlAHMAIAAqACAAfAAgAGYAdAAgAE4AYQBtAGUALABMAGEAcwB0AEwAbwBnAG8AbgBEAGEAdABlAA0ACgAJAH0ADQAKAA0ACgA=

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

Как очистить стену во вконтакте (версия 2017-го года)

Чтобы удалить со стены все записи, можно воспользоваться нижеприведенным джава-скриптом. Для этого нужно:

  1. открыть свою стену,
  2. пролистать ее до самого конца,
  3. открыть консоль (в хроме: CTRL+SHIFT+I),
  4. вставить код в поле ввода и нажать Enter

 
 
  1. (function () {
  2.   'use strict';
  3.   if (!confirm('Удалить все записи со стены?')) return;
  4.   var deletePostLink = document.body.querySelectorAll('a.ui_actions_menu_item[onclick^="wall.deletePost"]');
  5.   for (var i = 0; i < deletePostLink.length; i++) {
  6.     deletePostLink[i].click();
  7.     }
  8.   alert(deletePostLink.length + ' posts deleted');
  9. }());

[из техноблога] Тормозит Lightroom 5, неожиданное решение

Долгое время страдал от диких тормозов в лайтруме. Тормоза были при скроллинге фоток во вьювере, при их обработке — решительно во всех местах лайтрума, причем независимо от размера каталога

Читать далее

[из техноблога] Как избавиться от вируса EIMG001.exe и NsCpuCNMiner32.exe в большой сети

Если в вашей большой корпоративной сети обнаружилась движуха с сабжевым вирусом, который расползся по компам, проще всего заблокировать его запуск через GPO — это позволит прекратить или как минимум ограничить его распространение.

Читать далее