0

I'm using Python's telnetlib.write() function for quite some time without issues, but in this case the command that I want to send does nothing. While the same command sent through SecureCRT works fine.

Here's more or less what I have:

import telnetlib

tn = telnetlib.Telnet(HOST)

tn.read_until('login: ')
tn.write(user + '\n')

if pswrd:
    tn.read_until('Password: ')
    tn.write(pswrd + '\n')

tn.write('echo "" > /path/to/file.log' + '\n')

tn.write('exit\n')
tn.close()

What this should do is clear the contents of file.log, but the file remains the same. Why is this happening? If it's worth mentioning, the telnet server is running SunOS. Thanks!

leshurex
  • 23
  • 1
  • 5
  • Well, what's actually going back and forth over the telnet session? Have you tried [`set_debuglevel`](https://docs.python.org/3/library/telnetlib.html#telnetlib.Telnet.set_debuglevel) to see? – abarnert May 17 '15 at 19:59
  • Also, what makes you think it's the `write()` function that's not working, as opposed to, say, the `write` working perfectly and executing an `echo` command that fails with a permissions error or something? Or failing to log in, so you're not even talking to the shell? (For example, on many platforms, the `Password:` prompt doesn't have a space after the colon; using sample code that happened to work on one machine without even testing it to see if it works on your machine isn't a very good idea.) – abarnert May 17 '15 at 20:02
  • @abarnert Well, the code showed in my question is a simplified example, because there's a lot more going on in my script. So, I know that everything else is working, perhaps I should've started explaining that. If the problem is a matter of permissions it shouldn't have worked with SecureCRT, I believe. -- By other hand, I tried tn.set_debuglevel(1) and now is working, if I comment that line it doesn't work anymore. Don't know why, but it appears that the issue resolves that way. – leshurex May 17 '15 at 20:24
  • A simplified example is good, but not if it's so simplified that it doesn't actually reproduce the problem. (If you show us working code, we can't tell you what's wrong with it.) Please read [minimal, complete, verifiable example](http://stackoverflow.com/help/mcve). – abarnert May 17 '15 at 20:25
  • perhaps you should wait until a prompt `#|>|$`before you keep doing `tn.write()`.Smells like a timing issue – cmidi May 17 '15 at 20:26
  • 2
    Meanwhile, if just adding `tn.set_debuglevel` makes a difference, you've most likely got some kind of timing issue. Maybe SunOS's `telnetd` is only buffering, say, 16 characters for the shell, so if you `write` a command without waiting for the shell to start it gets truncated, but writing debug info just happens to slow things down just enough that often the shell will have started in time and can read your whole command, so things now work 98% of the time instead of 2% of the time. – abarnert May 17 '15 at 20:28
  • telnetlib lets you write a expect like script with the `expect` method so it would be better if you do something like `tn.write(command+"\n")` and follow it by `tn.expect([prompt],timeout=3)` – cmidi May 17 '15 at 20:31
  • @abarnert @cmidi That appears to be the source of the problem. I've no problem leaving the `tn.set_debuglevel` the way it is, but what would be the most elegant way to address that? – leshurex May 17 '15 at 20:37
  • As cmidi said, you do it by waiting for the expected prompt, with `read_until` (if it's a simple string) or `expect` (if it's a list of possibilities or a regular expression). You're already doing that for `Password`, just do it again for the prompt. – abarnert May 17 '15 at 20:39
  • @abarnert @cmidi With `read_until` the prompt appears it solves the issue. Many thanks! – leshurex May 17 '15 at 20:48

1 Answers1

0

Your problem is almost certainly a timing error.

Without being able to debug it, or seeing the results of you debugging it, it's hard to be sure exactly what the problem is, but my guess is something like this:

The SunOS machine's telnetd server has a relatively small buffer, say 16 bytes. So, if you send it that whole command before the shell has started, it's only going to send 16 bytes of it to the shell. Which will, of course, not do what you want. But if you wait until the shell has started, it'll get the whole command, and therefore work.

By adding tn_setdebuglevel(1) to your program, you're changing the timing—the extra time it takes to print out the debugging information is just enough to (usually) give the shell time to start before you've filled up the buffer, so it happens to work.

The password prompt probably has the same problem, which you solved by using `tn.read_until('Password: '). You just need to do the same thing here. For example (depending on what the expected prompt is):

# ...
tn.read_until('$')
tn.write('echo "" > /path/to/file.log\n')
tn.read_until('$')
tn.write('exit\n')
tn.close()
abarnert
  • 354,177
  • 51
  • 601
  • 671