Writing telnetlib's Telnet.interact() stream to file - python

I need to establish a connection to a telnet server which continually broadcasts information and save all of that information to a file. For testing, I am using the famous ASCII Star Wars located on towel.blinkenlights.nl
In essence, I need to replicate in Python what you get when inputting the following command into Windows Command Prompt: telnet towel.blinkenlights.nl /f c:/randfolder/output.txt
The below does establish the connection and is showing the data received in terminal, however I am having no luck in saving what I see in the terminal to a file:
import telnetlib
HOST = "towel.blinkenlights.nl"
PORT = "23"
telnetObj=telnetlib.Telnet(HOST,PORT)
outF = open("output.txt", "a")
outF.write(telnetObj.interact())
telnetObj.close()

While this seems to me to be a rather hacky solution, using stdout does output the telnet stream to a file as required. Running this creates and appends a file containg all of the data received until interrupted
import sys
import telnetlib
with open('output.txt', 'w') as output:
sys.stdout = output # this is where the magic happens
HOST = "towel.blinkenlights.nl"
PORT = "23"
telnetObj=telnetlib.Telnet(HOST,PORT)
outF = open("output.txt", "a")
outF.write(telnetObj.interact())
telnetObj.close()
Would not be surprised however, if incorrect handling of this approach caused mess in program that this is part of. I'm thinking running it as a separate process could be reasonably safe.

Related

can I redirect the output of this program to script?

I'm running a binary that manages a usb device. The binary file, when executed outputs results to a file I specify.
Is there any way in python the redirect the output of a binary to my script instead of to a file? I'm just going to have to open the file and get it as soon as this line of code runs.
def rn_to_file(comport=3, filename='test.bin', amount=128):
os.system('capture.exe {0} {1} {2}'.format(comport, filename, amount))
it doesn't work with subprocess either
from subprocess import check_output as qx
>>> cmd = r'C:\repos\capture.exe 3 text.txt 128'
>>> output = qx(cmd)
Opening serial port \\.\COM3...OK
Closing serial port...OK
>>> output
b'TrueRNG Serial Port Capture Tool v1.2\r\n\r\nCapturing 128 bytes of data...Done'
The actual content of the file is a series of 0 and 1. This isn't redirecting the output to the file to me, instead it just prints out what would be printed out anyway as output.
It looks like you're using Windows, which has a special reserved filename CON which means to use the console (the analog on *nix would be /dev/stdout).
So try this:
subprocess.check_output(r'C:\repos\capture.exe 3 CON 128')
You might need to use shell=True in there, but I suspect you don't.
The idea is to make the program write to the virtual file CON which is actually stdout, then have Python capture that.
An alternative would be CreateNamedPipe(), which will let you create your own filename and read from it, without having an actual file on disk. For more on that, see: createNamedPipe in python

Python: Save output files on another computer through ssh

I want to save output files (binary, matplotlib, etc.) of a Python program in a different computer over ssh. So far, I have saved files in the same computer that runs the program and to do that I have a line in my Python code filename = '/OutputFiles/myOutput.txt'. How do I change this line so that I can save the output in a different computer through ssh? It can be assumed that the ssh login password for the remote computer is in my keyring.
(New answer because OP specified they wanted to write multiple files)
You want to look into the paramiko module. It might look something like this:
import paramiko
connection = paramiko.SSHClient()
connection.set_missing_host_key_policy(paramiko.AutoAddPolicy())
connection.connect(10.10.10.10, username=myuser, password=mypass)
ftp = connection.open_sftp()
for i in range(10):
results = do_stuff()
f = ftp.open(i+'.txt', 'w+')
f.write(results)
f.close()
ftp.close()
connection.close()
The easiest way to do this would be to write your output to standard out and pipe it to ssh (assuming you're on a Mac, Linux, or other *nix-based machine). For example:
python myProgram | ssh user#host 'cat > outfile.txt'

Logging ping results python?

I can use the ping command and save the output using the following line:
command = os.system('ping 127.0.0.1 > new.txt')
However each time the script is run the text file is overwritten so I only have the last ping saved. I have looked into logging but cannot find a way to save the outputs of the ping requests into a text file without over writing.
I have tried:
logging.debug(command = os.system('ping 127.0.0.1'))
But this throws up an error with: debug() takes at least 1 argument (0 given)
Any help would be appreciated, thanks!
You could get result of subprocess.check_output and write it to a file:
import subprocess
result = subprocess.check_output(['ping', '127.0.0.1'])
with open("new.txt", "a") as myfile:
myfile.write(result)
If you insist on using os.system, then simply use >> redirection:
command = os.system('ping 127.0.0.1 >> new.txt')
This would append new data to new.txt instead of overwriting it.
Another solution is to use subprocess module and manage file handler manually. This has the advantage of skipping the shell (it's faster and in some cases safer):
import subprocess
out = open('new.txt', 'a')
subprocess.call(['ping', '127.0.0.1'], stdout = out)
out.close()
Notice that you can do something else with stdout. For example, save it to string.

Permission Denied sometimes when downloading executable file

So I'm writing a script to download a file and restart the download from where it left off if it doesn't complete. That part's taken care of.
I took out all of those parts out to show just the part that doesn't work. The amazon url here I just made up, so it won't actually download anything if you run this, but replacing the url with an actual download link, would:
import urllib
import time
import os
file_name = "setup.exe"
web_page = urllib.FancyURLopener().open("https://s3.amazonaws.com/some_bucket/files/"+file_name)
while True:
data = web_page.read(8192)
if not data:
print "done"
break
#print os.getcwd()
with open(file_name, "ab") as outputFile:
outputFile.write(data)
#print "going..."
#time.sleep(1)
What happens is (and this is ONLY when trying to download EXE files), The process will read from web_page a seemingly random number of times (between 1 and 20ish), then throws an IOError: 13, Permission denied. Again, with a .gif or .mov, or a few other things I've tested, the permission denied error is never thrown.
Additionally, uncommenting the time.sleep(1) line resolves the issue. It's as though the with statement doesn't fully close the file before continuing.
I thought the with statement was supposed to handle the close, no?
I also thought that perhaps SOMEHOW my current directory was being changed, but uncommenting that never reveals it (though by the same logic it wouldn't necessarily have to).
(What's also weird is that if I run this script from the desktop [so that it also writes to the desktop] with Aptana opened in front of it, the permission denied error won't occur, yet the second I minimize the text editor to focus the desktop, the error is thrown -- I attribute this to Aptana taking up a lot of resources while it's opened, therefore slowing down the other process and being kind of like a time.sleep??)
Thanks very much for any pointers.
I don't understand why you're going to the trouble to re-open and close the file for each network read. As Pavel suggests, this might give a virus scanner a chance to open (and lock?) the file to scan it. Why not just open it once, do all your I/O, then close it? (I suppose it may have something to do with the code you omitted.)
Instead of:
while True:
data = web_page.read(8192)
if not data:
print "done"
break
with open(file_name, "ab") as outputFile:
outputFile.write(data)
Try:
with open(file_name, "ab") as outputFile:
while True:
data = web_page.read(8192)
if not data:
print "done"
break
outputFile.write(data)

can you print a file from python?

Is there some way of sending output to the printer instead of the screen in Python? Or is there a service routine that can be called from within python to print a file? Maybe there is a module I can import that allows me to do this?
Most platforms—including Windows—have special file objects that represent the printer, and let you print text by just writing that text to the file.
On Windows, the special file objects have names like LPT1:, LPT2:, COM1:, etc. You will need to know which one your printer is connected to (or ask the user in some way).
It's possible that your printer is not connected to any such special file, in which case you'll need to fire up the Control Panel and configure it properly. (For remote printers, this may even require setting up a "virtual port".)
At any rate, writing to LPT1: or COM1: is exactly the same as writing to any other file. For example:
with open('LPT1:', 'w') as lpt:
lpt.write(mytext)
Or:
lpt = open('LPT1:', 'w')
print >>lpt, mytext
print >>lpt, moretext
close(lpt)
And so on.
If you've already got the text to print in a file, you can print it like this:
with open(path, 'r') as f, open('LPT1:', 'w') as lpt:
while True:
buf = f.read()
if not buf: break
lpt.write(buf)
Or, more simply (untested, because I don't have a Windows box here), this should work:
import shutil
with open(path, 'r') as f, open('LPT1:', 'w') as lpt:
shutil.copyfileobj(f, lpt)
It's possible that just shutil.copyfile(path, 'LPT1:'), but the documentation says "Special files such as character or block devices and pipes cannot be copied with this function", so I think it's safer to use copyfileobj.
Python doesn't (unless you're using graphical libraries) ever send stuff to "The screen". It writes to stdout and stderr, which are, as far as Python is concerned, just things that look like files.
It's simple enough to have python direct those streams to anything else that looks like a file; for instance, see Redirect stdout to a file in Python?
On unix systems, there are file-like devices that happen to be printers (/dev/lp*); on windows, LPT1 serves a similar purpose.
Regardless of the OS, you'll have to make sure that LPT1 or /dev/lp* are actually hooked up to a printer somehow.
If you are on linux, the following works if you have your printer setup and set as your default.
from subprocess import Popen
from cStringIO import StringIO
# place the output in a file like object
sio = StringIO(output_string)
# call the system's lpr command
p = Popen(["lpr"], stdin=sio, shell=True)
output = p.communicate()[0]

Categories

Resources