AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 206678
Accepted
TheGameiswar
TheGameiswar
Asked: 2018-05-15 07:07:24 +0800 CST2018-05-15 07:07:24 +0800 CST 2018-05-15 07:07:24 +0800 CST

Invoke SQLCMD não funciona quando usado com xp_cmdshell

  • 772

Estou tentando obter o relatório de espaço em disco de vários servidores e inseri-los na tabela sql ..

abaixo está uma amostra do que estou tentando fazer, os nomes dos servidores serão preenchidos a partir de uma tabela e passados ​​como uma lista separada por vírgulas. Mesmo passando um servidor também tem o mesmo resultado

set @ps = 'powershell.exe -noexit -c "

$computers=Get-WmiObject -Class Win32_Volume '+@servernames+'
foreach($computer in $computers) 
{ 
$pscomputername=$computer.pscomputername 
$name=$computer.name 
$capacity=$computer.capacity 
$freespace=$computer.freespace 
$Label=$computer.Label 

$insertquery=" 
INSERT INTO [dbo].[temp_disksdata] 
           (
           [servername] ,
           [DiskName] ,
           [Capacity(GB)] ,
           [FreeSpace(GB)],
           [label]
           )
     VALUES 
           (''$pscomputername'' ,
           ''$name'' ,
           ''$capacity'',
           ''$freespace'',
           ''$Label''
           ) 
GO
" 

Invoke-SQLcmd  -query $insertquery -ServerInstance ''someserver'' -Database dbname

}

"';

Agora eu tento passar a variável para xp_cmdshell como abaixo

execute xp_cmdshell @ps;

Quando invocado no SSMS, acima retorna nulo, mas funciona no powershell.

Alguma idéia por quê?

Abaixo estão algumas coisas que eu tentei

1.A mesma conta (admin) é usada tanto no shell quanto no ssms
2.tentei várias coisas como importar módulos
3.XP_CMDshell funciona, mas isso retorna nulo apenas para esta consulta
4.Eu tentei adicionar -nowait, mas isso não funciona ajude também

Eu tenho tentado fazer isso por mais de um dia, mas isso não funciona .. Eu tenho que usar xp_cmdshell porque escrever ac # app não é permitido. O arquivo Bat não ajuda porque os nomes dos servidores são passados ​​como uma vírgula lista separada.

Estou modificando o código e me disseram para não reescrever quando solicitado

Por favor, deixe-me saber se você precisar de mais informações

Repro:
Abaixo está todo o comando da impressão, se você remover o powershell.exe e -c , abaixo será executado no powershell ..

powershell.exe  -c "

$computers=Get-WmiObject -Class Win32_Volume 'servername'
foreach($computer in $computers) 
{ 
$pscomputername=$computer.pscomputername 
$name=$computer.name 
$capacity=$computer.capacity 
$freespace=$computer.freespace 
$Label=$computer.Label 

$insertquery=" 
INSERT INTO [dbo].[temp_disksdata] 
           (
           [servername] ,
           [DiskName] ,
           [Capacity(GB)] ,
           [FreeSpace(GB)],
           [label]
           )
     VALUES 
           ('$pscomputername' ,
           '$name' ,
           '$capacity',
           '$freespace',
           '$Label'
           ) 

" 

Invoke-SQLcmd  -query $insertquery -ServerInstance 'servername' -Database dbname 

}

"
sql-server sql-server-2012
  • 3 3 respostas
  • 2245 Views

3 respostas

  • Voted
  1. Best Answer
    Solomon Rutzky
    2018-05-15T10:16:02+08:002018-05-15T10:16:02+08:00

    Há vários problemas aqui:

    O principal problema é que o shell CMD executa cada linha à medida que ela chega por meio de um retorno; ele não espera por um indicador de "fim de comando", como ;, nem tenta descobrir por meio de análise (como o SQL faz quando um lote é enviado), pois não há como saber se umreturn termina um "comando" ou não. Normalmente você pode usar ^para continuação de linha, mas isso não parece funcionar dentro de um parâmetro de entrada (pelo menos não um com aspas não fechadas).

    Então, para isso, você precisa reduzir tudo a uma única linha. Isso é bastante simples, pois você pode substituir Carriage Return (caractere 13) por uma string vazia e Line Feed/Newline (caractere 10) por um espaço. Mas isso por si só não funcionará, pois as instruções do PowerShell precisam ser separadas por uma nova linha ou um ponto e vírgula. Atualmente, as novas linhas estão sendo usadas, mas se as substituirmos por espaços, serão necessários pontos e vírgulas.

    1. Portanto, a Etapa 1 é anexar um ponto e vírgula a cada comando real do PowerShell. Isso provavelmente é uma boa forma em geral, da mesma forma que com o T-SQL.

    2. A etapa 2 seria fazer as duas REPLACEchamadas na @psvariável para transformá-la em um script de linha única.

    3. Você inseriu aspas duplas, usadas para criar a INSERTinstrução. Esses precisam ser escapados com uma barra invertida ( \).

    4. Get-WmiObjectnão parece funcionar como você está tentando usá-lo aqui. Eu tive que adicionar -ComputerNamepara passar no nome de um sistema. Se eu deixar em branco, ele retornou as informações do sistema local, mas se você quiser retornar informações para servidores remotos, provavelmente precisará usar o -ComputerNameswitch e passar um servidor por vez. Isso provavelmente exigirá um loop externo adicional para lidar com vários nomes de servidor (e seria lá que você passaria @ServerNamespara ser dividido para iterar na lista).

    5. "capacity" e "freespace" são realmente armazenados como strings no banco de dados? Caso contrário, você pode querer remover as aspas simples em torno desses "valores" na INSERTinstrução.

    O seguinte pelo menos é executado. Você pode depurar a partir daí. Eu estava recebendo erros por não encontrar o módulo "Invoke-SQLcmd" ou algo assim.

    DECLARE @ServerNames NVARCHAR(4000);
    SET @ServerNames = N'ALBRIGHT';
    
    DECLARE @ps NVARCHAR(4000);
    SET @ps = N'powershell.exe -noexit -c "
    
    $computers=Get-WmiObject -Class Win32_Volume -ComputerName ' + @ServerNames + N';
    foreach($computer in $computers) 
    { 
    $pscomputername=$computer.pscomputername;
    $name=$computer.name;
    $capacity=$computer.capacity;
    $freespace=$computer.freespace;
    $Label=$computer.Label;
    
    $insertquery=\";
    INSERT INTO [dbo].[temp_disksdata] 
               (
               [servername] ,
               [DiskName] ,
               [Capacity(GB)] ,
               [FreeSpace(GB)],
               [label]
               )
         VALUES 
               (''$pscomputername'' ,
               ''$name'' ,
               ''$capacity'',
               ''$freespace'',
               ''$Label''
               ) 
    GO
    \";
    
    Invoke-SQLcmd  -query $insertquery -ServerInstance ''someserver'' -Database dbname;
    
    }
    
    "';
    
    SET @ps = REPLACE(REPLACE(@ps, NCHAR(13), N''), NCHAR(10), N' ')
    PRINT @ps;
    
    
    EXEC xp_cmdshell @ps;
    
    • 5
  2. Peter Vandivier
    2018-05-15T08:55:48+08:002018-05-15T08:55:48+08:00

    O problema pode ser os feeds de linha no comando que você está tentando executar. Considere a diferença entre os seguintes casos.

    -- case 1
    execute xp_cmdshell N'powershell.exe -noexit -c "echo hello"';
    
    -- case 2
    execute xp_cmdshell N'powershell.exe -noexit -c "
    echo hello
    "';
    

    powershellPara executar scripts de várias linhas de xp_cmdshell, tente salvar o comando inteiro em um arquivo e, em seguida, fazer referência ao arquivo em uma chamada de linha única. Por exemplo, dado este texto...

    $srvs =@(
        'localhost',
        '127.0.0.1',
        '(local)'
    )
    
    $srvs | % {
       (Invoke-SqlCmd -ServerInstance "$_" -Query 'select @@servername srv').srv
    }
    

    ...salvo como arquivoC:\temp\foo.ps1 , o seguinte deve ser bem-sucedido...

    execute xp_cmdshell N'powershell.exe c:\temp\foo.ps1';
    

    Existem várias maneiras de escrever texto arbitrário no sistema de arquivos usando T-SQL, mas a jogada mais inteligente provavelmente terá um arquivo estático e obterá o@servernames de outra chamada para o banco de dados - por exemplo, alterando isso ...

    $computers = Get-WmiObject -Class Win32_Volume '+@servernames+'
    

    ...em um script sql para isso...

    $conn = @{
        ServerInstance = $server
        Database       = $database
    }
    $servernames = (Invoke-SqlCmd @conn -query "select Name from server_list").Name -join ','
    $computers = Get-WmiObject -Class Win32_Volume '$servernames' 
    

    ... em um script powershell.

    • 4
  3. Konstantin Taranov
    2018-05-15T06:54:33+08:002018-05-15T06:54:33+08:00

    Altamente recomendado para usar dbatools incríveis Powershell.

    Basta instalar este módulo:

    Install-Module dbatools
    

    Em seguida, use a função Get-DbaDatabaseSpace :

    # Get Db Free Space AND write it to table
    Get-DbaDatabaseSpace -SqlInstance $instance | Out-GridView
    Get-DbaDatabaseSpace -SqlInstance $instance -IncludeSystemDB | Out-DbaDataTable | Write-DbaDataTable -SqlInstance $instance -Database tempdb -Table DiskSpaceExample -AutoCreateTable
    Invoke-Sqlcmd2 -ServerInstance $instance -Database tempdb -Query 'SELECT * FROM dbo.DiskSpaceExample' | Out-GridView
    

    Ou para instâncias de multiplicação:

    $allservers = "localhost\sql2016", "localhost\sql2017"
    $allservers | Get-DbaDatabaseSpace -IncludeSystemDB | Out-DbaDataTable | Write-DbaDataTable -SqlInstance $instance -Database tempdb -Table DiskSpaceExample -AutoCreateTable
    

    Além disso, você pode usar o modelo PowerBI muito útil para esta tarefa: https://sqljana.wordpress.com/2018/04/30/sql-server-quick-space-file-layout-analysis-with-powershell-and-powerbi/

    • 3

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve