Bi MS SQL ji Powershell li ser Linux re dixebitin

Ev gotar bi tevahî pratîkî ye û ji çîroka min a xemgîn re hatî veqetandin

Amadekirina ji bo Zero Touch PROD ji bo RDS (MS SQL), ya ku hemî guhên me lê diqeliqî, min pêşandanek (POC - Proof Of Concept) otomatê çêkir: komek nivîsarên powershell. Piştî pêşkêşiyê, dema ku çepikên bahoz û dirêj mir, veguherî çepikên bênavber, wan ji min re got - ev hemî baş e, lê tenê ji ber sedemên îdeolojîk, hemî koleyên me yên Jenkins li ser Linux dixebitin!

Ma ev gengaz e? DBA-ya wusa germ, çira ji binê Windows-ê derxînin û di bin Linux-ê de di germahiya hêzê de bihêlin? Ma ev ne zilm e?

Bi MS SQL ji Powershell li ser Linux re dixebitin
Diviya bû ku ez xwe di nav vê tevliheviya ecêb a teknolojiyê de biçim. Bê guman, hemî 30+ senaryoyên min ji xebatê rawestiyan. Bi şaşwaziya min, min di rojek xebatê de her tiştî rast kir. Ez di nav lêgerîna germ de dinivîsim. Ji ber vê yekê, dema ku hûn nivîsarên powershell ji Windows-ê li Linux veguhezînin hûn dikarin bi çi xeletiyan re rûbirû bibin?

sqlcmd vs Invoke-SqlCmd

Bila ez ferqa sereke ya di navbera wan de bi bîr bînim. Karsaziya kevn a baş sqlcmd Di heman demê de ew di bin Linux-ê de, bi fonksiyonek hema hema yekane jî dixebite. Em pirsê derbas dikin da ku -Q, pelê têketinê wekî -i, û derketinê wekî -o. Lê navên pelan, bê guman, bi hesas têne çêkirin. Ger hûn -i bikar bînin, wê hingê di pelê de li dawiyê binivîsin:

GO
EXIT

Ger di dawiyê de DERKET tunebe, wê hingê sqlcmd dê li benda têketinê bimîne, û heke berê DERÎ neyê GO, wê hingê emrê paşîn dê nexebite. Pelê derketinê hemî encam, hilbijartî, peyam, çapkirin, hwd vedihewîne.

Invoke-SqlCmd encamê wekî DataSet, DataTables an DataRows çêdike. Ji ber vê yekê, heke hûn encama hilbijarkek hêsan pêvajoyê bikin, hûn dikarin bikar bînin sqlcmd, piştî ku hilberîna wê pars bike, hema ne gengaz e ku meriv tiştek tevlihev derxîne: ji ber vê yekê heye Invoke-SqlCmd. Lê vê tîm jî henekên xwe hene:

  • Ger hûn pelek bi rêya wê veguhezînin -InputFile, paşê DERÎ ne hewce ye, ji bilî vê, ew xeletiyek hevoksaziyê çêdike
  • -OutputFile na, emrê we encamê wekî objeyekê vedigerîne
  • Ji bo diyarkirina serverek du hevoks hene: -ServerInstance -Navê bikarhêner -Şîfre -Database û bi rêya -ConnectionString. Pir ecêb e, di doza yekem de ne gengaz e ku ji bilî 1433-ê portek din diyar bike.
  • derana nivîsê, PRINT binivîsin, ku bi tenê "girtin" sqlcmdji bo Invoke-SqlCmd pirsgirêkek e
  • Û ya herî girîng: Bi îhtîmaleke mezin Linuxa we ev cmdlet nîne!

Û ev pirsgirêka sereke ye. Tenê di meha Adarê de ev cmdlet ji bo platformên ne-Windows peyda bû, û di dawiyê de em dikarin pêşde biçin!

Cîgira guherbar

sqlcmd bi karanîna -v-ê veguhertina guhêrbar heye, mînakî bi vî rengî:

# $conn содержит начало команды sqlcmd
$cmd = $conn + " -i D:appsSlaveJobsKillSpid.sql -o killspid.res 
  -v spid =`"" + $spid + "`" -v age =`"" + $age + "`""
Invoke-Expression $cmd

Di skrîpta SQL de em cîgiran bikar tînin:

set @spid=$(spid)
set @age=$(age)

Ji ber vê yekê ev e. Li *nix guherbarên guherbar kar nakin. Parametre -v paşguh kirin. U Invoke-SqlCmd paşguh kirin -Guherbar. Her çend pîvana ku guhêrbaran bi xwe diyar dike were paşguh kirin jî, veguheztin bixwe dixebitin-hûn dikarin her guhêrbaran ji Shell bikar bînin. Lêbelê, ez ji guherbaran aciz bûm û min biryar da ku ez çu carî bi wan ve nemînim, û bi bêaqilî û primitive tevgeriyam, ji ber ku nivîsarên SQL kurt in:

# 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"

Ev, wekî ku hûn fêm dikin, ceribandinek berê ji guhertoya Unix-ê ye.

Barkirina pelan

Di guhertoya Windows-ê de, her operasyonek bi vedîtinê re hat: me sqlcmd dimeşîne, di pelê derketinê de celebek destdirêjî wergirt, vê pelê bi plakaya kontrolê ve girêda. Xwezî, servera SQL li ser heman serverê wekî Jenkins xebitî, tiştek bi vî rengî hate kirin:

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

Bi vî rengî, em pelê BCP bi tevahî dadiqurtînin û wê di qada nvarchar(max) ya tabloya kontrolê de vedişêrin. Bê guman, ev pergal tev hilweşiya, ji ber ku li şûna serverek SQL min RDS stend, û BULK INSERT ji ber hewildanek ji bo girtina kilîtek taybetî li ser pelek bi tevahî bi UNC-ê naxebite, û bi RDS re ev bi gelemperî ji mehkûmê tê mehkûm kirin. pir destpêkê. Ji ber vê yekê min biryar da ku sêwirana pergalê biguhezim, rêz bi rêz veguhezîne:

CREATE TABLE AuditOut (
  ID int NULL,
  TextLine nvarchar(max) NULL,
  n int IDENTITY(1,1) PRIMARY KEY
  )

Û di vê tabloyê de bi vî awayî binivîse:

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() 
  }  

Ji bo bijartina naverokê, hûn hewce ne ku bi nasnameya xwe hilbijêrin, bi rêzê n (nasname) hilbijêrin.

Di gotara din de ez ê bi hûrgulî biçim ka ev hemî çawa bi Jenkins re têkilî dike.

Source: www.habr.com

Add a comment