writing ping results from Paramiko stdout into a txt file - python-2.7

I have a method in which I can connect to a host and ping it. I can see the ping results on the screen, but cannot write them into a file. The file is always empty. Can anyone help me in this regard?
def Check(self,fname):
client = SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.load_system_host_keys()
client.connect(self.ip,22,self.username,self.password)
ping_command = 'ping -n -c 5 '+str(self.ip)
stdin, stdout, stderr = client.exec_command(ping_command)
for line in stdout.readlines():
print line
try:
with open(fname,'ab') as text_file:
text_file.wirte(stdout)
text_file.close()
except IOError:
pass
client.close()
I also tried to store stdout into a variable and then write that variable into the file and didn't get any results. I also found some topics in the site about Paramiko output, and none of them helped.

Related

django project does not write to file and there is no error, the file does not appear

I'm trying to write to a file and django doesn't do it. There is no error of any kind but the file does not appear. Using the process monitor I don't see any attempt to write.
In a python file the same code works fine.
Test performed:
#method_decorator(login_required, name='dispatch')
class TestWrite(TemplateView):
template_name = 'test.html'
with open(r'd:\djangotest.txt', "w") as fo:
fo.write('test')
fo.close()
I did the test with Popen and it doesn't work either.
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
stdout, stderr = p.communicate()
returncode = p.returncode
In the case of Popen I used pg_dump.exe and in stderr I got the result of the program running correctly but no file anywhere.
It doesn't matter which path you select to write, inside the project, outside of it, ect. the file does not appear.
I don't know if it's important, but I did the tests in pycharm.

Rsyslog, omprog, and python

I have an issue with Rsyslog's 'omprog' module when trying to get it to interact with my python (2.7) code. Rsyslog is supposed to send desired messages to python's stdin, yet it does not receive anything. I wonder if anyone else has had better success with this output module?
Rsyslog.conf
module(load="omprog")
template(name="sshmsg" type="string" string="%msg%")
if ($programname == "myprogram") then {
action(type="omprog"
binary="/usr/sshtrack.py"
template="sshmsg")
}
If I replace the binary with a test shell script containing a line below, it works
test.sh
!#/bin/sh
cat /dev/stdin >> /var/log/ssh2.log
I also tried reading stdin in the shell script into a variable using
var="$(</dev/stdin)"
and
var="$(cat /dev/stdin)"
Neither of the above resulted var containing anything
Finally, when trying to read stdin from python script, I get nothing. Sometimes, it says resource unavailable (errno 11) error message.
sshtrack.py
#!/usr/bin/python
import sys
f = open("/var/log/ssh2.log", "a", 0)
while True:
f.write("Starting\n")
for line in sys.stdin:
f.flush()
msg = line.strip()
if not msg:
break
f.write(msg)
f.write("\n")
f.close()
The issue seems similar to can not read correctly from STDIN except adding a non-block flag did nothing.
I notice that your template sshmsg doesn't end with a newline. Try changing it to string="%msg%\n". Though it won't matter to rsyslog, Python will not be able to give you the data until it sees a newline.
Then it should work, but you probably not see any output from your python as it is buffered. Try adding an f.flush() after the last write in the loop, or opening the file unbuffered.
omprog will keep the pipe open, sending multiple lines until your program exits.
Note, not all shells might understand $() syntax.
In case of your shell script you can use read to read into a variable.
#!/bin/bash
# This will read until \n
read log
echo $log
The python source code (tested with python 3.8.2) can be adjusted to:
#!/usr/bin/env python3
import sys
# Changed from unbuffered to buffered as unbuffered is only possible in binary mode Ref (1):
f = open("/var/log/ssh2.log", "a", 1)
while True:
f.write("Starting\n")
for line in sys.stdin:
f.flush()
msg = line.strip()
if not msg:
break
f.write(msg)
f.write("\n")
f.close()
In case you want to have the output of you executed script (debugging) you can adjust the settings in Rsyslog.conf with the output option
module(load="omprog")
template(name="sshmsg" type="string" string="%msg%")
if ($programname == "myprogram") then {
action(type="omprog"
binary="/usr/sshtrack.py"
output="/var/log/sshtrack.log"
template="sshmsg")
}
Ref (1): https://stackoverflow.com/a/45263101/13108341

How to capture output without preventing it from output in python

I want to run command line in python, and capture the output. I can use subprocess.check_output. But it will suppress the output, how can i do it without suppressing the console output?
How about this?
from subprocess import Popen, PIPE
proc = Popen(["/usr/bin/nc", "-l", "9999"], stdout=PIPE)
buffer = []
line = proc.stdout.readline()
while line:
buffer.append(line)
print "LINE", line.strip()
line = proc.stdout.readline()
print "buffer", ''.join(buffer)
Using another terminal send some text
nc localhost 9999
# type something. the text should appear from the python code
Break the nc, and you get the output in buffer as well

How to get ping output from cmd shell in python without stop the script

Recently I spent a few hours to find How can I get output while this script running
ping = subprocess.check_output(["start", "cmd.exe", "/k", "ping", "-t", SomeIP], shell=True)
All the answers I've found in the internet proposed to use communicte(), subprocess.call and other unusable commands because all of this command forcing me to stop the script.
Please help me :)
My python is 2.7
Another solution is saving the results of the ping to a file then reading from it...
import subprocess, threading
class Ping(object):
def __init__(self, host):
self.host = host
def ping(self):
subprocess.call("ping %s > ping.txt" % self.host, shell = True)
def getping(self):
pingfile = open("ping.txt", "r")
pingresults = pingfile.read()
return pingresults
def main(host):
ping = Ping(host)
ping.ping()
#startthread(ping.ping) if you want to execute code while pinging.
print("Ping is " + ping.getping())
def startthread(method):
threading.Thread(target = method).start()
main("127.0.0.1")
Basically, I just execute the cmd ping command and in the cmd ping command I used the > ping.txt to save the results to a file. Then you just read from the file and you have the ping details. Notice, you can start a thread if you want to execute ping while executing your own code.

Failed ping request in Python script

I have a python script that want to ping a few (quite a few!) hosts. I have set this up to read the contents of a hosts.txt file as the hosts to ping in the script. The odd thing is that I am recieving the following error, for the first few addresses (no matter what they are):
Ping request could not find host 66.211.181.182. Please check the name and try again.
I have included the address shown above at twice (within the file) and it attempts a ping. Any thoughts on what I am doing wrong - I am a python newbie, so be gentle.
Here is my script:
import subprocess
hosts_file = open("hosts.txt","r")
lines = hosts_file.readlines()
for line in lines:
ping = subprocess.Popen(
["ping", "-n", "1",line],
stdout = subprocess.PIPE,
stderr = subprocess.PIPE
)
out, error = ping.communicate()
print out
print error
hosts_file.close()
Here is my hosts.txt file:
66.211.181.182
178.236.5.39
173.194.67.94
66.211.181.182
And here are the results from the above test:
Ping request could not find host 66.211.181.182
. Please check the name and try again.
Ping request could not find host 178.236.5.39
. Please check the name and try again.
Ping request could not find host 173.194.67.94
. Please check the name and try again.
Pinging 66.211.181.182 with 32 bytes of data:
Request timed out.
Ping statistics for 66.211.181.182:
Packets: Sent = 1, Received = 0, Lost = 1 (100% loss)
Looks like the line variable contains a linebreak at the end (except for the last line of the file). From the Python tutorial:
f.readline() reads a single line from the file; a newline character (\n) is left at the end of the string, and is only omitted on the last line of the file if the file doesn’t end in a newline.
You need to strip the \n before calling Popen: How can I remove (chomp) a newline in Python?
Few comments:
Using readlines() is highly not recommended as it will load the entire file into memory.
I suggest using Generator in order to perform rstrip on each line and then pinging the server.
No need to use file.close - you can use with statement that does it for you
Your code should look like this:
import subprocess
def PingHostName(hostname):
ping=subprocess.Popen(["ping","-n","1",hostname],stdout=subprocess.PIPE
,stderr=subprocess.PIPE)
out,err=ping.communicate();
print out
if err is not None: print err
with open('C:\\myfile.txt') as f:
striped_lines=(line.rstrip() for line in f)
for x in striped_lines: PingHostName(x)