Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 使用不同的凭据调用SQLCmd_Sql Server_Powershell - Fatal编程技术网

Sql server 使用不同的凭据调用SQLCmd

Sql server 使用不同的凭据调用SQLCmd,sql-server,powershell,Sql Server,Powershell,背景: 我正在本地运行一个脚本,该脚本必须作为系统运行,让我们不要深入了解原因。:) 脚本试图通过一个简单的查询来检查我的MSSQL集群的运行状况。然而,我遇到的问题是本地系统帐户无法访问远程数据库。在这一点上,我已经尝试了很多事情,我会在一段时间内进入,但我诚实地为任何有意义的解决方案。如果这意味着在数据库中创建一个本地帐户来回答我的简单查询,那也没关系 到目前为止,我有以下几点: $Server = 'myserver.domain.tld' $Database = 'myDatabase'

背景: 我正在本地运行一个脚本,该脚本必须作为系统运行,让我们不要深入了解原因。:) 脚本试图通过一个简单的查询来检查我的MSSQL集群的运行状况。然而,我遇到的问题是本地系统帐户无法访问远程数据库。在这一点上,我已经尝试了很多事情,我会在一段时间内进入,但我诚实地为任何有意义的解决方案。如果这意味着在数据库中创建一个本地帐户来回答我的简单查询,那也没关系

到目前为止,我有以下几点:

$Server = 'myserver.domain.tld'
$Database = 'myDatabase'
$Query = 'SELECT DB_NAME() AS DataBaseName'
$Username = 'myDomain\myUsername'
$Password = 'myPasswordWithPlainText'
Invoke-SQLCmd -ServerInstance $Server -Database $Database -ConnectionTimeout 300 -QueryTimeout 600 -Query $Query -Username $Username -Password $Password
结果:
Invoke-Sqlcmd:Login用户'myDomain\myUsername'失败。

也许调用SQL不需要Windows身份验证,但它不使用-Credential。然后我尝试使用Invoke命令作为包装器

$Server = 'myserver.domain.tld'
$Database = 'myDatabase'
$Query = 'SELECT DB_NAME() AS DataBaseName'
$Username = 'myDomain\myUsername'
$Password = 'myPasswordWithPlainText'
$secpasswd = ConvertTo-SecureString $Password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($Username, $secpasswd)
Invoke-Command -script {Invoke-SQLCmd -ServerInstance $Server -Database $Database -ConnectionTimeout 300 -QueryTimeout 600 -Query $Query} -Credential $Credential
这让我明白了:
Invoke命令:无法使用指定的命名参数解析参数集。


所以。。我卡住了。有什么想法吗

对于这类事情,我们取得了很大的成功

不确定Powershell是否有等效的东西(可能只是使用RUNAS/NETONLY运行Powershell)。如果您正在将其构建到应用程序中,我们将使用Windows API重新启动:


另外:

我使用Get-Credential,然后调用命令-AsJob从.sql文件运行脚本。e、 g

$s = 'myserver.domain.tld';
$scriptpath = 'C:\myfile.sql';
$cred = Get-Credential -credential domain\user;
$sess = New-PSSession -ComputerName $s -Credential $cred -Authentication CredSSP -Name 'S1';
$job1 = Invoke-Command -Session $sess -FilePath $scriptpath -AsJob -JobName 'J1';
  # -ArgumentList $args;

Get-Job | Wait-Job;
Get-Job -Name 'J1';

Get-PSSession | Remove-Session;
Get-Job | Remove-Job;

但是请注意,$cred行将启动一个确认/验证凭据的提示-我在脚本中也有数据库名称,因此我不确定如何更改此逻辑以将脚本指向任何数据库(如果需要针对每台服务器进行自定义)。

如果尚未检查用户是否有权访问数据库:-)

如果他这样做了,你就可以避开这个问题,使用.net对象——不是那么简洁,可能还有其他问题,但可以像使用连接字符串一样工作

这是未经测试的:-)

可悲的是,我尝试了所有的方法(包括马特的建议),然后又尝试了一些,但在以下参数下,我无法让它工作。 1) 脚本是从作为系统帐户运行的服务启动的。2) 系统位于SQL群集以外的单独域/子网/etc中。3) 查询必须实时运行并返回,因为查询只是较大脚本的一部分


现在,我已经认输了,创建了一个本地SQL登录名,然后使用-username和-password选项按原样调用SQL。这不是我想如何处理这种情况,而是事实。谢谢大家!

您可以尝试提交作业并传递凭据

#Submit the job with creds
$job = Start-Job {importsystemmodules; Invoke-Sqlcmd -Query 'select @@version'  -ServerInstance LOCALHOST} -Credential $creds | Get-Job | Wait-Job

#Receive the job
$jobInfo = Receive-Job -Job $job

这对我来说很有效。

无需远程登录即可运行SQL查询。您可以使用下面的函数并根据需要传递变量。无论哪个帐户具有访问权限,都可以作为凭据传递。(适用于Windows和SQL身份验证)


希望有帮助。

我会试试看,它的一个变种听起来很有希望。谢谢。它不会立即运行,但希望它能让您有一个开始。很抱歉,我忽略了提到脚本作为服务运行,因此没有GUI可供使用。实际上,说服务运行脚本(Nagios客户端,NRPE/NSClient)更为“正确”,我想我可以将sanur与runas一起使用。@Aaron Wurthmann我最终构建了一个自定义runas,它只允许CreateProcessWithLogonW使用登录\网络凭据\而不提示输入凭据。但我们从未在生产中使用过它,因为存储密码的安全考虑。是的,我听说了。在本例中,我用于监视的帐户权限非常小,运行脚本的服务器位于内部网络和域上,而不是生产网络和域上。也许有一天我会回到这个问题上来,从.NET的角度来解决这个问题。确实您已经检查了这个问题,但是用户(mydomain\myusername)确实可以访问数据库?您可以授予计算机访问远程SQL Server的权限。无法通过GUI进行设置,但在远程计算机上,使用WINDOWS中的创建登录名[myDomain\myMachine$]添加了myDomain\myMachine$;然后从脚本中删除所有用户名、密码等内容。@Matt当然可以,因为从Shell运行时,帐户可以工作。但是,嘿,有时我们忽略的小事情又回来咬我们了。@Chad,那会很酷的。除了系统与SQL server尚不在同一域中。这不会在今天发生。我将保留此尝试。您确定您的PowerShell实例具有正确的远程权限吗?容易被忽视。在过去,它一直在折磨着我……在一个我已经可以访问的系统上工作。在不同的系统上,它只是产生了一个错误
[localhost]启动后台进程时出错。报告的错误:登录失败:未知用户名或错误密码。
Ok。这对我来说很有效,但我无法让它在scriptblock中使用变量作为参数。更新为$using:并且有效。如下所示:$query='select@@version'Start Job{importsystemmodules;调用Sqlcmd-query$using:query-ServerInstance LOCALHOST}-Credential$creds | Get Job | Wait Job这并不能完成op所寻找的任务。在此代码中提供用户名和密码时,它使用SQL身份验证。“集成”身份验证只传递用户在运行此代码时的登录身份。但是,如果您不想在PS环境中安装SQL Powershell工具并添加依赖项,那么这是一段有用的代码,因此我将在另一个项目中使用它!:)@马特。OP在他的问题中提到“如果这意味着在数据库中创建一个本地帐户,它也可以回答我的简单查询”,这意味着他可以创建sql用户ID。这就是答案
#Submit the job with creds
$job = Start-Job {importsystemmodules; Invoke-Sqlcmd -Query 'select @@version'  -ServerInstance LOCALHOST} -Credential $creds | Get-Job | Wait-Job

#Receive the job
$jobInfo = Receive-Job -Job $job
        $SQLInstance = "Instance Name"
        $Database = "Database"
        $ID = "User ID" 
        $Password = "Password"



     function Invoke-Sqlcommand 
        { 
            [CmdletBinding()] 
            param( 
            [Parameter(Position=0, Mandatory=$true)] [string]$ServerInstance, 
            [Parameter(Position=1, Mandatory=$false)] [string]$Database, 
            [Parameter(Position=2, Mandatory=$false)] [string]$Query, 
            [Parameter(Position=3, Mandatory=$false)] [string]$Username, 
            [Parameter(Position=4, Mandatory=$false)] [string]$Password, 
            [Parameter(Position=5, Mandatory=$false)] [Int32]$QueryTimeout=600, 
            [Parameter(Position=6, Mandatory=$false)] [Int32]$ConnectionTimeout=15, 
            [Parameter(Position=7, Mandatory=$false)] [ValidateScript({test-path $_})] [string]$InputFile, 
            [Parameter(Position=8, Mandatory=$false)] [ValidateSet("DataSet", "DataTable", "DataRow")] [string]$As="DataRow" 
            ) 

            if ($InputFile) 
            { 
                $filePath = $(resolve-path $InputFile).path 
                $Query =  [System.IO.File]::ReadAllText("$filePath") 
            } 

            $conn=new-object System.Data.SqlClient.SQLConnection 

            if ($Username) 
            { $ConnectionString = "Server={0};Database={1};User ID={2};Password={3};Trusted_Connection=False;Connect Timeout={4}" -f $ServerInstance,$Database,$Username,$Password,$ConnectionTimeout } 
            else 
            { $ConnectionString = "Server={0};Database={1};Integrated Security=True;Connect Timeout={2}" -f $ServerInstance,$Database,$ConnectionTimeout } 

            $conn.ConnectionString=$ConnectionString 

            #Following EventHandler is used for PRINT and RAISERROR T-SQL statements. Executed when -Verbose parameter specified by caller 
            if ($PSBoundParameters.Verbose) 
            { 
                $conn.FireInfoMessageEventOnUserErrors=$true 
                $handler = [System.Data.SqlClient.SqlInfoMessageEventHandler] {Write-Verbose "$($_)"} 
                $conn.add_InfoMessage($handler) 
            } 

            $conn.Open() 
            $cmd=new-object system.Data.SqlClient.SqlCommand($Query,$conn) 
            $cmd.CommandTimeout=$QueryTimeout 
            $ds=New-Object system.Data.DataSet 
            $da=New-Object system.Data.SqlClient.SqlDataAdapter($cmd) 
            [void]$da.fill($ds) 
            $conn.Close() 
            switch ($As) 
            { 
                'DataSet'   { Write-Output ($ds) } 
                'DataTable' { Write-Output ($ds.Tables) } 
                'DataRow'   { Write-Output ($ds.Tables[0]) } 
            } 

        } 

Invoke-Sqlcommand -ServerInstance $SQLInstance -Database $Database -Query "Query Goes here" -Username $ID -Password $Password