本文纯粹是实用的,致力于我的悲伤故事。
为了准备让RDS(MS SQL)
零接触的PROD ,我们的耳朵都在嗡嗡作响,我做了一个关于自动化的演示(POC-概念验证):一组Powershell脚本。 演讲结束后,当长时间的热烈掌声渐渐消退,并不断鼓掌时,我被告知这一切都很好,但是仅出于意识形态的原因,我们所有人都在Linux下运行Jenkins奴隶!
有可能吗 要从Windows下获得如此热情的DBA,并使其在Linux下非常强大的功能中呢? 那不是很残忍吗?
我不得不深入研究这种奇怪的技术组合。 当然,我所有的30多个脚本都停止了工作。 令我惊讶的是,在一个工作日内,我设法解决了所有问题。 我正在紧追写作。 因此,将Powershell脚本从Windows移植到Linux时,会遇到什么陷阱?
sqlcmd与Invoke-SqlCmd
让我提醒您它们之间的主要区别。 好的旧
sqlcmd实用程序
也可以在Linux下运行,并且功能几乎相同。 要执行查询,我们传递-Q,输入文件为-i,输出为-o。 当然,这里只是文件名,区分大小写。 如果使用-i,则在末尾写入文件:
GO EXIT
如果结尾没有EXIT,则sqlcmd将等待输入,如果
EXIT之前没有
GO ,则最后一条命令将无效。 所有输出,选择,消息,打印等,都进入输出文件。
Invoke-SqlCmd将结果作为DataSet,DataTables或DataRows返回。 因此,如果您可以通过
sqlcmd处理简单选择的结果,
解析其输出,然后输出复杂的内容几乎是不可能的:为此有
Invoke-SqlCmd 。 但是这支球队有自己的笑话:
- 如果通过-InputFile将文件传递给它,则不需要EXIT ,此外,它还会产生语法错误
- -OutputFile不是,该命令将结果作为对象返回
- 用于指定服务器的语法有两种: -ServerInstance -Username -Password -Database和通过-ConnectionString 。 奇怪的是,在第一种情况下,您不能指定1433以外的端口。
- Invoke-SqlCmd遇到 的问题是PRINT类型的文本输出,它被sqlcmd “捕获”
- 最重要的是: 此cmdlet最有可能不在您的Linux中!
这是主要问题。 仅在三月份,此cmdlet
才可用于非Windows平台 ,最后我们可以继续前进!
变量替代
Sqlcmd使用-v进行变量替换,如下所示:
在SQL脚本中,我们使用替换:
set @spid=$(spid) set @age=$(age)
所以在这里。 在* nix中
,变量替换无效 。
-v选项将被忽略。
Invoke-SqlCmd忽略
-Variables 。 尽管设置变量本身的参数将被忽略,但是替换本身也可以工作-您可以使用Shell中的任何变量。 但是,我对变量感到恼火,并决定根本不依赖它们,并且由于sql的脚本很短,因此我的行为举止粗俗:
如您所知,这是对Unix版本的测试。
上载档案
在Windows版本中,我执行的任何操作都伴随着审核:我们执行了sqlcmd,在输出文件中出现了某种滥用,并将此文件附加到审核板上。 幸运的是,SQL Server与Jenkins在同一服务器上工作,它是这样完成的:
CREATE procedure AuditUpload @id int, @filename varchar(256) as set nocount on declare @sql varchar(max) CREATE TABLE
因此,我们吞下了整个BCP文件,并在nvarchar(max)字段中插入了审核表。 当然,整个系统崩溃了,因为我没有使用SQL Server而是使用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) {
要选择内容,请按ID选择,然后依次选择n(身份)。
在下一篇文章中,我将详细介绍这一切与詹金斯的互动方式。