6

The scenario

I use Zabbix to monitor my servers and recently I wanted to add some more metrics for the Windows ones. For security reasons, I used Zabbix's User Parameter feature, but it limits the execution of external commands to about 3 seconds. After that, the command is forcibly killed.

I want to run some long run commands, so I used the trick from Zabbix's forum: run the command in the background, write the results to a file and use Zabbix to collect them.

This is rather easy under *nix thanks to the "&" operator, but there is no such support in Windows' shell. To make things worse, when Zabbix kills forcibly kill the cmd.exe it used to evaluate the commands, all child processes die including the unfinished background tasks.

Thus I need something that can sever all the ties with its children so they won't be affected in the cascading kill.

What I've tried

  • start and start /B - They do nothing as the child always die with the parent
  • WScript.Shell.Run as in invis.vbs from StackOverflow - Sometimes work. If the wscript process is forcibly killed as opposed to quitting on its own, the children will die as well.
  • hstart - similar results to invis.vbs
  • At command - This requires you to set an absolution time for the task to run as opposed to an offset, so the code would be quite messy due to the limited shell scripting capability of Windows.
  • (Edit) PsExec.exe from the SysInternals suite - It uses a service to launch the command, so it is not affected by the kill; however, it prints some banner and log info to StdErr and there's no switch to disable this. When I use 2>NUL to redirect them, Zabbix reports an error.

After trying the above in different combinations, I noticed if I call hstart from invis.vbs, the command started by the former will be left alone as a parent-less process when invis.vbs is killed.

However, since I need to redirect the output, the command I want to run is always in the form of cmd.exe /c ""command" "args"" >log. The vbs also removes all the quotes, so I have to encode the command with self-defined escape sequences. The end result involves about five levels of escaping/quoting, which is almost impossible to maintain.

Anyone know any better solutions?

Some requirements

  • Any bat/vbs/js/Win32 binary is acceptable
  • Better not require multiple levels of escaping
  • No .Net (including PowerShell) because it is not installed
2
  • Can't you use a Windows scheduled task to run the program ?
    – adaptr
    Jan 25, 2012 at 17:38
  • See my comments regarding the at command. Using Scheduled Tasks require I define both the schedule and the exact command. As I may need to frequently change the parameters of the metrics (especially during network problems), I would need to log into every server and manually change the tasks. Group policy may take up to 1 hour to deploy, so that's not an option either.
    – billc.cn
    Jan 25, 2012 at 17:46

7 Answers 7

1
  1. Separate whatever your lengthy script is supposed to be doing into its own script.

  2. Using NSSM, make that script into a service; set its Exit action to Ignore.

  3. Create a short batch file for Zabbix to start, its content is only one short line to start the service you created in the above step.

In step 2, alternatively, have the script end with exit code 0, and set the AppExit\0 action to Exit, which will gracefully instruct Windows' Service Manager to mark the service as stopped.

1

Have you tried BeyondExec? It's very very similar to psexec, so I don't know if the same issue you have with psexec would apply, but it's worth a shot.

0

I'm using

start "mybatch.bat"

from within another batch file (e.g. "host.bat") and it works fine. The host.bat file can be stopped and the other file runs fine.

1
  • I just tried this and I realized this is the one of the first things I tried and dismissed. The bat files are indeed not killed, but they bring two other problems: 1) they generate visible windows and 2) the start command will actually cause the parent to wait for the child batch files to finish before it exits. This will certainly make the whole thing exceed the 3-second timeout and cause Zabbix to raise and error and disable this metric.
    – billc.cn
    Jan 25, 2012 at 18:07
0

Suggestion 1:

Use PSEXEC, but try escaping the redirect character. I'm not familiar with Zabbix, so I'm not sure if this will help though.

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

Suggestion 2:

Use a batch file containing schtasks commands.

---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

If this works for you on one server, in order to do this on multiple servers without having to log into each one, you could change the account that is used for the scheduled task to a network account, and store your zabbixscript.cmd in a central location and just edit it when you need to change something.

0

Have you considered that you don't need Zabbix to actually monitor the systems? Instead you can make it monitor a file which is written to by a service on the system. IOW, write a service which does everything you need and writes the end results to a file (XML, JSON, CSV, the format doesn't matter as long as you can read it later from Zabbix). Then your monitoring app would just need to parse out that file which should happen nearly instantaneously.

0

If I were monitoring servers, I would probably roll my own batch or bash scripts to check server status and schedule those check-jobs using a Jenkins server.

0

Windows Script Host is the correct solution. If it's only starting the batch job, it will never have time to be killed. All you need is:

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

Save that as wrapper.vbs and run it. It will start the batch and exit immediately, leaving the batch file running in the background.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .