0

I am struggling for the past couple of days to figure out why is paramiko sending \x07 instead of tab to remote session. I am using paramikos invoke_shell because i need to run several interconnected commands. Everything works except for this part:

check_export = f'echo -e \"this\tis\tjust a test\" > /tmp/export'

This is simplified version, the only important part is that i need to have words delimited by a tab (in certain places only). print returns correct form:

echo -e "this   is      just a test" > /tmp/export

but when i check the recv() from paramiko session i see this:

b'echo -e "this\x07is\x07just a test" > /tmp/export\r\n[root@server~]# '

and as a result the file /tmp/export does not contain tabs and those first 3 words are jammed together. I have tried providing literal tab, \t, U00000009, nothing works.
I also tried doing .encode() on the string, but i get error that bytes are expected, not string.

What am i missing here? I would appreciate some input. Thanks

boz noz
  • 25
  • 5
  • The `b'...'` part shows that you are looking at a `bytearray`, not a string. If you `.decode()` it into a string, there will be some ASCII control character. Though ASCII 7 is a bell, not a tab... – tevemadar Oct 31 '22 at 11:28
  • 1
    Don't use `echo -e` anyway. Does `printf '"this\tis\tjust a test"\n'` work better? – tripleee Oct 31 '22 at 11:34
  • Ok, so my question is wrong in that case. Using decode() indeed "removes" the \x07 from the output, but the tabs are still not pushed to the final /tmp/export file. I am going to edit my question. – boz noz Oct 31 '22 at 11:36

1 Answers1

5

That's all probably a side effect of you abusing an interactive shell for command automation. What happens if you type echo -e "this in the shell and then you press Tab key? The shell will try to expand this to a filename and beep (ASCII 7), if no such file is found. That's what your code does. It's not Paramiko seconding ASCII 7 (bell) to the server. It's the server responding with bell to you sending the Tab key.

Don't use an interactive shell for command automation. See
Execute multiple commands in Paramiko so that commands are affected by their predecessors


Or if you want to stick to your (imo wrong) approach, send literal \ t sequence to the remote shell (what I assume you actually meant to do, based on the -e) by escaping the backslash: \\t

check_export = f'echo -e \"this\\tis\\tjust a test\" > /tmp/export'

Btw, no need to f'...' here. Or maybe you have meant to use r'...'?

check_export = r'echo -e \"this\tis\tjust a test\" > /tmp/export'

See https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
  • Thanks Martin, should have realized this on my own now when i think about it.. What i still dont understand is why i shouldnt use interactive shell for command automation. Isnt the whole purpose of paramiko to help automate? I thought thats the main difference in usage between exec_command() and invoke_shell() – boz noz Oct 31 '22 at 11:46
  • I do not understand *what* did you thought is the main difference in usage between exec_command() and invoke_shell(). Anyway, see [What is the difference between exec_command and send with invoke_shell() on Paramiko?](https://stackoverflow.com/q/55762006/850848) – Martin Prikryl Oct 31 '22 at 12:59
  • Apologies if i name it wrong, but for me the difference is that exec_command() opens and closes its channel immediately after cmd exec, while invoke_shell keeps the channel open until you manually close it, allowing you to chain more complex commands. You still havent explained why you shouldnt use interactive shell for cmd automation. What else would you use it for, then? – boz noz Oct 31 '22 at 13:33
  • No, that's not the difference. The difference is that `exec_command` is **API for executing commands**, while `invoke_shell` is API for implementing an interactive shell. And I've explained that above by *posting a link*. Did you follow it? – Martin Prikryl Oct 31 '22 at 15:07
  • Thats one of the differences, not the only one. Yes i have followed your link but sadly there is no sufficient information or explanation to your statement. The link just follows to another of your posts where you explain how to execute multiple commands over command_exec. Nowhere it states WHY you should stay away from using invoke_shell. Im not trying to start an argument, im trying to understand your point. – boz noz Oct 31 '22 at 16:39
  • That's the primary difference. + My answer says *"The purpose of the shell channel is to implement an interactive shell session. So basically it's legitimate use is an implementation of an SSH terminal client."* Are you implementing *"an SSH terminal client"*? – Martin Prikryl Oct 31 '22 at 20:55