Այս հոդվածը զուտ գործնական է և նվիրված է իմ տխուր պատմությանը
Պատրաստվում է Zero Touch PROD RDS-ի (MS SQL) համար, որի մասին բոլորը շատ էին խոսում, ես ներկայացրեցի ավտոմատացման վերաբերյալ ներկայացում (POC - Proof of Concept)՝ PowerShell սկրիպտների հավաքածու։ Ներկայացումից հետո, երբ որոտալից, երկարատև ծափահարությունները, որոնք վերածվեցին կանգնած ծափահարությունների, մարեցին, նրանք ինձ ասացին. սա բոլորը լավ է, բայց գաղափարական պատճառներով մեր բոլոր Jenkins ստրուկները վազում են... Linux!
Հնարավո՞ր է սա։ Այդքան տաք, խողովականման DBA վերցնել ներքևից։ Windows և տեղադրեք այն PowerShell-ի ամենահաստ մասում LinuxՉէ՞ որ դա դաժան է։

Ես ստիպված էի խորանալ տեխնոլոգիաների այս տարօրինակ համադրության մեջ։ Բնականաբար, իմ բոլոր 30+ սկրիպտները դադարեցին աշխատել։ Ի զարմանս ինձ, ես կարողացա ամեն ինչ շտկել մեկ աշխատանքային օրվա ընթացքում։ Ես սա գրում եմ, քանի դեռ նորությունները դեռ թարմ են։ Այսպիսով, ինչպիսի՞ թակարդների կարող եք հանդիպել PowerShell սկրիպտները միգրացիայի ժամանակ։ Windows տակ Linux?
sqlcmd vs Invoke-SqlCmd
Հիշեցնեմ նրանց հիմնական տարբերությունը. Լավ հին կոմունալ sqlcmd Այն նաև աշխատում է Linux-ի ներքո՝ գրեթե նույնական ֆունկցիոնալությամբ: Հարցումը կատարում ենք -Q, մուտքային ֆայլը՝ -i, իսկ ելքը՝ -o: Բայց ֆայլերի անունները, իհարկե, մեծատառերի զգայուն են: Եթե օգտագործում եք -i, ապա ֆայլում վերջում գրեք.
GO
EXITԵթե վերջում EXIT չկա, ապա sqlcmd-ը կշարունակի սպասել մուտքագրմանը, և եթե նախկինում Ելք չի լինի GO, ապա վերջին հրամանը չի աշխատի։ Ելքային ֆայլը պարունակում է բոլոր արդյունքները, ընտրվածները, հաղորդագրությունները, տպագրությունը և այլն:
Invoke-SqlCmd-ն արդյունք է տալիս որպես DataSet, DataTables կամ DataRows: Հետեւաբար, եթե դուք մշակում եք պարզ ընտրության արդյունքը, կարող եք օգտագործել sqlcmd, վերլուծելով դրա արդյունքը, գրեթե անհնար է բարդ բան դուրս բերել. դրա համար կա Invoke-SqlCmd. Բայց այս թիմն ունի նաև իր կատակները.
- Եթե դուք ֆայլ եք փոխանցում նրան միջոցով -InputFile, Հետո Ելք անհրաժեշտ չէ, ավելին, այն առաջացնում է շարահյուսական սխալ
- - OutputFile ոչ, հրամանը ձեզ վերադարձնում է արդյունքը որպես օբյեկտ
- Սերվերը նշելու երկու շարահյուսություն կա. -ServerInstance -Օգտվողի անուն -Գաղտնաբառ -Տվյալների բազա և միջոցով -ConnectionString. Տարօրինակ կերպով, առաջին դեպքում հնարավոր չէ նշել 1433-ից այլ նավահանգիստ:
- տեքստի ելք, տպեք PRINT, որը պարզապես «բռնված» է sqlcmdհամար Invoke-SqlCmd
- Եվ ամենակարևորը.
Եվ սա է հիմնական խնդիրը։ Միայն մարտին այս cmdlet-ը , և վերջապես մենք կարող ենք առաջ շարժվել:
Փոփոխական փոխարինում
sqlcmd-ն ունի փոփոխական փոխարինում՝ օգտագործելով -v, օրինակ՝ այսպես.
# $conn содержит начало команды sqlcmd
$cmd = $conn + " -i D:appsSlaveJobsKillSpid.sql -o killspid.res
-v spid =`"" + $spid + "`" -v age =`"" + $age + "`""
Invoke-Expression $cmdSQL սկրիպտում մենք օգտագործում ենք փոխարինումներ.
set @spid=$(spid)
set @age=$(age)Այսպիսով, ահա այն: * nix-ում Փոփոխական փոխարինումները չեն աշխատում. Պարամետր -v անտեսված. U Invoke-SqlCmd անտեսված -Փոփոխականներ. Չնայած այն պարամետրը, որը սահմանում է հենց փոփոխականները, անտեսվում է, փոխարինումներն իրենք են աշխատում. կարող եք օգտագործել Shell-ի ցանկացած փոփոխական: Այնուամենայնիվ, ես վիրավորված էի փոփոխականներից և որոշեցի ընդհանրապես կախված չլինել դրանցից և գործեցի կոպիտ և պարզունակ, քանի որ SQL սցենարները կարճ են.
# prepend the parameters
"declare @age int, @spid int" | Add-Content "q.sql"
"set @spid=" + $spid | Add-Content "q.sql"
"set @age=" + $age | Add-Content "q.sql"
foreach ($line in Get-Content "Sqlserver/Automation/KillSpid.sql") {
$line | Add-Content "q.sql"
}
$cmd = "/opt/mssql-tools/bin/" + $conn + " -i q.sql -o res.log"Սա, ինչպես հասկանում եք, արդեն թեստ է Unix տարբերակից։
Ֆայլերի բեռնում
Windows-ի տարբերակում ցանկացած գործողություն ուղեկցվում էր աուդիտով՝ մենք գործարկեցինք sqlcmd, ստացանք ինչ-որ չարաշահում ելքային ֆայլում, կցեցինք այս ֆայլը աուդիտի ափսեին: Բարեբախտաբար, SQL սերվերը աշխատում էր նույն սերվերի վրա, ինչ Ջենքինսը, դա արվեց հետևյալ կերպ.
CREATE procedure AuditUpload
@id int, @filename varchar(256)
as
set nocount on
declare @sql varchar(max)
CREATE TABLE #multi (filer NVARCHAR(MAX))
set @sql='BULK INSERT #multi FROM '''+@filename
+''' WITH (ROWTERMINATOR = '' '',CODEPAGE = ''ACP'')'
exec (@sql)
select @sql=filer from #multi
update JenkinsAudit set multiliner=@sql where ID=@id
returnԱյսպիսով, մենք ամբողջությամբ կուլ ենք տալիս BCP ֆայլը և այն տեղափոխում աուդիտի աղյուսակի nvarchar(max) դաշտ: Իհարկե, այս ամբողջ համակարգը փլուզվեց, քանի որ SQL սերվերի փոխարեն ես ստացա RDS, իսկ BULK INSERT-ն ընդհանրապես չի աշխատում UNC-ի միջոցով՝ ֆայլի վրա բացառիկ կողպելու փորձի պատճառով, և RDS-ով դա ընդհանրապես դատապարտված է: հենց սկիզբը. Այսպիսով, ես որոշեցի փոխել համակարգի դիզայնը, պահելով աուդիտը տող առ տող.
CREATE TABLE AuditOut (
ID int NULL,
TextLine nvarchar(max) NULL,
n int IDENTITY(1,1) PRIMARY KEY
)Եվ այս աղյուսակում գրեք այսպես.
function WriteAudit([string]$Filename, [string]$ConnStr,
[string]$Tabname, [string]$Jobname)
{
# get $lastid of the last execution -- проскипано для статьи
#create grid and populate it with data from file
$audit = Get-Content $Filename
$DT = new-object Data.DataTable
$COL1 = new-object Data.DataColumn;
$COL1.ColumnName = "ID";
$COL1.DataType = [System.Type]::GetType("System.Int32")
$COL2 = new-object Data.DataColumn;
$COL2.ColumnName = "TextLine";
$COL2.DataType = [System.Type]::GetType("System.String")
$DT.Columns.Add($COL1)
$DT.Columns.Add($COL2)
foreach ($line in $audit)
{
$DR = $dt.NewRow()
$DR.Item("ID") = $lastid
$DR.Item("TextLine") = $line
$DT.Rows.Add($DR)
}
# write it to table
$conn=new-object System.Data.SqlClient.SQLConnection
$conn.ConnectionString = $ConnStr
$conn.Open()
$bulkCopy = new-object ("Data.SqlClient.SqlBulkCopy") $ConnStr
$bulkCopy.DestinationTableName = $Tabname
$bulkCopy.BatchSize = 50000
$bulkCopy.BulkCopyTimeout = 0
$bulkCopy.WriteToServer($DT)
$conn.Close()
}
Բովանդակություն ընտրելու համար անհրաժեշտ է ընտրել ըստ ID-ի՝ ընտրելով n (ինքնություն) հերթականությունը:
Հաջորդ հոդվածում ես ավելի մանրամասն կանդրադառնամ, թե ինչպես է այս ամենը փոխազդում Ջենկինսի հետ:
Source: www.habr.com
