Inputs.exec with Powershell

I’m having troubles within my telegraf.conf file using the inputs.exec method to call on my powershell script to check the status of DFSR between nodes.

I have a simple powershell script that when ran on its own returns the results using write-host

PS C:\Program Files\Telegraf> C:\dfsr.ps1
DFSRBacklog,host=DFS1, DfsrBacklogCount=0i

My telegraf.conf file

[[inputs.exec]]

commands = [“powershell C:/dfsr.ps1”]
timeout = “5s”
name_suffix = “_mycollector”
data_format = “influx”

When I try and test my config file out, there are no results

PS C:\Program Files\Telegraf> .\telegraf.exe --config telegraf.conf --test
PS C:\Program Files\Telegraf>

Here is my full powershell script

$command = Get-DfsrBacklog -SourceComputer DFS1 -DestinationComputerName DFS2 | select FileName,FullpathName | measure-object | select Count

Write-Output “DFSRBacklog,host=$(env:ComputerName), DfsrBacklogCount=($command.Count)i”

What am I missing here? I’ve tried different quotations on the powershell file path, forward and back slashes, testing the powershell script on its own

The command is executed by telegraf using cmd, so try to run the script directly from the cmd to simulate what telegraf does.

You can also try the “-File” or “-Command” arguments after powershell, there is some difference between the two.

in the cmd try to run:
1. powershell C:\dfsr.ps1
2. powershell -Command C:\dfsr.ps1
3. powershell -File C:\dfsr.ps1

the final telegraf conf may look like this one
  ## Commands array
  commands = [
    'powershell -Command C:\dfsr.ps1'
  ]

Be aware that error thrown in the PowerShell script won’t be correctly received by the cmd and telegraf unless you use exit codes, I opened an issue (now closed) on this topic, in the reply you may find a solution/explanation.

Thanks for the recommendations

in cmd I tried the 3 commands you recommended, and I get results from all 3 versions of the syntax

C:\Windows\system32>powershell -Command C:\dfsr.ps1
DFSRBacklog,host=DFS1, DfsrBacklogCount=1i

C:\Windows\system32>powershell -Command C:\dfsr.ps1
DFSRBacklog,host=DFS1, DfsrBacklogCount=0i

I modified my powershell script to have exit 1 at the end of the script so it now reads

$command = Get-DfsrBacklog -SourceComputer DFS1 -DestinationComputerName DFS2 | select FileName,FullpathName | measure-object | select Count

#send data to telegraf
Write-host “DFSRBacklog,host=$(env:ComputerName), DfsrBacklogCount=($command.Count)i”
exit 1

However when I still try and test out the dfs conf file, it doesn’t return any results

PS C:\Program Files\Telegraf> .\telegraf.exe --config dfsr-telegraf.conf --test
PS C:\Program Files\Telegraf>

Here’s the dfsr-telegraf.conf config

[[inputs.exec]]
commands = [‘powershell -Command C:\dfsr.ps1’]

timeout = “5s”

name_suffix = “_mycollector”

data_format = “influx”

That’s strange.

Are you running the tests (using cmd) on the same machine and with the same user as telegraf? If not, I recommend you to do so.

Also you don’t need to “force” an exit code, especially since a fixed one will show the execution as successful/failed even if it’s not true and makes debugging harder.

Head scratcher for sure.

I’m running the tests on the server 2019 where telegraf already runs and collects Cpu/memory/server metrics. Telegraf is running as the Local System service account. I can manually test my other .conf files just fine by using this command and see that data in influx

.\telegraf.exe --config telegraf.conf --test

When I test the dfsr-telegraf.conf file with the same command I don’t get any results

I don’t know what’s wrong, but just to be sure, try to run a config that returns some fixed strings.

  commands = [
   'powershell -Command Write-Host TestCommand`,host=DFS1 DfsrBacklogCount=0i'
  ,'powershell -File C:\Test.ps1'
  ]

Where "C:\dfsr.ps1" does simply this:
Write-Host TestFile`,host=DFS1 DfsrBacklogCount=0i

Let me know if you see both points in the output.

Another issue might be the timeout, how much does the command takes when you run it by hand?

EDIT:
When using Write-Host the commas must be escaped using backtick(`), otherwise powershell and cmd won’t print them out

Here is the updated telegraf.conf

only modifications from what you suggested is where the comma is between powershell commands, and running powershell -File C:\dfsr.ps1 from test.ps1

[[inputs.exec]]
  ## Commands array
  commands = [
   'powershell -Command Write-Host TestCommand,host=DFS1, DfsrBacklogCount=0i',
   'powershell -File C:\dfsr.ps1'
  ]
  ## Timeout for each command to complete.
  timeout = "20s"

  ## measurement name suffix (for separating different commands)
  name_suffix = "_mycollector"

  ## Data format to consume.
  ## Each data format has its own unique set of configuration options, read
  ## more about them here:
  ## https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_INPUT.md
  data_format = "influx"

Here is the updated powershell dfsr.ps1 per the recommendation of just a string

Write-Host TestFile,host=DFS1, DfsrBacklogCount=0i

Running the powershell script takes less than a second, but I added a 20s timeout just in case

Same results from testing the config

PS C:\Program Files\Telegraf> .\telegraf.exe --config dfsr-telegraf.conf --test
PS C:\Program Files\Telegraf>
PS C:\Program Files\Telegraf> C:\dfsr.ps1
TestFile host=DFS1 DfsrBacklogCount=0i
PS C:\Program Files\Telegraf>

My last idea is related to the “Powershell Execution Policy” settings.
Have a look at it and if it’s too restrictive and change it more generous level (if possible of course), otherwise you can set it before executing the command

In my previous answer there is a mistake, today I got a similar issue while trying some test configurations.

Looks like that “Write-Host” ignores characters like commas and adds spaces when using an expression inside a string.
I’ve never noticed this before because I use the powershell module “PowerShell-Influx” to manage formatting. and looks like that objects are not affected by this problem
ie:

Write-Host GatewayInput,Tag1=Testing Value=(Get-Random -Maximum 100)
#result
GatewayInput Tag1=Testing Value= 0

As you can see the commas are missing, and also there is a space before the field value.

passing through cmd also causes more complications, even if powershell shows the commas (in some cases), the cmd will remove them.
The solution I’ve found so far is to escape the commas using the backtick (`).

Write-Host GatewayInput`,Source=Gatherer_1 Value=10
# which will also produce the correct result if used in cmd
powershell -Command Write-Host GatewayInput`,Source=Gatherer_1 Value=10

In general, if you don’t see any output string that means that what you write is not a valid LineProtocol syntax.

If you put this in the config and test the configuration you should see the output

[[inputs.exec]]

  commands = [
    'powershell -Command Write-Host GatewayInput`,Source=Gatherer_1 Value=10'
  ]

Yes this is absolutely the problem and I’m super close to being done. I’m just having issues passing in the powershell variable and getting its results

dfsr-telegraf.conf

[[inputs.exec]]

    commands = [
    'powershell "C:\dfsr.ps1"'
  ]
  timeout = "10s"
  data_format = "influx"

C:\dfsr.ps1

$command = (Get-DfsrBacklog -SourceComputer DFS1.ec.city -DestinationComputerName DFS2.ec.city | select FileName,FullpathName | measure-object | select Count)
$command1 = $command.count
Write-Host DFSRBacklog`,host=$env:COMPUTERNAME, DfsrBacklogCount=$command1

When I test out the telegraf conf

PS C:\Program Files\Telegraf> .\telegraf.exe --config ‘C:\Program Files\Telegraf\telegraf.d\dfsr-telegraf.conf’ --test
DFSRBacklog,host=DFS1 DfsrBacklogCount=0 1579891406000000000
PS C:\Program Files\Telegraf>

However when I run the dfsr.ps1 manually I can see there are 3 items still replicating, when the telegraf.conf shows a count of 0

PS C:\Windows\system32> C:\dfsr.ps1
DFSRBacklog,host=DFS1 DfsrBacklogCount=3

Any thoughts on how I can successfully write DfsrBacklogCount=$command1 in my write-host line?

I don’t know why telegraf returns a count of 0.
To debug this you can try to add another command in the script to append its result to a file, this will allow you to see which ps objects Get-DfsrBacklog returns to telegraf. (before serializing them in influx line protocol.

$command = Get-DfsrBacklog {etc..}
Add-Content -Path .\YourFile.txt -Value ($command | Out-String)
{etc...}

You can also let your telegraf session run for a bit and see what it gets. (simply using PowerShell, without using the --test param), if you don’t want to write to the DB write to a file using the file output

I still see a potential error, an extra comma after the tags. It works because that comma is not escaped and gets ignored. (have a look at the line protocol)

$command = Get-DfsrBacklog {etc..}
Write-Host DFSRBacklog`,host=$env:COMPUTERNAME DfsrBacklogCount=$command.count