Precisa de um script / lote / programa que execute um comando que não será morto quando o pai for morto

6

O cenário

Eu uso o Zabbix para monitorar meus servidores e, recentemente, eu queria adicionar mais algumas métricas para as do Windows. Por motivos de segurança, usei o recurso Parâmetro do usuário do Zabbix, mas ele limita a execução de comandos externos para cerca de 3 segundos. Depois disso, o comando é morto à força.

Eu quero executar alguns comandos de longo prazo, então usei o truque do fórum do Zabbix: execute o comando em segundo plano, escreva os resultados em um arquivo e use o Zabbix para coletá-los.

Isto é bastante fácil em * nix graças ao "&" operador, mas não há tal suporte no shell do Windows. Para piorar as coisas, quando o Zabbix mata forçadamente o cmd.exe usado para avaliar os comandos, todos os processos secundários morrem, incluindo as tarefas de segundo plano inacabadas.

Assim, eu preciso de algo que possa cortar todos os vínculos com seus filhos, para que eles não sejam afetados na matança em cascata.

O que eu tentei

  • start e start /B - Eles não fazem nada porque a criança sempre morre com o pai
  • WScript.Shell.Run como em invis.vbs do StackOverflow - às vezes funciona. Se o processo wscript for forçado a morrer em vez de desistir sozinho, as crianças também morrerão.
  • hstart - resultados semelhantes a invis.vbs
  • At command - Isso requer que você defina um tempo de absolvição para a tarefa ser executada, em oposição a um deslocamento, portanto, o código seria bastante confuso devido ao recurso de script de shell limitado do Windows.
  • (Editar) PsExec.exe da suíte SysInternals - Ele usa um serviço para iniciar o comando, por isso não é afetado pelo kill; no entanto, imprime algumas informações de banner e log para StdErr e não há nenhuma opção para desabilitar isso. Quando eu uso o 2>NUL para redirecioná-los, o Zabbix relata um erro.

Depois de tentar o acima em combinações diferentes, notei que se eu chamar hstart de invis.vbs , o comando iniciado pelo primeiro será deixado como um processo sem pai quando invis.vbs for eliminado.

No entanto, como preciso redirecionar a saída, o comando que desejo executar está sempre na forma de cmd.exe /c ""command" "args"" >log . O vbs também remove todas as aspas, então eu tenho que codificar o comando com seqüências de escape auto-definidas. O resultado final envolve cerca de cinco níveis de escape / cotação, o que é quase impossível de manter.

Alguém conhece alguma solução melhor?

Alguns requisitos

  • Qualquer binário bat / vbs / js / Win32 é aceitável
  • Melhor não exigir vários níveis de escape
  • Não .Net (incluindo PowerShell) porque não está instalado
por billc.cn 25.01.2012 / 04:28

7 respostas

1
  1. Separe o que seu script longo deveria estar fazendo em seu próprio script.

  2. Usando o NSSM , transforme esse script em um serviço; defina sua ação Sair para Ignorar.

  3. Crie um pequeno arquivo de lote para o Zabbix iniciar, seu conteúdo é apenas uma linha curta para iniciar o serviço criado na etapa acima.

No passo 2, alternativamente, faça o script terminar com o código de saída 0 e defina a ação AppExit \ 0 como Exit, que instruirá o Service Manager do Windows a marcar o serviço como interrompido.

    
por 13.01.2014 / 19:49
1

Você já tentou BeyondExec ? É muito parecido com o psexec, então eu não sei se o mesmo problema que você tem com o psexec se aplica, mas vale a pena tentar.

    
por 25.01.2012 / 23:13
0

Estou usando

inicie "mybatch.bat"

de outro arquivo de lote (por exemplo, "host.bat") e funciona bem. O arquivo host.bat pode ser parado e o outro arquivo é executado corretamente.

    
por 25.01.2012 / 18:35
0

Sugestão 1:

Use PSEXEC, mas tente escapar do caractere de redirecionamento. Eu não estou familiarizado com o Zabbix, então não tenho certeza se isso ajudará.

psexec.exe ...args... 2^>nul

Sugestão 2:

Use um arquivo em lotes contendo comandos schtasks.

--- schedzabbixscript.cmd ---

@echo off
schtasks /create /ru "NT AUTHORITY\SYSTEM" /sc once /tn zabbixtemp /tr c:\path\zabbixscript.cmd /st 23:23:59 /sd 12/31/2999
schtasks /run /tn zabbixtemp

--- zabbixscript.cmd ---

@echo off
...command...
...command...
...command...
schtasks /delete zabbixtemp /f

Se isso funcionar para você em um servidor, para fazer isso em vários servidores sem precisar fazer login em cada um deles, você pode alterar a conta usada para a tarefa agendada para uma conta de rede e armazenar seu zabbixscript. cmd em um local central e apenas editá-lo quando você precisar mudar alguma coisa.

    
por 12.04.2012 / 15:53
0

Você já considerou que não precisa do Zabbix para realmente monitorar os sistemas? Em vez disso, você pode monitorar um arquivo gravado por um serviço no sistema. IOW, escreva um serviço que faz tudo que você precisa e grava os resultados finais em um arquivo (XML, JSON, CSV, o formato não importa, contanto que você possa lê-lo posteriormente no Zabbix). Então, seu aplicativo de monitoramento precisaria apenas analisar esse arquivo, o que deve acontecer quase instantaneamente.

    
por 26.08.2013 / 19:46
0

Se eu estivesse monitorando servidores, provavelmente eu iria rolar meus próprios scripts batch ou bash para verificar o status do servidor e agendar esses testes usando um servidor Jenkins.

    
por 12.09.2013 / 23:46
0

O Windows Script Host é a solução correta. Se estiver apenas iniciando o trabalho em lote, ele nunca terá tempo para ser eliminado. Tudo que você precisa é:

Set quickShell = WScript.CreateObject("WScript.Shell")
myCommand = "mybatchfile.bat ""first argument"" ""second argument"" > logfile.log"
quickShell.Run myCommand, 0

Salve isso como wrapper.vbs e execute-o. Ele iniciará o lote e sairá imediatamente, deixando o arquivo de lote em execução em segundo plano.

    
por 18.09.2013 / 11:43