<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Rollback &#187; PowerShell</title>
	<atom:link href="http://blog.rollback.hu/tag/powershell/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.rollback.hu</link>
	<description>SQL, üzemeltetés kicsiknek és nagyoknak.</description>
	<lastBuildDate>Thu, 17 Nov 2011 16:38:59 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>SQL objektumok scriptelése Powershellben</title>
		<link>http://blog.rollback.hu/2010/12/sql-objektumok-scriptelese-powershellben/</link>
		<comments>http://blog.rollback.hu/2010/12/sql-objektumok-scriptelese-powershellben/#comments</comments>
		<pubDate>Fri, 10 Dec 2010 01:08:58 +0000</pubDate>
		<dc:creator>Erik</dc:creator>
				<category><![CDATA[Magyar]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false">http://blog.rollback.hu/?p=315</guid>
		<description><![CDATA[Azt már mindenki tudja, h PS-ben lehet kiválóan scriptet generálni a SQL entitásokról a Script() metódus segítségével. Felvetődött egy kérdés vkiben, hogy hogyan lehet csak DB sémát backupolni, és felvetődött erre a Powershell, meg a get-contentitem&#124;%{$_.Script()}, mint alapgondolat. Ja, ez ezt adja vissza egy új táblámra:

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
CREATE TABLE [dbo].[KeynoteDaily](
    [...]]]></description>
			<content:encoded><![CDATA[<p>Azt már mindenki tudja, h PS-ben lehet kiválóan scriptet generálni a SQL entitásokról a Script() metódus segítségével. Felvetődött egy kérdés vkiben, hogy hogyan lehet csak DB sémát backupolni, és felvetődött erre a Powershell, meg a get-contentitem|%{$_.Script()}, mint alapgondolat. Ja, ez ezt adja vissza egy új táblámra:</p>
<pre class="brush: sql;">
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
CREATE TABLE [dbo].[KeynoteDaily](
        [day] [date] NOT NULL,
        [site] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
        [measurements] [smallint] NULL,
        [failures] [smallint] NULL,
        [contenterrors] [smallint] NULL,
        [availability_wc] [real] NULL,
        [availability_woc] [real] NULL,
        [errors] [varchar](1000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
        [loadtime] [smalldatetime] NULL,
        [comment] [varchar](2000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]
</pre>
<p>Szóval jól néz ki, nem? Nem. addig néz ki jól, amíg nem jut eszembe, hogy van primary key is a táblán. Meg még további indexek. Amiket persze megint ki lehet scriptelni: ˘</p>
<pre class="brush: powershell;">
%{$_.Indexes}|%{$_.script()}
</pre>
<p>Meg még ki tudja, mi marad ki. Na mindegy, tuti megoldást nem tudok, de ez olyan lámának tűnt, hogy elkezdtem nézegetni a metódusokat, és találtam egy olyat, hogy EnumScript():</p>
<pre class="brush: powershell;">
PS &gt; gci |%{$_.EnumScript()}
</pre>
<pre class="brush: sql;">
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
CREATE TABLE [dbo].[KeynoteDaily](
        [day] [date] NOT NULL,
        [site] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
        [measurements] [smallint] NULL,
        [failures] [smallint] NULL,
        [contenterrors] [smallint] NULL,
        [availability_wc] [real] NULL,
        [availability_woc] [real] NULL,
        [errors] [varchar](1000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
        [loadtime] [smalldatetime] NULL,
        [comment] [varchar](2000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
 CONSTRAINT [PK_KeynoteDaily] PRIMARY KEY CLUSTERED
(
        [site] ASC,
        [day] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE NONCLUSTERED INDEX [ix_test] ON [dbo].[KeynoteDaily]
(
        [failures] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON,
ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
CREATE NONCLUSTERED INDEX [ix_test2] ON [dbo].[KeynoteDaily]
(
        [measurements] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON,
ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
</pre>
<p>Vagyis ő megcsinálja nekünk a rekurziót. Szerintem aranyos kényelmi szolgáltatás.<br />
Ja, a fentiekhez a teljes path a következő volt: <strong>PS SQLSERVER:\SQL\MYCOMPUTER\DENALI\Databases\MyDatabase\Tables&gt; </strong>. Csak a tisztánlátás kedvéért.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rollback.hu/2010/12/sql-objektumok-scriptelese-powershellben/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Backup listázás PowerShellben</title>
		<link>http://blog.rollback.hu/2010/04/backup-listazas-powershellben/</link>
		<comments>http://blog.rollback.hu/2010/04/backup-listazas-powershellben/#comments</comments>
		<pubDate>Tue, 27 Apr 2010 08:45:22 +0000</pubDate>
		<dc:creator>Erik</dc:creator>
				<category><![CDATA[Magyar]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[sqlcmd]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false">http://blog.rollback.hu/?p=256</guid>
		<description><![CDATA[Az SQL 2008 R2 előadásomon a Lurdy Házban mutattam egy PS scriptet, ami a következő igényt elégíti ki: egy fájlrendszeren lakó könyvtárban lévő backup fájlokból kinyalja a backup információkat. Íme a script:

function List-Backups(
[string] $filename, ##fájl vagy könyvtárnév, dir parancs számára emészthető input kell
$Html, ## HTML fájl output neve, .\ prefix kell neki lokális esetén
$servername = [...]]]></description>
			<content:encoded><![CDATA[<p>Az SQL 2008 R2 előadásomon a Lurdy Házban mutattam egy PS scriptet, ami a következő igényt elégíti ki: egy fájlrendszeren lakó könyvtárban lévő backup fájlokból kinyalja a backup információkat. Íme a script:</p>
<pre class="brush: powershell;">
function List-Backups(
[string] $filename, ##fájl vagy könyvtárnév, dir parancs számára emészthető input kell
$Html, ## HTML fájl output neve, .\ prefix kell neki lokális esetén
$servername = '.' ## az SQL Server, aki lefuttatja a restore headeronly parancsot
) {

## a tulajdonságok, amik kellenek - teljes lista a BOL-ban
$proplist = ('Position', 'DatabaseName','ServerName','BackupFinishDate','DatabaseVersion')
## mint fent, csak a filename mezővel prefixeltem. igénytelen, de gyors megoldás,
$proplist2 = ('FileName', 'Position', 'DatabaseName','ServerName','BackupFinishDate','DatabaseVersion')

## ez a tömb tárolja a teljes listát
$allbck = @()

foreach ($file in (dir $filename)) ## ezért kellett dir kompatibilis input
  {
  ## lefut a restore headeronly...
  $backups = invoke-sqlcmd -ServerInstance &quot;.\mysql&quot; -Query &quot;restore headeronly from disk = '$($file.FullName)'&quot;
  $bck = @()
  ## a kiválasztott mezoket eltesszük a $bck változóba.
  ##   Igazából perzisztált scriptben nem illik olyan shortcutokat használni, mint % (foreach) meg ? (where)
  $backups|select $proplist|%{$bck += $_}
  ## hozzáadjuk a fájlnevet is...
  $bck |add-member noteproperty filename $file.FullName
  ## ... és a kibövitett listát eltesszük az összegzett listába
  $allbck += $bck|select $proplist2
  } #foreach $file
## kiírjuk az összegzett listát a standard outputra - ez a függvény kimenete
$allbck
## ha meg lett adva HTML fájlnév, akkor abba is kitoljuk a táblázatot, és meg is nyitjuk. Itt lehetne kezelni a .\ hiányát, de nem tettem, lustaságból
if ($Html)
  {
  $allbck|ConvertTo-Html|Out-file $Html
  ## itt nyitjuk meg, az alkalmazás a default app a megadott kiterjesztéshez, tehát a böngészőnk htm(l)-nél
  invoke-expression $Html
  } #if $html
}  #function List-Backups

## És nézzünk néhány példát is:

## nézzük meg a D:\SQLData\Backups könyvtár tartalmát, HTML-ben is
List-Backups D:\SQLData\Backups .\lista.html
## nézzünk meg egyetlen fájlt a konzolon
List-Backups D:\SQLData\Backups\Full.BAK
##keressük meg a Billing adatbázis legfrissebb full backupját tartalmazó fájlt és a backup pozícióját a megadott könyvtárban
List-Backups D:\SQLData\Backups | ?{$_.DatabaseName -eq 'Billing' -and $_.BackupTypeDescription -eq 'DATABASE'} | `
 Sort -prop BackupFinishDate -desc| select Filename, Position -first 1
</pre>
<p>Az utolsó parancsba beletoltam több mindent is. A ? (where) a szűrést hivatott bemutatni, a -eq és az -and a vicces operátorokat, amit el is rontottam a demóban, a backtick a többsoros parancs sorvégét jelzi, a többi meg magától értetődő, de azért jó látni, hogy a lehetőségek szinte korlátlanok.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rollback.hu/2010/04/backup-listazas-powershellben/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Powershell profile-ok</title>
		<link>http://blog.rollback.hu/2010/04/powershell-profile-ok/</link>
		<comments>http://blog.rollback.hu/2010/04/powershell-profile-ok/#comments</comments>
		<pubDate>Fri, 16 Apr 2010 16:42:53 +0000</pubDate>
		<dc:creator>Erik</dc:creator>
				<category><![CDATA[Magyar]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://blog.rollback.hu/?p=242</guid>
		<description><![CDATA[Készülődve a jövő szerdai SQL Server 2008 R2 bejelentésre  éppen a Powershelles demómat reszelem-tesztelem, és örömmle tapasztaltam, hogy a PowerShell 2.0-hoz adott ISE, avagy GUI egy másik profile-t használ, mint a mezei parancssor, amiben ez látszik:

PS C:\Users\erik&#62; $profile
C:\Users\erik\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

Ezzel szemben az ISE ezt mondja:

PS C:\Windows\system32&#62; $profile
C:\Users\erik\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1

Biztos van különbség közöttük, gondoltam, majd elhatároztam, hogy csinálok egy [...]]]></description>
			<content:encoded><![CDATA[<p>Készülődve a<a href="http://www.microsoft.com/hun/technet/article/?id=bd5d606a-f906-46bb-b5af-ddd0b5ea0bdd"> jövő szerdai SQL Server 2008 R2 bejelentésre </a> éppen a Powershelles demómat reszelem-tesztelem, és örömmle tapasztaltam, hogy a PowerShell 2.0-hoz adott ISE, avagy GUI egy másik profile-t használ, mint a mezei parancssor, amiben ez látszik:</p>
<pre class="brush: plain;">
PS C:\Users\erik&gt; $profile
C:\Users\erik\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
</pre>
<p>Ezzel szemben az ISE ezt mondja:</p>
<pre class="brush: plain;">
PS C:\Windows\system32&gt; $profile
C:\Users\erik\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1
</pre>
<p>Biztos van különbség közöttük, gondoltam, majd elhatároztam, hogy csinálok egy symlinket (vagy hogy hívják azt Windowson) a sima profájlra. Aztán belenéztem az internetbe, és bing! máris megtaláltam a különbséget. Az ISE profile-ban gyakorlatilag kibővíthetjük az ISE menürendszerét, egy custom menüpontba betolhatjuk mindazt, amit szeretnénk még a GUI-ban látni, billentyűkombóval meg mindennel. It tvan pl. egy kedves kis minta: <a href="http://get-powershell.com/2008/12/29/code-snippets-in-powershell-ise/">http://get-powershell.com/2008/12/29/code-snippets-in-powershell-ise/</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rollback.hu/2010/04/powershell-profile-ok/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Technet Scripting Games 2010</title>
		<link>http://blog.rollback.hu/2010/03/technet-scripting-games-2010/</link>
		<comments>http://blog.rollback.hu/2010/03/technet-scripting-games-2010/#comments</comments>
		<pubDate>Mon, 29 Mar 2010 12:12:58 +0000</pubDate>
		<dc:creator>Erik</dc:creator>
				<category><![CDATA[Magyar]]></category>
		<category><![CDATA[esemény]]></category>
		<category><![CDATA[fejtoro]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://blog.rollback.hu/?p=229</guid>
		<description><![CDATA[És végre!!!! A régóta várt esemény újra itt van: Scripting Games a nemzetközi Technet oldalon! Anno ennek segítségével barátkoztam meg a VBscripttel. és még egy Scripto Bubble figurát (a képen látható) is nyertem a sorsoláson. Egy hónap múlva kezdődik, úgyhogy mindenki felszívhatja addig magát kedvenc scriptnyelvéből. 

Kalandra fel!
]]></description>
			<content:encoded><![CDATA[<p>És végre!!!! A régóta várt esemény újra itt van: Scripting Games a nemzetközi Technet oldalon! Anno ennek segítségével barátkoztam meg a VBscripttel. és még egy Scripto Bubble figurát (a képen látható) is nyertem a sorsoláson. Egy hónap múlva kezdődik, úgyhogy mindenki felszívhatja addig magát kedvenc scriptnyelvéből. </p>
<p><a href="http://blogs.technet.com/heyscriptingguy/archive/tags/2010+Scripting+Games/default.aspx"><img alt="2010 Scripting Games" src="http://bit.ly/2010sgbadge" style="display: block; margin: 0px auto" /></a></p>
<p>Kalandra fel!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rollback.hu/2010/03/technet-scripting-games-2010/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Log shipping PowerShell scripttel</title>
		<link>http://blog.rollback.hu/2010/03/log-shipping-powershell-scripttel/</link>
		<comments>http://blog.rollback.hu/2010/03/log-shipping-powershell-scripttel/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 07:04:48 +0000</pubDate>
		<dc:creator>Erik</dc:creator>
				<category><![CDATA[Magyar]]></category>
		<category><![CDATA[migráció]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false">http://blog.rollback.hu/?p=212</guid>
		<description><![CDATA[Egy hónapja ígértem meg Tibornak azt a PowerShelles log shipping megoldást, amit használtunk SQL 2000-2005 migrációra. Az alapgondolat a következő: a 2000-es szerveren csinálunk egy log backup jobot, ami már az új szerverre, UNC-n keresztül teszi le a backup fájlokat. Ez egy sima T-SQL job. A 2005-ös szerveren pedig egy Operating System jobstep lakik, ami [...]]]></description>
			<content:encoded><![CDATA[<p>Egy hónapja <a href="http://blog.rollback.hu/2010/02/sql-2005-2008-upgrade-jatekosan/">ígértem meg</a> Tibornak azt a PowerShelles log shipping megoldást, amit használtunk SQL 2000-2005 migrációra. Az alapgondolat a következő: a 2000-es szerveren csinálunk egy log backup jobot, ami már az új szerverre, UNC-n keresztül teszi le a backup fájlokat. Ez egy sima T-SQL job. A 2005-ös szerveren pedig egy Operating System jobstep lakik, ami egy powershell scriptet futtat. A jobstep maga kb. ennyi: <strong>powershell.exe D:\mssql\MigrateMyDB.ps1</strong>. Ez most egy bedrótozott verzió, de elég egyszerűen átalakítható paraméterezhetővé, és akkor egy scripttel lehet több adatbázist is tutujgatni.<br />
<span id="more-212"></span></p>
<p>A log backup script helyett a magunk log backup tárolt eljárását teszem közzé &#8211; eléggé elegem lett a maintenance planekből, úgyhogy én így mentek:</p>
<pre class="brush: sql;">
CREATE procedure [bckup].[spBackupLogDatabase]
@dbname varchar(128),
@backupdir varchar(512) = NULL -- tegyél \-t a path végére!
AS
declare @str varchar(2000)
declare @errornumber varchar(5), @errormessage varchar(1000)
BEGIN TRY
select @str = 'backup log ' + @dbname +
	' to disk = ''' + @backupdir + @dbname + '_Log_' +
	replace(replace(replace(convert(varchar(16),getdate(),120),'-',''), ' ', ''), ':', '') +
	'.TRN'''
exec(@str)
END TRY
BEGIN CATCH
-- itt én custom error message-et használok, de lehet a sima 50001-et is raiselni
    SELECT
        @errornumber = ERROR_NUMBER(),
        @errormessage = ERROR_MESSAGE();
	SELECT @errormessage = 'Error number: ' + @errornumber + ', message: ' + @errormessage
	RAISERROR (999001,16,1, 'log', @dbname, @errormessage)
END CATCH
</pre>
<p>Ezt valami olyasmi módon hívjuk meg, hogy </p>
<pre class="brush: sql;">
EXEC [bckup].[spBackupLogDatabase] 'MyDB', '\\myserver\backups\'
</pre>
<p>A Powershell script pedig a következőket teszi: felolvassa a .trn kiterjesztésű fájlokat keletkezési sorrendben, aztán elkezdi restore-olni őket. Az éppen aktuális fájl kiterjesztését átírja .NOW-ra, és amikor kész van vele, akkor pedig .DONE-ra. így ha bukta van, akkor a .NOW kiterjesztésű fájlokat vissza kell nevezni .trn-re és lehet folytatni a probléma megoldása után a folyamatot.</p>
<pre class="brush: powershell;">
Set-PSDebug -Strict

##adatbázis neve
$dbname = 'MyDB'

##ide írjuk a logot
$logfile = &quot;D:\mssql\logs\$($dbname).log&quot;
##ebbe a könyvtárba kerülnek a transaction log backupok
$logdir = &quot;D:\mssql\backups\$($dbname)\'

##a secondary szerver, ahova restore-olunk
$servername = 'MYSERVER,1438'

$restore_cmd = &quot;restore log =DBNAME=
from disk = '=DIR==FILE='
with norecovery&quot;

$restore_cmd_orig = ($restore_cmd -replace '=DBNAME=', $dbname) -replace '=DIR=', $logdir

##felolvassuk a log backup fajlokat
$files = Get-ChildItem $logdir -Filter '*.TRN' | Sort-Object -Property &quot;LastWriteTime&quot;
if ($files -eq $null) {
	&quot;No file to process&quot;
	Exit
	} #if ($files.Length -eq 0) 

##restore-oljuk a meg nem restore-olt fajlokat
foreach ($f in $files) {
	$f.PSPath
	$f_new = rename-item -path $f.PSPath -newname ($f.Name -replace '.TRN', '.NOW')
	$restore_cmd = $restore_cmd_orig -replace '=FILE=', ($f.Name -replace '.TRN', '.NOW')
	$restore_res = sqlcmd -E -S $servername -Q $restore_cmd

	Get-Date -Format 'yyyy-MM-dd HH:mm:ss' |out-file $logfile -Append
	$restore_cmd |out-file $logfile -Append
	$restore_res |out-file $logfile -Append

	if ($restore_res | select-string -quiet &quot;abnormally&quot;) {
		Write-Error &quot;Restore had problems, see the following error:&quot;
		Write-Error ($restore_res| Out-String)
		throw $restore_res
		# stop no matter the cost
		Exit
		} #if restore abnormal
##nevezzuk at a sikeresen betoltott fajlokat
	rename-item -Path ($f.PSPath -replace '.TRN', '.NOW') -newname ($f.Name -replace '.trn', '.DONE')

	#write restore log:
	Get-Date -Format 'yyyy-MM-dd HH:mm:ss' |out-file -Append $logfile
	} #foreach ($file in $files)
</pre>
<p>Hát ennyi. A restore után volt még egy második lépés is, szintén powershell, ami takarította a könyvtárat. Szerintem ez elég egyszerű, persze nincs is benne atombiztos hibakezelés, szóval lehet használni, de ha bedől, nem adok pénzt, ezt leszögezem.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rollback.hu/2010/03/log-shipping-powershell-scripttel/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

