Linuxలో Powershell నుండి MS SQLతో పని చేస్తోంది

ఈ వ్యాసం పూర్తిగా ఆచరణాత్మకమైనది మరియు నా విచారకరమైన కథకు అంకితం చేయబడింది

కోసం సిద్ధమవుతున్నారు జీరో టచ్ PROD RDS (MS SQL) కోసం, మా చెవులన్నీ సందడి చేస్తున్నాయి, నేను ఆటోమేషన్ యొక్క ప్రెజెంటేషన్ (POC - ప్రూఫ్ ఆఫ్ కాన్సెప్ట్) చేసాను: పవర్‌షెల్ స్క్రిప్ట్‌ల సమితి. ప్రదర్శన తరువాత, తుఫాను, సుదీర్ఘమైన చప్పట్లు తగ్గినప్పుడు, అవి ఎడతెగని చప్పట్లుగా మారినప్పుడు, వారు నాకు చెప్పారు - ఇవన్నీ మంచివి, కానీ సైద్ధాంతిక కారణాల వల్ల మాత్రమే, మన జెంకిన్స్ బానిసలందరూ Linuxలో పని చేస్తారు!

ఇది సాధ్యమా? విండోస్ కింద నుండి అలాంటి వెచ్చగా, ల్యాంప్ DBAని తీసుకుని, Linux కింద పవర్‌షెల్ వేడిలో అతికించాలా? ఇది దారుణం కాదా?

Linuxలో Powershell నుండి MS SQLతో పని చేస్తోంది
ఈ విచిత్రమైన సాంకేతికతల కలయికలో నేను మునిగిపోవలసి వచ్చింది. అయితే, నా 30+ స్క్రిప్ట్‌లు పని చేయడం ఆగిపోయాయి. నా ఆశ్చర్యానికి, నేను ఒక పని రోజులో ప్రతిదీ పరిష్కరించగలిగాను. నేను హాట్ ముసుగులో వ్రాస్తున్నాను. కాబట్టి, Windows నుండి Linuxకి పవర్‌షెల్ స్క్రిప్ట్‌లను బదిలీ చేసేటప్పుడు మీరు ఏ ఆపదలను ఎదుర్కోవచ్చు?

sqlcmd vs ఇన్వోక్-SqlCmd

వాటి మధ్య ఉన్న ప్రధాన వ్యత్యాసాన్ని నేను మీకు గుర్తు చేస్తాను. మంచి పాత యుటిలిటీ sqlcmd ఇది దాదాపు ఒకే విధమైన కార్యాచరణతో Linux క్రింద కూడా పని చేస్తుంది. మేము -Qని అమలు చేయడానికి ప్రశ్నను, ఇన్‌పుట్ ఫైల్‌ను -iగా మరియు అవుట్‌పుట్‌ను -oగా పాస్ చేస్తాము. కానీ ఫైల్ పేర్లు, వాస్తవానికి, కేస్-సెన్సిటివ్‌గా ఉంటాయి. మీరు -i ఉపయోగిస్తే, ఫైల్‌లో చివర వ్రాయండి:

GO
EXIT

చివరిలో నిష్క్రమణ లేకపోతే, sqlcmd ఇన్‌పుట్ కోసం వేచి ఉండటానికి కొనసాగుతుంది మరియు ముందు అయితే EXIT వుండదు GO, అప్పుడు చివరి ఆదేశం పనిచేయదు. అవుట్‌పుట్ ఫైల్‌లో అన్ని అవుట్‌పుట్, సెలెక్ట్‌లు, మెసేజ్‌లు, ప్రింట్ మొదలైనవి ఉంటాయి.

Invoke-SqlCmd డేటాసెట్, డేటా టేబుల్స్ లేదా డేటారోస్‌గా ఫలితాన్ని ఉత్పత్తి చేస్తుంది. అందువల్ల, మీరు సాధారణ ఎంపిక యొక్క ఫలితాన్ని ప్రాసెస్ చేస్తే, మీరు ఉపయోగించవచ్చు sqlcmd, దాని అవుట్‌పుట్‌ను అన్వయించడం ద్వారా, సంక్లిష్టమైనదాన్ని పొందడం దాదాపు అసాధ్యం: దీని కోసం ఉంది ఇన్వోక్-SqlCmd. కానీ ఈ బృందానికి దాని స్వంత జోకులు కూడా ఉన్నాయి:

  • మీరు ఆమె ద్వారా ఫైల్‌ను బదిలీ చేస్తే -ఇన్‌పుట్ ఫైల్, అప్పుడు EXIT అవసరం లేదు, అంతేకాకుండా, ఇది సింటాక్స్ లోపాన్ని ఉత్పత్తి చేస్తుంది
  • -అవుట్‌పుట్ ఫైల్ లేదు, కమాండ్ మీకు ఫలితాన్ని వస్తువుగా అందిస్తుంది
  • సర్వర్‌ను పేర్కొనడానికి రెండు సింటాక్స్‌లు ఉన్నాయి: -ServerInstance -యూజర్ పేరు -పాస్‌వర్డ్ -డేటాబేస్ మరియు ద్వారా -కనెక్షన్ స్ట్రింగ్. విచిత్రమేమిటంటే, మొదటి సందర్భంలో 1433 కాకుండా వేరే పోర్ట్‌ను పేర్కొనడం సాధ్యం కాదు.
  • టెక్స్ట్ అవుట్‌పుట్, ప్రింట్ అని టైప్ చేయండి, ఇది కేవలం "క్యాచ్" sqlcmdకోసం ఇన్వోక్-SqlCmd అనేది ఒక సమస్య
  • మరియు ముఖ్యంగా: చాలా మటుకు మీ Linuxలో ఈ cmdlet లేదు!

మరియు ఇది ప్రధాన సమస్య. మార్చిలో మాత్రమే ఈ cmdlet విండోస్ కాని ప్లాట్‌ఫారమ్‌లకు అందుబాటులోకి వచ్చింది, చివరకు మనం ముందుకు సాగవచ్చు!

వేరియబుల్ ప్రత్యామ్నాయం

sqlcmd -v ఉపయోగించి వేరియబుల్ ప్రత్యామ్నాయం ఉంది, ఉదాహరణకు ఇలా:

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

SQL స్క్రిప్ట్‌లో మేము ప్రత్యామ్నాయాలను ఉపయోగిస్తాము:

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

కాబట్టి ఇదిగో ఇదిగో. In *nix వేరియబుల్ ప్రత్యామ్నాయాలు పని చేయవు. పరామితి -v పట్టించుకోలేదు. యు ఇన్వోక్-SqlCmd పట్టించుకోలేదు -వేరియబుల్స్. వేరియబుల్స్‌ను పేర్కొనే పరామితి విస్మరించబడినప్పటికీ, ప్రత్యామ్నాయాలు స్వయంగా పనిచేస్తాయి-మీరు షెల్ నుండి ఏదైనా వేరియబుల్‌లను ఉపయోగించవచ్చు. అయినప్పటికీ, నేను వేరియబుల్స్‌తో మనస్తాపం చెందాను మరియు వాటిపై ఆధారపడకూడదని నిర్ణయించుకున్నాను మరియు 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"

ఇది, మీరు అర్థం చేసుకున్నట్లుగా, ఇప్పటికే యునిక్స్ వెర్షన్ నుండి ఒక పరీక్ష.

ఫైల్ ఎక్కించుట

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(గరిష్టంగా) ఫీల్డ్‌లోకి పంపుతాము. వాస్తవానికి, ఈ మొత్తం వ్యవస్థ విచ్ఛిన్నమైంది, ఎందుకంటే SQL సర్వర్‌కు బదులుగా నాకు RDS వచ్చింది మరియు ఫైల్‌పై ప్రత్యేకమైన లాక్‌ని తీసుకునే ప్రయత్నం కారణంగా 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 (గుర్తింపు) క్రమంలో ఎంచుకోవాలి.

జెంకిన్స్‌తో ఇవన్నీ ఎలా సంకర్షణ చెందుతాయి అనే దాని గురించి నేను తదుపరి కథనంలో మరింత వివరంగా తెలియజేస్తాను.

మూలం: www.habr.com

ఒక వ్యాఖ్యను జోడించండి