Renci SSH.NET - script hangs indefinitly - powershell

Here is the code - hangs after last command:
$DllPath = "Q:\A_FILES\PowerSHell\SSH_NET_for_powershell\Renci.SshNet_Binary\Renci.SshNet.dll"
[void][reflection.assembly]::LoadFrom( (Resolve-Path $DllPath) )
$SshClient = New-Object Renci.SshNet.SshClient('199.12.13.44', 22, 'userid', 'password')
$SshClient.Connect()
Get-Process | Out-File -FilePath D:\Powershell\SAN_NAP01_TEST.txt -Encoding ASCII
$SshCommand = $SshClient.RunCommand('statistics show-periodic')
The command issued via SSH above - STATISTICS show-periodic - when manually issued to an SSH session into the Netapp Storage SAN - starts displaying data and runs forever - you are not given a prompt again - you must manually issue CTRL-C to exit this command and then you receive the CLI prompt in the SSH session to issue another desired command. I assume this is why the powerscript hangs - because the command does not go back to a prompt - without a CTRL-C issued.
I would like to issue $SshCommand = $SshClient.RunCommand('CTRL-C') following the above last command (after a desired sleep time) - but the powershell script does not get control back.
Wondering if their is any way to get control back after the statistics... command and then be able to issue the CTRL-C command into the SSH session after a desired time interval.

are you connecting to a Netapp server?
If that's the case you could consider using the -iterations parameter in your command, so your statistics command returns.
$SshCommand = $SshClient.RunCommand('statistics show-periodic -iterations 5')

Related

How to execute ssh connect by script?

I have local Windows 10 and remote Ubuntu server.
I want to automate connection to server and write executable script witch connects by ssh to server and open new terminal from another server.
What it's supposed to look like
I double click on bat
And then script
inits ssh connect
writes password
gives the user a terminal with a ready ssh connection.
That is, it mimics the following
Problems
How to wait ssh password request? All commands executes immediately.
(additional) can I write it in .sh script, run script, execute all in "start" terminal (from which I run .sh script) and then pass ssh control to invoked terminal?
It's best if someone writes a ready-made script
Automatically enter SSH password with script
Answers:
Direct answer - use expects. But sshpass is better. Also RSA-key can be used.
Can`t tell anything.
Can be done without any 3rd party tools like this:
$env:TMPPW=Get-Content -Path 'secure_file.txt' ; $un='MyUserName'
$j=Start-Job -ScriptBlock{Start-Sleep -Seconds 1
(New-Object -ComObject wscript.shell).SendKeys("$env:TMPPW{ENTER}")}
& ssh.exe -q -4 -l $un 127.0.0.1 'whoami'
$env:TMPPW=([guid]::NewGuid()).Guid ; $env:TMPPW=$null

Scheduled script that pings server with log file

I am new to powershell but I am trying to learn.
Right now, I need to set a scheduled script to run every 10 minutes and ping on of our servers while saving that information to a log file. I have a script that does this but the issue I am facing is with the log.txt
Every time the script runs it overwrites the log file.
My questions is: how can I tell powershell to update the log file and not overwrite the contents of it when it is run?
My script: Ping.exe <HOSTNAME> | ForEach {"{0} - {1}" -f (Get-Date),$_} > D:\ping.txt
I believe > D:\ping.txt is telling Powershell to overwrite your log file. Have you tried >> D:\ping.txt instead?
EDIT: For future reference, Microsoft can explain this better than I can:
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_redirection?view=powershell-7.1#powershell-redirection-operators

How to get command line application output to a variable in background in PowerShell 5.1?

SOLVED
Thanks to #mklement0 's advice, I tried to get an exit code from rstcli64.exe:
from cmd I get 0
from zabbix-agent I get 3 (INVALID_DEVICE, according to manual)
So, the culprit is not PowerShell, but rstcli64.exe exiting with an error in conditions: Windows Server 2019 and ran from PS script ran by zabbix-agent. I've updated rstcli from Intel's website and new version has the same syntax and works perfectly in new conditions.
ORIGINAL POST
I have Windows Zabbix Agent, which runs a PowerShell script, which runs a command line application, parses output and gives 1 or 0.
$states = C:\util\rstcli64.exe --information --volume 2> $null | select-string -Pattern "State:"
$notNormalStates = $states | Select-String -Pattern "Normal" -NotMatch
if ($states.Count -gt 0 -and $notNormalStates.Count -eq 0){
"1"
} Else {
"0"
}
This script worked on Windows Server 2012 R2, but after migration to Windows Server 2019 (with PowerShell 5.1) it began to output only 0.
This is a wave-particle duality situation: if I run this script from command line (User, Administrator, System - the same), it gives 1, because it receives the output from rstcli64.exe; and if zabbix-agent runs this exact script, it gets nothing from rstcli64.exe, thus gives 0.
So I guess the difference is that I run the script from an interactive shell and zabbix-agent runs the script from background.
And the question is: how do I get the output from a command line application in PowerShell 5.1 (Windows Server 2019), when run in background?
MORE INFO
If I just use this:
$states = C:\util\rstcli64.exe --information --volume
$states
exit
It shows a lot of data if I run the script in command line:
--VOLUME INFORMATION--
Name: HDD_MIRROR Raid Level: 1 Size:
1863 GB StripeSize: 64 KB Num Disks: 2 State:
Normal System: True Initialized: True Cache Policy:
R
--DISKS IN VOLUME: HDD_MIRROR --
ID: 0-0-0-0 Type: Disk Disk Type:
SATA Disk State: Normal
But if ran from zabbix - there's nothing:
6304:20201014:170446.686 EXECUTE_STR()
command:'%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe
-nologo -ExecutionPolicy ByPass -File "C:\util\intel_rst_raid.ps1"' len:0 cmd_result:'' 6304:20201014:170446.686 Sending back []
8208:20201014:170446.687 End of collect_perfstat()
MORE INFO
It just does it with rstcli64.exe. With few other command line tools I get the same output when manually running script in cmd and triggering it from zabbix-agent. Again, only in PowerShell 5.1 in Windows Server 2019, so...
This sounds like an issue with redirection and streams. The information stream was introduced in 5.0 and Windows 2012R2 comes with 4.0. Which might explain the different behavior.
About_Redirection
I'd play around with the redirection operators to see if you can get what you need piped to Select-String. It might look something like:
$states = C:\util\rstcli64.exe --information --volume *>&1 | select-string -Pattern "State:"
This takes all streams and redirects them to the success stream, this way everything goes down the pipeline to Select-string.
I'd also advise you can make your RegEx a little more precise. Maybe "^State:" so you are capturing lines that start with "State:". Though I don't know if there may be preceding white space.

Powershell Output inconsistencies

I have a powershell script that works just fine when I open powershell manually and run the script. It produces an output like such:
10.52.30.131 BALL-AIRKYYCP0 Not installed Ping successful Windows
10.52.30.133 BALL-4FNRAMLOD Not installed Ping successful Windows
10.52.30.134 BALL-5UU20W8E2 Not installed Ping successful Windows
If I right click the script file and then click run in powershell the script runs fine and does everything it needs to do but the output returned is different, see below:
10.52.30.131 BALL-AIRKYYCP0 Not installed Ping successful Wind
ows
10.52.30.133 BALL-4FNRAMLOD Not installed Ping successful Wind
ows
10.52.30.134 BALL-5UU20W8E2 Not installed Ping successful Wind
ows
For some reason running it by right click 'Run in Powershell' causes the output to be messy and cells to be cut off and finished on the next row. This is a small sample
Any ideas why the output would be different when running the script this way?
It appears the console windows were different sizes depending how you were launching it.
You can set your console window size from within your Powershell script if you want, using get-host.
For example, this will set the width of the console to 120:
$ws = (get-host).UI.RawUI.WindowSize
$ws.Width = 120
(get-host).UI.RawUI.WindowSize = $ws
Got this technique from here: http://technet.microsoft.com/en-ca/library/ee156814.aspx

Sleep command in batch file?

When I'm writing a batch file to run automatically, how do I write it so that when the batch file is run, it can pause for a couple seconds in between commands?
Context:
psexec \\server -u user -p pass cmd
[there needs to be a pause here for psexec to establish a connection]
dir /s >output.txt \\server\shared
*Note: the reason I run the dir command server-side using psexec and not locally is because it's much faster to run dir on a local machine than remotely, and time is of the essence.
When I'm doing this by hand it's obviously easy, I just wait. But running a batch file makes it run all commands at near instant speeds next to each other, regardless of the completion status of the last command. How do I put in a pause?
On Windows Vista / Windows 7 you can use the timeout command:
timeout /T [delay in seconds] /NOBREAK > NUL
On previous versions of Windows, you can use the ping command (the ping command has 1000 ms of delay between each iteration):
ping -n [delay in seconds + 1] 127.0.0.1 > NUL
Some versions of Windows (like Windows Server 2003) has the sleep.exe executable:
sleep [delay in seconds]
Note: Windows Resource kit for 2003 contains sleep.exe command.
If you don't know the Windows version, simply use the ping hack since it'll be available.
There is timeout command in more recent version of Windows:
timeout /T 10
Windows Resource kit for 2003 will install on Windows XP. It contains SLEEP.EXE which can be used from a command batch file.
download is here http://www.microsoft.com/download/en/details.aspx?id=17657
I think the information here: http://malektips.com/xp_dos_0002.html would explain it better than I.
There's still the case of error handling though (what if the remote machine isn't up?). cmd.exe is quite useless for doing any remote activities for the most part, using powershell would enable so much more.
EDIT::
In fact, you can execute a program stored locally with psexec (it gets copied across and executed locally server-side) - would using that be a more viable alternative?
Without knowing what commands you're intending to run it's hard to take it much further.
EDIT(2)::
If it's just the one command you're running, simply store it in a dedicated file, like 'remote_dir_listing.cmd', and then use psexec with:
psexec \\server -u <user> -p <pass> -c -f remote_dir_listing.cmd
This will force a copy of the local file to the remote side each time you execute it (in case you want to expand it). In this way, you bypass the need for a pause at all - only when psexec has got the pipes open will it run, and once it completes, it closes itself silently.